|
|
- 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"
-
|