当代数据库管理系统课程实验二
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

402 行
18 KiB

  1. import sqlite3 as sqlite
  2. from sqlalchemy.exc import SQLAlchemyError
  3. from sqlalchemy import and_
  4. from be.model import postgreSQLORM
  5. from be.model.postgreSQLORM import Store_Book
  6. from be.model.postgreSQLORM import New_Order_Detail
  7. from be.model.postgreSQLORM import New_Order
  8. from be.model.postgreSQLORM import User
  9. import uuid
  10. import json
  11. import logging
  12. import time
  13. from be.model import db_conn
  14. from be.model import error
  15. from datetime import datetime
  16. import threading
  17. from datetime import timedelta
  18. to_be_overtime={}
  19. def overtime_append(key,value):#对to_be_overtime进行操作
  20. global to_be_overtime
  21. if key in to_be_overtime:
  22. to_be_overtime[key].append(value)
  23. else:
  24. to_be_overtime[key]=[value]
  25. class TimerClass(threading.Thread):
  26. def __init__(self):
  27. threading.Thread.__init__(self)
  28. self.event = threading.Event()
  29. def thread(self):
  30. # threading.Thread(target=Buyer().auto_cancel(to_be_overtime[(datetime.utcnow() + timedelta(seconds=1)).second])).start()
  31. # 上面这个,有利有弊利是超过一秒也能处理 弊是每有任何一次路由访问就要延时开一次线程次数秒
  32. Buyer().auto_cancel(to_be_overtime[(datetime.utcnow() + timedelta(seconds=1)).second])
  33. def run(self): # 每秒运行一次 将超时订单删去
  34. global to_be_overtime
  35. # schedule.every().second.do(thread)#每秒开一个线程去auto_cancel,做完的线程自动退出
  36. while not self.event.is_set():
  37. self.event.wait(1)
  38. if (datetime.utcnow() + timedelta(seconds=1)).second in to_be_overtime:
  39. self.thread()
  40. # schedule.run_pending()
  41. def cancel_timer(self):
  42. self.event.set()
  43. # tmr = TimerClass()#####################在无需测试自动取消订单test时删去 单独测取消订单请在test.sh中用
  44. # #coverage run --timid --branch --source fe,be --concurrency=thread -m pytest -v -k fe/test/test_new_order.py --ignore=fe/data
  45. # tmr.start()###################在无需测试自动取消订单test时删去
  46. def tostop():
  47. global tmr
  48. tmr.cancel_timer()
  49. def jwt_encode(user_id: str, terminal: str) -> str:
  50. encoded = jwt.encode(
  51. {"user_id": user_id, "terminal": terminal, "timestamp": time.time()},
  52. key=user_id,
  53. algorithm="HS256",
  54. )
  55. return encoded.decode("utf-8")
  56. # decode a JWT to a json string like:
  57. # {
  58. # "user_id": [user name],
  59. # "terminal": [terminal code],
  60. # "timestamp": [ts]} to a JWT
  61. # }
  62. def jwt_decode(encoded_token, user_id: str) -> str:
  63. decoded = jwt.decode(encoded_token, key=user_id, algorithms="HS256")
  64. return decoded
  65. class DateEncoder(json.JSONEncoder):
  66. def default(self, obj):
  67. if isinstance(obj, datetime):
  68. return obj.strftime("%Y-%m-%d %H:%M:%S")
  69. else:
  70. return json.JSONEncoder.default(self, obj)
  71. class Buyer(db_conn.DBConn):
  72. def __init__(self):
  73. db_conn.DBConn.__init__(self)
  74. def new_order(self, user_id: str, store_id: str, id_and_count: [(str, int)]) -> (int, str, str):
  75. order_id = ""
  76. try:
  77. if not self.user_id_exist(user_id):
  78. return error.error_non_exist_user_id(user_id) + (order_id, )
  79. if not self.store_id_exist(store_id):
  80. return error.error_non_exist_store_id(store_id) + (order_id, )
  81. uid = "{}_{}_{}".format(user_id, store_id, str(uuid.uuid1()))
  82. # print("touch0")
  83. for book_id, count in id_and_count:
  84. row = self.session.query(postgreSQLORM.Store_Book).filter(and_(postgreSQLORM.Store_Book.store_id==store_id,postgreSQLORM.Store_Book.book_id==book_id)).first()
  85. # cursor = self.conn.execute(
  86. # "SELECT book_id, stock_level, book_info FROM store "
  87. # "WHERE store_id = ? AND book_id = ?;",
  88. # (store_id, book_id))
  89. # row = cursor.fetchone()
  90. if row is None:
  91. return error.error_non_exist_book_id(book_id) + (order_id, )
  92. # stock_level = row[1]
  93. # book_info = row[2]
  94. stock_level = row.stock_level
  95. book_info = row.book_info
  96. book_info_json = json.loads(book_info)
  97. price = book_info_json.get("price")
  98. if stock_level < count:
  99. return error.error_stock_level_low(book_id) + (order_id,)
  100. # print("touch2")
  101. 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})
  102. # cursor = self.conn.execute(
  103. # "UPDATE store set stock_level = stock_level - ? "
  104. # "WHERE store_id = ? and book_id = ? and stock_level >= ?; ",
  105. # (count, store_id, book_id, count))
  106. # if cursor.rowcount == 0:
  107. # print("touch3")
  108. if row == 0:
  109. return error.error_stock_level_low(book_id) + (order_id, )
  110. # print("touch4")
  111. new_order_detail_entity = New_Order_Detail(order_id=uid,book_id=book_id,count=count,price=price)
  112. # print("touch5")
  113. row = self.session.add(new_order_detail_entity)
  114. # self.session.commit()
  115. # self.conn.execute(
  116. # "INSERT INTO new_order_detail(order_id, book_id, count, price) "
  117. # "VALUES(?, ?, ?, ?);",
  118. # (uid, book_id, count, price))
  119. # print("touch1")
  120. timenow = datetime.utcnow()
  121. creat_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()) ## 订单创建时间
  122. new_order_entity = New_Order(order_id=uid,store_id=store_id,user_id=user_id,creat_time=creat_time,status=0)
  123. self.session.add(new_order_entity)
  124. # self.conn.execute(
  125. # "INSERT INTO new_order(order_id, store_id, user_id) "
  126. # "VALUES(?, ?, ?);",
  127. # (uid, store_id, user_id))
  128. # self.conn.commit()
  129. overtime_append(timenow.second,order_id) ##将刚下单的订单加入到overtime中管理
  130. self.session.commit()
  131. order_id = uid
  132. except SQLAlchemyError as e:
  133. logging.info("528, {}".format(str(e)))
  134. return 528, "{}".format(str(e)), ""
  135. except BaseException as e:
  136. logging.info("530, {}".format(str(e)))
  137. return 530, "{}".format(str(e)), ""
  138. return 200, "ok", order_id
  139. def payment(self, user_id: str, password: str, order_id: str) -> (int, str):
  140. # conn = self.conn
  141. session = self.session
  142. try:
  143. row = session.query(New_Order).filter(New_Order.order_id==order_id).first()
  144. # cursor = conn.execute("SELECT order_id, user_id, store_id FROM new_order WHERE order_id = ?", (order_id,))
  145. # row = cursor.fetchone()
  146. if row is None:
  147. return error.error_invalid_order_id(order_id)
  148. # order_id = row[0]
  149. # buyer_id = row[1]
  150. # store_id = row[2]
  151. order_id = row.order_id
  152. buyer_id = row.user_id
  153. store_id = row.store_id
  154. if buyer_id != user_id:
  155. return error.error_authorization_fail()
  156. row = session.query(postgreSQLORM.User).filter(postgreSQLORM.User.user_id==buyer_id).first()
  157. # cursor = conn.execute("SELECT balance, password FROM user WHERE user_id = ?;", (buyer_id,))
  158. # row = cursor.fetchone()
  159. if row is None:
  160. return error.error_non_exist_user_id(buyer_id)
  161. # balance = row[0]
  162. balance = row.balance
  163. pwd = row.password
  164. if password != pwd:
  165. return error.error_authorization_fail()
  166. row = session.query(postgreSQLORM.User_Store).filter(postgreSQLORM.User_Store.store_id==store_id).first()
  167. # cursor = conn.execute("SELECT store_id, user_id FROM user_store WHERE store_id = ?;", (store_id,))
  168. # row = cursor.fetchone()
  169. if row is None:
  170. return error.error_non_exist_store_id(store_id)
  171. # seller_id = row[1]
  172. seller_id = row.user_id
  173. if not self.user_id_exist(seller_id):
  174. return error.error_non_exist_user_id(seller_id)
  175. row = session.query(New_Order_Detail).filter(New_Order_Detail.order_id==order_id).all()
  176. # cursor = conn.execute("SELECT book_id, count, price FROM new_order_detail WHERE order_id = ?;", (order_id,))
  177. total_price = 0
  178. # for row in cursor:
  179. # count = row[1]
  180. # price = row[2]
  181. # total_price = total_price + price * count
  182. for i in row:
  183. count = i.count
  184. price = i.price
  185. total_price = total_price + price * count
  186. if balance < total_price:
  187. return error.error_not_sufficient_funds(order_id)
  188. # print('touch0')
  189. ## 买家扣钱
  190. row = session.query(User).filter(and_(User.balance>=total_price,User.user_id==buyer_id)).update({'balance':User.balance-total_price})
  191. # cursor = conn.execute("UPDATE user set balance = balance - ?"
  192. # "WHERE user_id = ? AND balance >= ?",
  193. # (total_price, buyer_id, total_price))
  194. # if cursor.rowcount == 0:
  195. if row == 0:
  196. return error.error_not_sufficient_funds(order_id)
  197. # print('touch1')
  198. ## 卖家加钱
  199. row = session.query(User).filter(User.user_id==seller_id).update({'balance':User.balance+total_price})
  200. # cursor = conn.execute("UPDATE user set balance = balance + ?"
  201. # "WHERE user_id = ?",
  202. # (total_price, buyer_id))
  203. # if cursor.rowcount == 0:
  204. if row == 0:
  205. return error.error_non_exist_user_id(buyer_id)
  206. # print('touch2')
  207. # row = session.query(New_Order).filter(New_Order.order_id==order_id).delete() 不在删除而是修改订单状态
  208. row = session.query(New_Order).filter(New_Order.order_id==order_id).update({'status':1})
  209. # cursor = conn.execute("DELETE FROM new_order WHERE order_id = ?", (order_id, ))
  210. # if cursor.rowcount == 0:
  211. if row == 0:
  212. return error.error_invalid_order_id(order_id)
  213. # row = session.query(New_Order_Detail).filter(New_Order_Detail.order_id==order_id).delete()
  214. # cursor = conn.execute("DELETE FROM new_order_detail where order_id = ?", (order_id, ))
  215. # if cursor.rowcount == 0:
  216. if row == 0:
  217. return error.error_invalid_order_id(order_id)
  218. # conn.commit()
  219. session.commit()
  220. except SQLAlchemyError as e:
  221. return 528, "{}".format(str(e))
  222. except BaseException as e:
  223. return 530, "{}".format(str(e))
  224. return 200, "ok"
  225. def add_funds(self, user_id, password, add_value) -> (int, str):
  226. try:
  227. row = self.session.query(postgreSQLORM.User).filter(postgreSQLORM.User.user_id==user_id).first()
  228. # cursor = self.conn.execute("SELECT password from user where user_id=?", (user_id,))
  229. # row = cursor.fetchone()
  230. if row is None:
  231. return error.error_authorization_fail()
  232. pwd = row.password
  233. if pwd != password:
  234. return error.error_authorization_fail()
  235. row = self.session.query(postgreSQLORM.User).filter_by(user_id=user_id).update({'balance':postgreSQLORM.User.balance+add_value,'user_id':user_id})
  236. # cursor = self.conn.execute(
  237. # "UPDATE user SET balance = balance + ? WHERE user_id = ?",
  238. # (add_value, user_id))
  239. if row == 0:
  240. return error.error_non_exist_user_id(user_id)
  241. self.session.commit()
  242. # self.conn.commit()
  243. except SQLAlchemyError as e:
  244. return 528, "{}".format(str(e))
  245. except BaseException as e:
  246. return 530, "{}".format(str(e))
  247. return 200, "ok"
  248. def take_over(self, user_id, order_id):
  249. session = self.session
  250. try:
  251. if not self.user_id_exist(user_id):
  252. return error.error_non_exist_user_id(user_id)
  253. row = session.query(New_Order).filter(and_(New_Order.order_id==order_id,New_Order.user_id==user_id)).first()
  254. if row is None:
  255. return error.error_invalid_order_id(order_id)
  256. if row.status != 2:
  257. return error.error_invalid_order_id(order_id)
  258. row = session.query(New_Order).filter(and_(New_Order.order_id==order_id,New_Order.user_id==user_id)).update({'status':3})
  259. if row == 0:
  260. return error.error_invalid_order_id(order_id)
  261. session.commit()
  262. except SQLAlchemyError as e:
  263. return 528, "{}".format(str(e))
  264. except BaseException as e:
  265. # print('touch3')
  266. return 530, "{}".format(str(e))
  267. return 200, "ok"
  268. def order_cancel(self, user_id, order_id):
  269. session = self.session
  270. try:
  271. if not self.user_id_exist(user_id):
  272. return error.error_non_exist_user_id(user_id)
  273. row = session.query(New_Order).filter(and_(New_Order.order_id==order_id,New_Order.user_id==user_id)).first()
  274. if row is None:
  275. return error.error_invalid_order_id(order_id)
  276. if row.status != 0:
  277. return error.error_invalid_order_id(order_id)
  278. store_id = row.store_id
  279. row2 = session.query(New_Order_Detail).filter(New_Order_Detail.order_id==order_id).first()
  280. book_id = row2.book_id
  281. count = row2.count
  282. 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})
  283. row = session.query(New_Order).filter(and_(New_Order.order_id==order_id,New_Order.user_id==user_id)).update({'status':-1})
  284. if row == 0:
  285. return error.error_invalid_order_id(order_id)
  286. session.commit()
  287. except SQLAlchemyError as e:
  288. return 528, "{}".format(str(e))
  289. except BaseException as e:
  290. # print('touch3')
  291. return 530, "{}".format(str(e))
  292. return 200, "ok"
  293. def history_order(self, user_id):
  294. session = self.session
  295. try:
  296. if not self.user_id_exist(user_id):
  297. return error.error_non_exist_user_id(user_id)
  298. row = session.query(New_Order).filter(New_Order.user_id==user_id).first()
  299. if row is None:
  300. return error.error_non_exist_user_id(user_id)
  301. row = session.query(New_Order).filter(New_Order.user_id==user_id).order_by(New_Order.creat_time.desc()).all()
  302. order_ids = []
  303. for i in row:
  304. order_ids.append(i.order_id)
  305. session.commit()
  306. except SQLAlchemyError as e:
  307. return 528, "{}".format(str(e))
  308. except BaseException as e:
  309. # print('touch3')
  310. return 530, "{}".format(str(e))
  311. return 200, "ok", order_ids
  312. def auto_cancel(self,order_id_list):#自动取消订单
  313. exist_order_need_cancel=0
  314. try:
  315. for order_id in order_id_list:
  316. row = self.session.query(New_Order).filter(New_Order.order_id==order_id).first()
  317. if row is None:
  318. return error.error_invalid_order_id(order_id)
  319. #是否属于未付款订单
  320. if row.status == 0:
  321. timenow = datetime.utcnow()
  322. check_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
  323. creat_time = row.creat_time
  324. time_1_struct = datetime.strptime(creat_time, "%Y-%m-%d %H:%M:%S")
  325. time_2_struct = datetime.strptime(check_time, "%Y-%m-%d %H:%M:%S")
  326. seconds = (time_2_struct - time_1_struct).seconds
  327. if seconds>= 30: ## 订单超过30秒为付款自动取消
  328. store_id = row.store_id
  329. row3 = self.session.query(New_Order).filter(New_Order_Detail.order_id==order_id).first()
  330. book_id = row3.book_id
  331. count = row3.count
  332. 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})
  333. self.session.query(New_Order).filter(New_Order.order_id==order_id).update({'status':-1})
  334. exist_order_need_cancel = 1
  335. self.session.commit()
  336. except SQLAlchemyError as e:
  337. return 528, "{}".format(str(e))
  338. except BaseException as e:
  339. # print('touch3')
  340. return 530, "{}".format(str(e))
  341. return 'no_such_order' if exist_order_need_cancel==0 else "auto_cancel_done"