import sqlite3 as sqlite from sqlalchemy.exc import SQLAlchemyError from sqlalchemy import and_ from be.model import postgreSQLORM from be.model.postgreSQLORM import Store_Book from be.model.postgreSQLORM import New_Order_Detail from be.model.postgreSQLORM import New_Order from be.model.postgreSQLORM import User import uuid import json import logging import time from be.model import db_conn from be.model import error from datetime import datetime import threading from datetime import timedelta to_be_overtime={} def overtime_append(key,value):#对to_be_overtime进行操作 global to_be_overtime if key in to_be_overtime: to_be_overtime[key].append(value) else: to_be_overtime[key]=[value] class TimerClass(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.event = threading.Event() def thread(self): # threading.Thread(target=Buyer().auto_cancel(to_be_overtime[(datetime.utcnow() + timedelta(seconds=1)).second])).start() # 上面这个,有利有弊利是超过一秒也能处理 弊是每有任何一次路由访问就要延时开一次线程次数秒 Buyer().auto_cancel(to_be_overtime[(datetime.utcnow() + timedelta(seconds=1)).second]) def run(self): # 每秒运行一次 将超时订单删去 global to_be_overtime # schedule.every().second.do(thread)#每秒开一个线程去auto_cancel,做完的线程自动退出 while not self.event.is_set(): self.event.wait(1) if (datetime.utcnow() + timedelta(seconds=1)).second in to_be_overtime: self.thread() # schedule.run_pending() def cancel_timer(self): self.event.set() # tmr = TimerClass()#####################在无需测试自动取消订单test时删去 单独测取消订单请在test.sh中用 # #coverage run --timid --branch --source fe,be --concurrency=thread -m pytest -v -k fe/test/test_new_order.py --ignore=fe/data # tmr.start()###################在无需测试自动取消订单test时删去 def tostop(): global tmr tmr.cancel_timer() def jwt_encode(user_id: str, terminal: str) -> str: encoded = jwt.encode( {"user_id": user_id, "terminal": terminal, "timestamp": time.time()}, key=user_id, algorithm="HS256", ) return encoded.decode("utf-8") # decode a JWT to a json string like: # { # "user_id": [user name], # "terminal": [terminal code], # "timestamp": [ts]} to a JWT # } def jwt_decode(encoded_token, user_id: str) -> str: decoded = jwt.decode(encoded_token, key=user_id, algorithms="HS256") return decoded class DateEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.strftime("%Y-%m-%d %H:%M:%S") else: return json.JSONEncoder.default(self, obj) class Buyer(db_conn.DBConn): def __init__(self): db_conn.DBConn.__init__(self) def new_order(self, user_id: str, store_id: str, id_and_count: [(str, int)]) -> (int, str, str): order_id = "" try: if not self.user_id_exist(user_id): return error.error_non_exist_user_id(user_id) + (order_id, ) if not self.store_id_exist(store_id): return error.error_non_exist_store_id(store_id) + (order_id, ) uid = "{}_{}_{}".format(user_id, store_id, str(uuid.uuid1())) # print("touch0") for book_id, count in id_and_count: row = self.session.query(postgreSQLORM.Store_Book).filter(and_(postgreSQLORM.Store_Book.store_id==store_id,postgreSQLORM.Store_Book.book_id==book_id)).first() # cursor = self.conn.execute( # "SELECT book_id, stock_level, book_info FROM store " # "WHERE store_id = ? AND book_id = ?;", # (store_id, book_id)) # row = cursor.fetchone() if row is None: return error.error_non_exist_book_id(book_id) + (order_id, ) # stock_level = row[1] # book_info = row[2] stock_level = row.stock_level book_info = row.book_info book_info_json = json.loads(book_info) price = book_info_json.get("price") if stock_level < count: return error.error_stock_level_low(book_id) + (order_id,) # print("touch2") row = self.session.query(Store_Book).filter(and_(Store_Book.store_id==store_id,Store_Book.book_id==book_id,Store_Book.stock_level>=count)).update({'stock_level':Store_Book.stock_level-count}) # cursor = self.conn.execute( # "UPDATE store set stock_level = stock_level - ? " # "WHERE store_id = ? and book_id = ? and stock_level >= ?; ", # (count, store_id, book_id, count)) # if cursor.rowcount == 0: # print("touch3") if row == 0: return error.error_stock_level_low(book_id) + (order_id, ) # print("touch4") new_order_detail_entity = New_Order_Detail(order_id=uid,book_id=book_id,count=count,price=price) # print("touch5") row = self.session.add(new_order_detail_entity) # self.session.commit() # self.conn.execute( # "INSERT INTO new_order_detail(order_id, book_id, count, price) " # "VALUES(?, ?, ?, ?);", # (uid, book_id, count, price)) # print("touch1") timenow = datetime.utcnow() creat_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()) ## 订单创建时间 new_order_entity = New_Order(order_id=uid,store_id=store_id,user_id=user_id,creat_time=creat_time,status=0) self.session.add(new_order_entity) # self.conn.execute( # "INSERT INTO new_order(order_id, store_id, user_id) " # "VALUES(?, ?, ?);", # (uid, store_id, user_id)) # self.conn.commit() overtime_append(timenow.second,order_id) ##将刚下单的订单加入到overtime中管理 self.session.commit() order_id = uid except SQLAlchemyError as e: logging.info("528, {}".format(str(e))) return 528, "{}".format(str(e)), "" except BaseException as e: logging.info("530, {}".format(str(e))) return 530, "{}".format(str(e)), "" return 200, "ok", order_id def payment(self, user_id: str, password: str, order_id: str) -> (int, str): # conn = self.conn session = self.session try: row = session.query(New_Order).filter(New_Order.order_id==order_id).first() # cursor = conn.execute("SELECT order_id, user_id, store_id FROM new_order WHERE order_id = ?", (order_id,)) # row = cursor.fetchone() if row is None: return error.error_invalid_order_id(order_id) # order_id = row[0] # buyer_id = row[1] # store_id = row[2] order_id = row.order_id buyer_id = row.user_id store_id = row.store_id if buyer_id != user_id: return error.error_authorization_fail() row = session.query(postgreSQLORM.User).filter(postgreSQLORM.User.user_id==buyer_id).first() # cursor = conn.execute("SELECT balance, password FROM user WHERE user_id = ?;", (buyer_id,)) # row = cursor.fetchone() if row is None: return error.error_non_exist_user_id(buyer_id) # balance = row[0] balance = row.balance pwd = row.password if password != pwd: return error.error_authorization_fail() row = session.query(postgreSQLORM.User_Store).filter(postgreSQLORM.User_Store.store_id==store_id).first() # cursor = conn.execute("SELECT store_id, user_id FROM user_store WHERE store_id = ?;", (store_id,)) # row = cursor.fetchone() if row is None: return error.error_non_exist_store_id(store_id) # seller_id = row[1] seller_id = row.user_id if not self.user_id_exist(seller_id): return error.error_non_exist_user_id(seller_id) row = session.query(New_Order_Detail).filter(New_Order_Detail.order_id==order_id).all() # cursor = conn.execute("SELECT book_id, count, price FROM new_order_detail WHERE order_id = ?;", (order_id,)) total_price = 0 # for row in cursor: # count = row[1] # price = row[2] # total_price = total_price + price * count for i in row: count = i.count price = i.price total_price = total_price + price * count if balance < total_price: return error.error_not_sufficient_funds(order_id) # print('touch0') ## 买家扣钱 row = session.query(User).filter(and_(User.balance>=total_price,User.user_id==buyer_id)).update({'balance':User.balance-total_price}) # cursor = conn.execute("UPDATE user set balance = balance - ?" # "WHERE user_id = ? AND balance >= ?", # (total_price, buyer_id, total_price)) # if cursor.rowcount == 0: if row == 0: return error.error_not_sufficient_funds(order_id) # print('touch1') ## 卖家加钱 row = session.query(User).filter(User.user_id==seller_id).update({'balance':User.balance+total_price}) # cursor = conn.execute("UPDATE user set balance = balance + ?" # "WHERE user_id = ?", # (total_price, buyer_id)) # if cursor.rowcount == 0: if row == 0: return error.error_non_exist_user_id(buyer_id) # print('touch2') # row = session.query(New_Order).filter(New_Order.order_id==order_id).delete() 不在删除而是修改订单状态 row = session.query(New_Order).filter(New_Order.order_id==order_id).update({'status':1}) # cursor = conn.execute("DELETE FROM new_order WHERE order_id = ?", (order_id, )) # if cursor.rowcount == 0: if row == 0: return error.error_invalid_order_id(order_id) # row = session.query(New_Order_Detail).filter(New_Order_Detail.order_id==order_id).delete() # cursor = conn.execute("DELETE FROM new_order_detail where order_id = ?", (order_id, )) # if cursor.rowcount == 0: if row == 0: return error.error_invalid_order_id(order_id) # conn.commit() session.commit() except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: return 530, "{}".format(str(e)) return 200, "ok" def add_funds(self, user_id, password, add_value) -> (int, str): try: row = self.session.query(postgreSQLORM.User).filter(postgreSQLORM.User.user_id==user_id).first() # cursor = self.conn.execute("SELECT password from user where user_id=?", (user_id,)) # row = cursor.fetchone() if row is None: return error.error_authorization_fail() pwd = row.password if pwd != password: return error.error_authorization_fail() row = self.session.query(postgreSQLORM.User).filter_by(user_id=user_id).update({'balance':postgreSQLORM.User.balance+add_value,'user_id':user_id}) # cursor = self.conn.execute( # "UPDATE user SET balance = balance + ? WHERE user_id = ?", # (add_value, user_id)) if row == 0: return error.error_non_exist_user_id(user_id) self.session.commit() # self.conn.commit() except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: return 530, "{}".format(str(e)) return 200, "ok" def take_over(self, user_id, order_id): session = self.session try: if not self.user_id_exist(user_id): return error.error_non_exist_user_id(user_id) row = session.query(New_Order).filter(and_(New_Order.order_id==order_id,New_Order.user_id==user_id)).first() if row is None: return error.error_invalid_order_id(order_id) if row.status != 2: return error.error_invalid_order_id(order_id) row = session.query(New_Order).filter(and_(New_Order.order_id==order_id,New_Order.user_id==user_id)).update({'status':3}) if row == 0: return error.error_invalid_order_id(order_id) session.commit() except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: # print('touch3') return 530, "{}".format(str(e)) return 200, "ok" def order_cancel(self, user_id, order_id): session = self.session try: if not self.user_id_exist(user_id): return error.error_non_exist_user_id(user_id) row = session.query(New_Order).filter(and_(New_Order.order_id==order_id,New_Order.user_id==user_id)).first() if row is None: return error.error_invalid_order_id(order_id) if row.status != 0: return error.error_invalid_order_id(order_id) store_id = row.store_id row2 = session.query(New_Order_Detail).filter(New_Order_Detail.order_id==order_id).first() book_id = row2.book_id count = row2.count row3 = session.query(Store_Book).filter(and_(Store_Book.store_id==store_id,Store_Book.book_id==book_id)).update({'stock_level':Store_Book.stock_level+count}) row = session.query(New_Order).filter(and_(New_Order.order_id==order_id,New_Order.user_id==user_id)).update({'status':-1}) if row == 0: return error.error_invalid_order_id(order_id) session.commit() except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: # print('touch3') return 530, "{}".format(str(e)) return 200, "ok" def history_order(self, user_id): session = self.session try: if not self.user_id_exist(user_id): return error.error_non_exist_user_id(user_id) row = session.query(New_Order).filter(New_Order.user_id==user_id).first() if row is None: return error.error_non_exist_user_id(user_id) row = session.query(New_Order).filter(New_Order.user_id==user_id).order_by(New_Order.creat_time.desc()).all() order_ids = [] for i in row: order_ids.append(i.order_id) session.commit() except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: # print('touch3') return 530, "{}".format(str(e)) return 200, "ok", order_ids def auto_cancel(self,order_id_list):#自动取消订单 exist_order_need_cancel=0 try: for order_id in order_id_list: row = self.session.query(New_Order).filter(New_Order.order_id==order_id).first() if row is None: return error.error_invalid_order_id(order_id) #是否属于未付款订单 if row.status == 0: timenow = datetime.utcnow() check_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()) creat_time = row.creat_time time_1_struct = datetime.strptime(creat_time, "%Y-%m-%d %H:%M:%S") time_2_struct = datetime.strptime(check_time, "%Y-%m-%d %H:%M:%S") seconds = (time_2_struct - time_1_struct).seconds if seconds>= 30: ## 订单超过30秒为付款自动取消 store_id = row.store_id row3 = self.session.query(New_Order).filter(New_Order_Detail.order_id==order_id).first() book_id = row3.book_id count = row3.count self.session.query(Store_Book).filter(and_(Store_Book.store_id==store_id,Store_Book.book_id==book_id)).update({'stock_level':Store_Book.stock_level+count}) self.session.query(New_Order).filter(New_Order.order_id==order_id).update({'status':-1}) exist_order_need_cancel = 1 self.session.commit() except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: # print('touch3') return 530, "{}".format(str(e)) return 'no_such_order' if exist_order_need_cancel==0 else "auto_cancel_done"