def createOrder(self, member_id, items=None, params=None): resp = {'code': 200, 'msg': '操作成功~', 'data': {}} pay_price = decimal.Decimal(0.00) continue_cnt = 0 food_ids = [] for item in items: if decimal.Decimal(item['price']) < 0: continue_cnt += 1 continue pay_price = pay_price + decimal.Decimal(item['price']) * int( item['number']) food_ids.append(item['id']) if continue_cnt >= len(items): resp['code'] = -1 resp['msg'] = '商品items为空~~' return resp yun_price = params[ 'yun_price'] if params and 'yun_price' in params else 0 note = params['note'] if params and 'note' in params else '' express_address_id = params[ 'express_address_id'] if params and 'express_address_id' in params else 0 express_info = params[ 'express_info'] if params and 'express_info' in params else {} yun_price = decimal.Decimal(yun_price) total_price = pay_price + yun_price try: # 为了防止并发库存出问题了,使用行锁select for update(悲观锁 ) tmp_food_list = db.session.query( Food ).filter( Food.id.in_( food_ids ) )\ .with_for_update().all() tmp_food_stock_mapping = {} for tmp_item in tmp_food_list: tmp_food_stock_mapping[tmp_item.id] = tmp_item.stock model_pay_order = PayOrder() model_pay_order.order_sn = self.geneOrderSn() model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.yun_price = yun_price model_pay_order.pay_price = pay_price model_pay_order.note = note model_pay_order.status = -8 model_pay_order.express_status = -8 model_pay_order.express_address_id = express_address_id model_pay_order.express_info = json.dumps(express_info) model_pay_order.updated_time = model_pay_order.created_time = getCurrentDate( ) db.session.add(model_pay_order) db.session.flush() for item in items: tmp_left_stock = tmp_food_stock_mapping[item['id']] if decimal.Decimal(item['price']) < 0: continue if int(item['number']) > int(tmp_left_stock): raise Exception("您购买的这美食太火爆了,剩余:%s,你购买%s~~" % (tmp_left_stock, item['number'])) tmp_ret = Food.query.filter_by(id=item['id']).update( {"stock": int(tmp_left_stock) - int(item['number'])}) if not tmp_ret: raise Exception("下单失败请重新下单") tmp_pay_item = PayOrderItem() tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item['number'] tmp_pay_item.price = item['price'] tmp_pay_item.food_id = item['id'] tmp_pay_item.note = note tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate( ) db.session.add(tmp_pay_item) #db.session.flush() FoodService.setStockChangeLog(item['id'], -item['number'], "在线购买") db.session.commit() resp['data'] = { 'id': model_pay_order.id, 'order_sn': model_pay_order.order_sn, 'total_price': str(total_price) } except Exception as e: db.session.rollback() print(e) resp['code'] = -1 resp['msg'] = "下单失败请重新下单" resp['msg'] = str(e) return resp return resp
def createOrder(self, member_id=0, items=None, params=None): resp = {'code': 200, 'msg': '操作成功', 'data': {}} pay_price = decimal.Decimal(0.00) continue_count = 0 food_ids = [] for item in items: if decimal.Decimal(item['price']) < 0: continue_count += 1 continue pay_price += decimal.Decimal(item['price']) * item['number'] food_ids.append(item['id']) if continue_count >= len(items): resp['code'] = -1 resp['msg'] = '部分或全部商品的价格有误' return resp yun_price = params[ 'yun_price'] if params and 'yun_price' in params else 0 note = params['note'] if params and 'note' in params else '' yun_price = decimal.Decimal(yun_price) total_price = pay_price + yun_price try: tmp_food_list = db.session.query(Food).filter( Food.id.in_(food_ids)).with_for_update().all() tmp_food_stock_mapping = {} for tmp_item in tmp_food_list: tmp_food_stock_mapping[tmp_item.id] = tmp_item.stock model_pay_order = PayOrder() model_pay_order.order_sn = self.geneOrderSn() model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.yun_price = yun_price model_pay_order.pay_price = pay_price model_pay_order.note = note model_pay_order.status = -8 model_pay_order.express_status = -8 model_pay_order.updated_time = getCurrentDate() db.session.add(model_pay_order) for item in items: tmp_left_stock = tmp_food_stock_mapping[item['id']] if decimal.Decimal(item['price']) < 0: continue if int(item['number']) > int(tmp_left_stock): raise Exception('你购买的这款美食太火爆了,剩余:%s,您购买:%s' % (tmp_left_stock, item['number'])) tmp_ret = Food.query.filter_by(id=item['id']).update( {'stock': tmp_left_stock - item['number']}) if not tmp_ret: raise Exception('下单失败,请重新下单') tmp_pay_item = PayOrderItem() tmp_pay_item.member_id = member_id tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.quantity = item['number'] tmp_pay_item.price = item['price'] tmp_pay_item.food_id = item['id'] tmp_pay_item.note = note tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate( ) db.session.add(tmp_pay_item) # db.session.flush() FoodService.setFoodStockChangeLog(item['id'], -item['number'], '在线购买') db.session.commit() resp['data'] = { 'id': model_pay_order.id, 'order_sn': model_pay_order.order_sn, 'total_price': str(total_price) } except Exception as e: print('错误' + str(e)) db.session.rollback() resp['code'] = -1 resp['msg'] = '下单失败,请重新下单, 原因:' + str(e) return resp return resp
def createOrder(self, member_id, items=None, params=None): resp = {"code": 200, "msg": "操作成功~", "data": {}} pay_price = decimal.Decimal(0.00) continue_cnt = 0 foods_id = [] for item in items: if decimal.Decimal(item["price"]) < 0: continue_cnt += 1 continue pay_price = pay_price + decimal.Decimal(item["price"]) * int( item["number"]) foods_id.append(item["id"]) if continue_cnt >= len(items): resp["code"] = -1 resp["msg"] = "商品 items 为空" return resp yun_price = params[ "yun_price"] if params and "yun_price" in params else 0 note = params["note"] if params and "note" in params else 0 yun_price = decimal.Decimal(yun_price) total_price = pay_price + yun_price try: tmp_food_list = db.session.query(Food).filter( Food.id.in_(foods_id)).with_for_update().all() tmp_food_stock_mapping = {} for tmp_item in tmp_food_list: tmp_food_stock_mapping[tmp_item.id] = tmp_item.stock model_pay_order = PayOrder() model_pay_order.order_sn = self.geneOrderSn() model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.yun_price = yun_price model_pay_order.pay_price = pay_price model_pay_order.note = note model_pay_order.status = -8 model_pay_order.express_status = -8 model_pay_order.updated_time = model_pay_order.created_time = getCurrentDate( ) db.session.add(model_pay_order) for item in items: tmp_left_stock = tmp_food_stock_mapping[item["id"]] if decimal.Decimal(item["price"]) < 0: continue if int(item["number"]) > int(tmp_left_stock): raise Exception("您购买的美食太火爆了,剩余:%s,您购买:%s" % (tmp_left_stock, item["number"])) tmp_ret = Food.query.filter_by(id=item["id"]).update( {"stock": int(tmp_left_stock) - int(item["number"])}) if not tmp_ret: raise Exception("下单失败请重新下单") tmp_pay_item = PayOrderItem() tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item["number"] tmp_pay_item.price = item["price"] tmp_pay_item.food_id = item["id"] tmp_pay_item.note = note tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate( ) db.session.add(tmp_pay_item) FoodService.setStockChangeLog(item["id"], -item["number"], "在线购买") db.session.commit() resp["data"] = { "id": model_pay_order.id, "order_sn": model_pay_order.order_sn, "total_price": str(total_price) } except Exception as e: db.session.rollback() print(e) resp["code"] = -1 resp["msg"] = str(e) return resp return resp
def createOrder(self, member_id, items =None, params=None): resp = {'code': 200, 'msg': "操作成功", 'data': {}} pay_price = decimal.Decimal(0.00) continue_count = 0 foods_id = [] for item in items: if decimal.Decimal(item['price']) < 0: continue_count+=1 continue pay_price = pay_price + decimal.Decimal(item['price']) * int(item['number']) foods_id.append(item['id']) if continue_count >= len(items): resp['code'] = -1 resp['msg'] = "商品为空" return resp yun_price = params['yun_price'] if 'yun_price' in params else 0 note = params['note'] if 'note' in params else 0 express_address_id = params['express_address_id'] if params and 'express_address_id' in params else 0 express_info = params['express_info'] if params and 'express_info' in params else {} yun_price = decimal.Decimal(yun_price) total_price = yun_price + pay_price # 并发处理 try: # 开启事务 tmp_food_list = db.session.query(Food).filter(Food.id.in_(foods_id)).with_for_update().all() tmp_food_stock_mapping = {} for tmp_item in tmp_food_list: tmp_food_stock_mapping[tmp_item.id] = tmp_item.stock #支付订单 model_pay_order = PayOrder() model_pay_order.member_id = member_id model_pay_order.order_sn = self.geneOrderSn() model_pay_order.total_price = total_price model_pay_order.yun_price = yun_price model_pay_order.pay_price = pay_price model_pay_order.note = note model_pay_order.status = -8 model_pay_order.express_status = -8 model_pay_order.express_address_id = express_address_id model_pay_order.express_info = json.dumps(express_info) model_pay_order.updated_time = model_pay_order.created_time = getCurrentDate() db.session.add(model_pay_order) for item in items: tmp_left_stock = tmp_food_stock_mapping[item['id']] if decimal.Decimal(item['price']) < 0: continue if int(item['number']) > int(tmp_left_stock): raise Exception("该商品剩余: %s"% (tmp_left_stock)) tmp_ret = Food.query.filter_by(id= item['id']).update({ 'stock':int(tmp_left_stock) - int(item['number']) }) if not tmp_ret: raise Exception("下单失败") tmp_pay_item = PayOrderItem() tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item['number'] tmp_pay_item.price = item['price'] tmp_pay_item.food_id = item['id'] tmp_pay_item.note = note tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate() FoodService.setStockChangeLog(item['id'], -item['number'], "online") db.session.add(tmp_pay_item) # 提交事务 db.session.commit() resp['data'] = { 'id': model_pay_order.id, 'order_sn': model_pay_order.order_sn, 'total_price': str(model_pay_order.total_price) } except Exception as e: db.session.rollback() print(e) resp['code'] = -1 resp['msg'] = "下单失败请重新下单" resp['msg'] = str(e) return resp
def createOrder(self, member_id, items=None, params=None): # 创建订单(哪个用户,商品列表,params额外字段[留言] ) """ 实现下单并发,库存减少 :param member_id: :param items: :param params: :return: """ resp = {'code': 200, 'msg': '操作成功~', 'data': {}} pay_price = decimal.Decimal(0.00) # 商品总价格 continue_cnt = 0 food_ids = [] for item in items: # 遍历所有下单的商品 if decimal.Decimal(item['price']) < 0: # 如果有的商品价格<0。那么统计次数,并且跳过 continue_cnt += 1 continue pay_price = pay_price + decimal.Decimal(item['price']) * int( item['number']) # 此时的,商品总价格。就是,初始价格0.00 + 上面跳过的商品价格 * 下单数量 food_ids.append(item['id']) # 在这里面添加,通过的商品的 id if continue_cnt >= len(items): # 如果跳过的次数 >= 下单商品的数量。说明没有选择商品 resp['code'] = -1 resp['msg'] = '商品items为空~~' return resp yun_price = params[ 'yun_price'] if params and 'yun_price' in params else 0 note = params['note'] if params and 'note' in params else '' express_address_id = params[ 'express_address_id'] if params and 'express_address_id' in params else 0 express_info = params[ 'express_info'] if params and 'express_info' in params else {} yun_price = decimal.Decimal(yun_price) total_price = pay_price + yun_price # 并发处理 乐观锁和悲观锁。这里采用的是观锁。(悲观锁:锁数据表行记录。乐观锁:数据表增加一个字段,每次更新时对它进行判断 ) try: # 为了防止并发库存出问题了,我们坐下selectfor update, 这里可以给大家演示下 tmp_food_list = db.session.query(Food).filter(Food.id.in_(food_ids)) \ .with_for_update().all() # 锁定所有本次下单的商品id,行记录 tmp_food_stock_mapping = {} # 临时的商品库存 map,方便对比 for tmp_item in tmp_food_list: tmp_food_stock_mapping[ tmp_item.id] = tmp_item.stock # 被锁定的商品 库存 model_pay_order = PayOrder() model_pay_order.order_sn = self.geneOrderSn() # 随机订单号,通过随机算法算出 model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.yun_price = yun_price model_pay_order.pay_price = pay_price model_pay_order.note = note # 备注信息 model_pay_order.status = -8 # 默认状态:-8待付款 model_pay_order.express_status = -8 # 待支付 model_pay_order.express_address_id = express_address_id model_pay_order.express_info = json.dumps(express_info) model_pay_order.updated_time = model_pay_order.created_time = getCurrentData( ) db.session.add(model_pay_order) db.session.flush() for item in items: # 第一次判断,剩下的商品(跳出的商品) tmp_left_stock = tmp_food_stock_mapping[item['id']] if decimal.Decimal(item['price']) < 0: # 如果是价格<=0,就停止本次操作,继续 continue if int(item['number']) > int(tmp_left_stock): # 如果下单的商品数量 > 库存 raise Exception("您购买的这美食太火爆了,剩余:%s,您购买%s~~" % (tmp_left_stock, item['number'])) tmp_ret = Food.query.filter_by(id=item['id']).update( {"stock": int(tmp_left_stock) - int(item['number'])}) # 更新库存 if not tmp_ret: raise Exception("下单失败请重新下单") tmp_pay_item = PayOrderItem() # 生成订单 tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item['number'] # 下单数量 tmp_pay_item.price = item['price'] # 商品单价 tmp_pay_item.food_id = item['id'] # 商品id tmp_pay_item.note = note # 备注信息 tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentData( ) db.session.add(tmp_pay_item) db.session.flush() FoodService.setStockChangeLog(item['id'], -item['number'], "在线购买") # 商品变更记录。商品id,-数量,备注 db.session.commit() # 直到完成本次提交,行锁才解开 resp['data'] = { # 下单成功,返回数据 'id': model_pay_order.id, 'order_sn': model_pay_order.order_sn, 'total_price': str(total_price) } except Exception as e: pass db.session.rollback() # 如果出现异常,数据回滚,回到操作前的状态 print("*" * 50, e) resp['code'] = -1 resp['msg'] = "下单失败请重新下单" resp['msg'] = str(e) return resp return resp
def createOrder(self, member_id, items=None, params=None): resp = {"code": 200, "msg": "添加成功", "data": {}} pay_price = decimal.Decimal(0.00) continue_count = 0 product_id = [] for item in items: if decimal.Decimal(item['price']) < 0: continue_count += 1 continue pay_price = pay_price + decimal.Decimal(item['price']) * int( item['number']) product_id.append(item['id']) if continue_count >= len(items): resp['code'] = -1 resp['msg'] = '商品为空' return resp note = params['note'] if 'params' and 'note' in params else '' total_price = pay_price # 并发控制, 悲观锁 try: tmp_product_list = db.session.query(Product).filter( Product.id.in_(product_id)).with_for_update().all() tmp_product_stock_mapping = {} for tmp_item in tmp_product_list: tmp_product_stock_mapping[tmp_item.id] = tmp_item.stock model_pay_order = PayOrder() # 提交给支付平台的凭证码, 不能重复 model_pay_order.order_sn = self.geneOrderSn() model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.pay_price = pay_price model_pay_order.note = note model_pay_order.status = -8 model_pay_order.updated_time = model_pay_order.created_time = getCurrentDate( ) db.session.add(model_pay_order) for item in items: tmp_left_stock = tmp_product_stock_mapping[item['id']] print(tmp_left_stock) print(item['number']) if decimal.Decimal(item['price']) < 0: continue if int(item['number']) > int(tmp_left_stock): raise Exception("库存不足") tmp_ret = Product.query.filter_by(id=item['id']).update( {'stock': int(tmp_left_stock) - int(item['number'])}) if not tmp_ret: raise Exception("下单失败") tmp_pay_item = PayOrderItem() tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item['number'] tmp_pay_item.price = item['price'] tmp_pay_item.product_id = item['id'] tmp_pay_item.note = note tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate( ) db.session.add(tmp_pay_item) ProductService.setStockChangeLog(item['id'], -item['number'], 'Online Sale') db.session.commit() resp['data'] = { 'id': model_pay_order.id, 'order_sn': model_pay_order.order_sn, 'total_price': str(total_price) } except Exception as e: db.session.rollback() print(e) resp['code'] = -1 resp['msg'] = '下单失败' resp['err_msg'] = str(e) return resp
def createOrder(self, member_id, items=None, params=None): resp = {'code': 200, 'msg': '操作成功', 'data': {}} pay_price = decimal.Decimal(0.00) continue_cnt = 0 foods_id = [] for item in items: if decimal.Decimal(item['price']) < 0: continue_cnt += 1 continue pay_price = pay_price + decimal.Decimal(item['price']) * int( item['number']) foods_id.append(item['id']) if continue_cnt >= len(items): # 说明没有选商品,商品的价格为空 resp['code'] = -1 resp['msg'] = '商品items为空' return resp yun_price = params[ 'yun_price'] if params and 'yun_price' in params else 0 note = params['note'] if params and 'note' in params else '' yun_price = decimal.Decimal(yun_price) total_price = yun_price + pay_price # 悲观锁 try: tmp_food_list = db.session.query(Food).filter( Food.id.in_(foods_id)).with_for_update().all() tmp_food_stock_mapping = {} for tmp_item in tmp_food_list: tmp_food_stock_mapping[tmp_item.id] = tmp_item.stock model_pay_order = PayOrder() model_pay_order.order_sn = self.geneOrderSn() model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.yun_price = yun_price model_pay_order.pay_price = pay_price model_pay_order.note = note model_pay_order.status = -8 model_pay_order.express_status = -8 model_pay_order.updated_time = model_pay_order.created_time = getCurrentDate( ) db.session.add(model_pay_order) for item in items: tmp_left_stock = tmp_food_stock_mapping[item['id']] if decimal.Decimal(item['price']) < 0: continue if int(item['number']) > int(tmp_left_stock): raise Exception("你购买的美食太火爆了,剩余:%s您购买:%s" % (tmp_left_stock, item['number'])) tmp_ret = Food.query.filter_by(id=item['id']).update( {"stock": int(tmp_left_stock) - int(item['number'])}) if not tmp_ret: raise Exception("下单失败请重新下单") tmp_pay_item = PayOrderItem() tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item['number'] tmp_pay_item.price = item['price'] tmp_pay_item.food_id = item['id'] tmp_pay_item.note = note tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate( ) db.session.add(tmp_pay_item) FoodService.setStockChangeLog(item['id'], -item['number'], "在线购买") db.session.commit() resp['data'] = { 'id': model_pay_order.id, 'order_sn': model_pay_order.order_sn, 'total_price': str(total_price) } except Exception as e: db.session.rollback() resp['code'] = -1 resp['msg'] = e return resp return resp
def createOrder(self, member_id, items=None, params=None): resp = {"code": 200, "msg": "操作成功", "data": {}} pay_price = decimal.Decimal(0.00) continue_cnt = 0 foods_id = [] for item in items: if decimal.Decimal(item['price']) < 0: continue_cnt += 1 continue pay_price = pay_price + decimal.Decimal(item['price']) * int( item['number']) foods_id.append(item['id']) if continue_cnt >= len(items): resp['code'] = -1 resp['msg'] = '商品items为空' return resp yun_price = params.get('yun_price', 0) note = params.get('note', '') yun_price = decimal.Decimal(yun_price) total_price = pay_price + yun_price try: # 锁 tmp_food_list = db.session.query(Food).filter( Food.id.in_(foods_id)).with_for_update().all() # 创建列表得到{food.id: 库存} tmp_food_stock_mapping = {} for tmp_item in tmp_food_list: tmp_food_stock_mapping[tmp_item.id] = tmp_item.stock model_pay_order = PayOrder() model_pay_order.order_sn = self.geneOrderSn() model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.yun_price = yun_price model_pay_order.pay_price = pay_price model_pay_order.note = note model_pay_order.status = -8 model_pay_order.express_status = -8 # model_pay_order.express_address_id = express_address_id # model_pay_order.express_info = json.dumps(express_info) model_pay_order.updated_time = model_pay_order.created_time = getCurrentData( ) db.session.add(model_pay_order) # db.session.flush() for item in items: tmp_left_stock = tmp_food_stock_mapping[item['id']] if decimal.Decimal(item['price']) < 0: continue # 库存不够 if int(item['number']) > int(tmp_left_stock): raise Exception("您购买的这美食太火爆了,剩余:%s,你购买%s~~" % (tmp_left_stock, item['number'])) # 库存减少 tmp_ret = Food.query.filter_by(id=item['id']).update( {"stock": int(tmp_left_stock) - int(item['number'])}) if not tmp_ret: raise Exception("下单失败请重新下单") tmp_pay_item = PayOrderItem() tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item['number'] tmp_pay_item.price = item['price'] tmp_pay_item.food_id = item['id'] tmp_pay_item.note = note tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentData( ) db.session.add(tmp_pay_item) # db.session.flush() # 修改库存 FoodService.setStockChangeLog(item['id'], -item['number'], "在线购买") db.session.commit() resp['data'] = { 'id': model_pay_order.id, 'order_sn': model_pay_order.order_sn, 'total_price': str(total_price) } except Exception as e: db.session.rollback() print(e) resp['code'] = -1 resp['msg'] = "下单失败请重新下单" resp['msg'] = str(e) return resp return resp
def createOrder(self, member_id, items=None, params=None): resp = {'code': 200, 'msg': '操作成功~', 'data': {}} # 这里面有下单并发的控制以及 库存的减少 pay_price = decimal.Decimal(0.00) # 无效商品跳过的次数 continue_cnt = 0 food_id = [] for item in items: if decimal.Decimal(item['price']) < 0: continue_cnt += 1 continue pay_price = pay_price + decimal.Decimal(item['price']) * int( item['number']) food_id.append(item['id']) if continue_cnt >= len(items): resp['code'] = -1 resp['msg'] = "商品items为空" return resp yun_price = params[ 'yun_price'] if params and 'yun_price' in params else 0 note = params['note'] if params and 'note' in params else '' yun_price = decimal.Decimal(yun_price) total_price = pay_price + yun_price # 并发处理 悲观锁 乐观锁 # 这里使用的是悲观锁 行锁 try: tem_food_list = db.session.query(Food).filter(Food.id.in_(food_id)) \ .with_for_update().all() tem_food_stock_mapping = {} for tem_item in tem_food_list: tem_food_stock_mapping[tem_item.id] = tem_item.stock # 订单主表 pay_order model_pay_order = PayOrder() model_pay_order.order_sn = self.geneOrder() model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.yun_price = yun_price model_pay_order.pay_price = pay_price model_pay_order.note = note model_pay_order.status = -8 # 未支付 model_pay_order.express_status = -8 model_pay_order.created_time = model_pay_order.updated_time = getCurrentDate( ) db.session.add(model_pay_order) # 订单从表 pay_order_item for item in items: tem_left_stock = tem_food_stock_mapping[item['id']] if decimal.Decimal(item['price']) < 0: continue if int(item['number']) > int(tem_left_stock): # 抛出异常 raise Exception("您购买的美食太火爆了,剩余%s,您购买%s" % (tem_left_stock, item['number'])) tmp_ret = Food.query.filter_by(id=item['id']).update({ "stock": int(tem_left_stock) - int(item['number']), "updated_time": getCurrentDate() }) if not tmp_ret: raise Exception("下单失败") tmp_pay_item = PayOrderItem() tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item['number'] tmp_pay_item.price = item['price'] tmp_pay_item.food_id = item['id'] tmp_pay_item.note = note tmp_pay_item.created_time = tmp_pay_item.updated_time = getCurrentDate( ) db.session.add(tmp_pay_item) # 库存变更操作 FoodService.setStockChangeLog(item['id'], -int(item['number']), "在线购买") db.session.commit() resp['data'] = { "id": model_pay_order.id, "order_sn": model_pay_order.order_sn, "total_price": str(model_pay_order.total_price), } except Exception as e: # 抛出错误要回滚 db.session.rollback() print(e) resp['code'] = -1 resp['msg'] = "下单失败请重新下单" resp['msg'] = str(e) pass return resp
def createOrder(self, member_id, items=None, params=None, eat_method=''): resp = {'code': 200, 'msg': '操作成功', 'data': {}} pay_price = decimal.Decimal(0.00) continue_cnt = 0 food_ids = [] for item in items: if decimal.Decimal(item['price']) < 0: continue_cnt += 1 continue pay_price = pay_price + \ (decimal.Decimal(item['price']) * int(item['number'])) food_ids.append(item['id']) if continue_cnt >= len(items): # 下单数量超过 选中数量,不成立 resp['code'] = -1 resp['msg'] = "商品items为空" return resp yun_price = params[ 'yun_price'] if params and 'yun_price' in params else 0 note = params['note'] if params and 'note' in params else '' express_address_id = params[ 'express_address_id'] if params and 'express_address_id' in params else 0 express_info = params[ 'express_info'] if params and 'express_info' in params else {} yun_price = decimal.Decimal(yun_price) total_price = pay_price + yun_price # 并发处理,加入库存 # 悲观锁 或者 乐观锁 try: # db.session.query( Food ).filter( Food.id.in_( food_ids ) )\ tmp_food_list = db.session.query(Food).filter(Food.id.in_(food_ids))\ .with_for_update().all() # 进行悲观锁 操作 # z只有rollback或者commit都能解锁; # time.sleep( 10 ) # 下单表 和 下单从表--加入数据 tmp_food_stock_mapping = {} for tmp_item in tmp_food_list: # 注意对象不能用数组来做,只能用属性值! tmp_food_stock_mapping[tmp_item.id] = tmp_item.stock model_pay_order = PayOrder() model_pay_order.order_sn = self.geneOrderSn() # 产生的 随机订单号 model_pay_order.member_id = member_id model_pay_order.total_price = total_price model_pay_order.pay_price = pay_price model_pay_order.yun_price = yun_price model_pay_order.note = note model_pay_order.status = -8 model_pay_order.express_status = -8 model_pay_order.express_address_id = express_address_id model_pay_order.express_info = json.dumps(express_info) model_pay_order.prepay_id = eat_method # 修改eat model_pay_order.updated_time = getCurrentDate() db.session.add(model_pay_order) # 从表添加 for item in items: tmp_left_stock = tmp_food_stock_mapping[item['id']] # 异常判断/处理 if decimal.Decimal(item['price']) < 0: continue if int(item['number']) > int(tmp_left_stock): # 直接抛出异常 raise Exception("您购买的美食太火爆了,剩余:%s,您购买:%s" % (tmp_left_stock, item['number'])) # 数据库处理 tmp_ret = Food.query.filter_by(id=item['id']).update( {"stock": int(tmp_left_stock) - int(item['number'])}) if not tmp_ret: raise Exception("下单失败请重新下单") tmp_pay_item = PayOrderItem() tmp_pay_item.pay_order_id = model_pay_order.id tmp_pay_item.member_id = member_id tmp_pay_item.quantity = item['number'] tmp_pay_item.price = item['price'] tmp_pay_item.food_id = item['id'] tmp_pay_item.note = note tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate( ) db.session.add(tmp_pay_item) # 库存处理,减少库存 FoodService.setStockChangeLog(item['id'], -item['number'], "在线购买") db.session.commit() # 下单成功,返回相应数据 resp['data'] = { 'id': model_pay_order.id, 'order_sn': model_pay_order.order_sn, 'total_price': str(total_price), } except Exception as e: # 如果抛出错误,进行回滚 db.session.rollback() print(e) resp['code'] = -1 resp['msg'] = "下单失败请重新下单" resp['msg'] = str(e) return resp return resp