From afca660216fffd48786300c5ff3e4da13899da2d Mon Sep 17 00:00:00 2001 From: Max <2032127781@qq.com> Date: Mon, 5 Dec 2022 14:50:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E9=80=9A=E8=BF=87=E5=89=8D60?= =?UTF-8?q?%=E7=9A=84=E4=BD=9C=E4=B8=9A=E8=A6=81=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .coverage | Bin 102400 -> 53248 bytes be/Config.py | 0 be/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 132 bytes be/__pycache__/serve.cpython-39.pyc | Bin 0 -> 1591 bytes be/creatTB.py | 5 + be/model/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 138 bytes be/model/__pycache__/buyer.cpython-39.pyc | Bin 0 -> 4171 bytes be/model/__pycache__/creatTB.cpython-39.pyc | Bin 0 -> 352 bytes be/model/__pycache__/db_conn.cpython-39.pyc | Bin 0 -> 1264 bytes be/model/__pycache__/error.cpython-39.pyc | Bin 0 -> 2079 bytes be/model/__pycache__/postgreSQLORM.cpython-39.pyc | Bin 0 -> 3332 bytes be/model/__pycache__/seller.cpython-39.pyc | Bin 0 -> 2704 bytes be/model/__pycache__/user.cpython-39.pyc | Bin 0 -> 5124 bytes be/model/buyer.py | 193 +++++++++++++-------- be/model/creatTB.py | 5 + be/model/db_conn.py | 23 ++- be/model/postgreSQLORM.py | 121 +++++++++++++ be/model/seller.py | 49 ++++-- be/model/store.py | 63 ------- be/model/user.py | 105 +++++++---- be/postgreSQLORM.py | 121 +++++++++++++ be/serve.py | 18 +- be/testconn.py | 22 +++ be/view/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 137 bytes be/view/__pycache__/auth.cpython-39.pyc | Bin 0 -> 1915 bytes be/view/__pycache__/buyer.cpython-39.pyc | Bin 0 -> 1390 bytes be/view/__pycache__/seller.cpython-39.pyc | Bin 0 -> 1415 bytes be/view/__pycache__/testconn.cpython-39.pyc | Bin 0 -> 934 bytes be/view/auth.py | 4 +- be/view/buyer.py | 4 +- be/view/seller.py | 3 +- be/view/testconn.py | 21 +++ fe/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 132 bytes fe/__pycache__/conf.cpython-39.pyc | Bin 0 -> 424 bytes .../conftest.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 1010 bytes fe/access/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 139 bytes fe/access/__pycache__/auth.cpython-39.pyc | Bin 0 -> 1833 bytes fe/access/__pycache__/book.cpython-39.pyc | Bin 0 -> 2700 bytes fe/access/__pycache__/buyer.cpython-39.pyc | Bin 0 -> 1813 bytes fe/access/__pycache__/new_buyer.cpython-39.pyc | Bin 0 -> 494 bytes fe/access/__pycache__/new_seller.cpython-39.pyc | Bin 0 -> 498 bytes fe/access/__pycache__/seller.cpython-39.pyc | Bin 0 -> 1821 bytes fe/bench/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 138 bytes fe/bench/__pycache__/run.cpython-39.pyc | Bin 0 -> 524 bytes fe/bench/__pycache__/session.cpython-39.pyc | Bin 0 -> 1770 bytes fe/bench/__pycache__/workload.cpython-39.pyc | Bin 0 -> 5420 bytes fe/test/__pycache__/gen_book_data.cpython-39.pyc | Bin 0 -> 1718 bytes .../test_add_book.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 3144 bytes .../test_add_funds.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 2237 bytes ...est_add_stock_level.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 3079 bytes .../test_bench.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 840 bytes .../test_create_store.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 1946 bytes .../test_login.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 3262 bytes .../test_new_order.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 3556 bytes .../test_password.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 3709 bytes .../test_payment.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 4254 bytes .../test_register.cpython-39-pytest-7.2.0.pyc | Bin 0 -> 3080 bytes script/test.sh | 2 +- 58 files changed, 550 insertions(+), 209 deletions(-) create mode 100644 be/Config.py create mode 100644 be/__pycache__/__init__.cpython-39.pyc create mode 100644 be/__pycache__/serve.cpython-39.pyc create mode 100644 be/creatTB.py create mode 100644 be/model/__pycache__/__init__.cpython-39.pyc create mode 100644 be/model/__pycache__/buyer.cpython-39.pyc create mode 100644 be/model/__pycache__/creatTB.cpython-39.pyc create mode 100644 be/model/__pycache__/db_conn.cpython-39.pyc create mode 100644 be/model/__pycache__/error.cpython-39.pyc create mode 100644 be/model/__pycache__/postgreSQLORM.cpython-39.pyc create mode 100644 be/model/__pycache__/seller.cpython-39.pyc create mode 100644 be/model/__pycache__/user.cpython-39.pyc create mode 100644 be/model/creatTB.py create mode 100644 be/model/postgreSQLORM.py create mode 100644 be/postgreSQLORM.py create mode 100644 be/testconn.py create mode 100644 be/view/__pycache__/__init__.cpython-39.pyc create mode 100644 be/view/__pycache__/auth.cpython-39.pyc create mode 100644 be/view/__pycache__/buyer.cpython-39.pyc create mode 100644 be/view/__pycache__/seller.cpython-39.pyc create mode 100644 be/view/__pycache__/testconn.cpython-39.pyc create mode 100644 be/view/testconn.py create mode 100644 fe/__pycache__/__init__.cpython-39.pyc create mode 100644 fe/__pycache__/conf.cpython-39.pyc create mode 100644 fe/__pycache__/conftest.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/access/__pycache__/__init__.cpython-39.pyc create mode 100644 fe/access/__pycache__/auth.cpython-39.pyc create mode 100644 fe/access/__pycache__/book.cpython-39.pyc create mode 100644 fe/access/__pycache__/buyer.cpython-39.pyc create mode 100644 fe/access/__pycache__/new_buyer.cpython-39.pyc create mode 100644 fe/access/__pycache__/new_seller.cpython-39.pyc create mode 100644 fe/access/__pycache__/seller.cpython-39.pyc create mode 100644 fe/bench/__pycache__/__init__.cpython-39.pyc create mode 100644 fe/bench/__pycache__/run.cpython-39.pyc create mode 100644 fe/bench/__pycache__/session.cpython-39.pyc create mode 100644 fe/bench/__pycache__/workload.cpython-39.pyc create mode 100644 fe/test/__pycache__/gen_book_data.cpython-39.pyc create mode 100644 fe/test/__pycache__/test_add_book.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_add_funds.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_add_stock_level.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_bench.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_create_store.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_login.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_new_order.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_password.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_payment.cpython-39-pytest-7.2.0.pyc create mode 100644 fe/test/__pycache__/test_register.cpython-39-pytest-7.2.0.pyc diff --git a/.coverage b/.coverage index bf8596987b42b9bd2a64606fc092e380b5f1490a..405b7280dd86f13285b1d0590ea7961885d8ce16 100644 GIT binary patch literal 53248 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 literal 0 HcmV?d00001 diff --git a/be/creatTB.py b/be/creatTB.py new file mode 100644 index 0000000..cca8c93 --- /dev/null +++ b/be/creatTB.py @@ -0,0 +1,5 @@ +from postgreSQLORM import Base,engine + +def createTable(): + # 创建所有继承于Base的类对应的表 + Base.metadata.create_all(engine) diff --git a/be/model/__pycache__/__init__.cpython-39.pyc b/be/model/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf0025175f2fa814623f5222b3a36d5a9af6f5c1 GIT binary patch literal 138 zcmYe~<>g`k0724V&P DYw#Z3 literal 0 HcmV?d00001 diff --git a/be/model/__pycache__/buyer.cpython-39.pyc b/be/model/__pycache__/buyer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..607640b9cf4417d7c3cb437a40142ef9470f33cb GIT binary patch literal 4171 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 AqW}N^ literal 0 HcmV?d00001 diff --git a/be/model/__pycache__/db_conn.cpython-39.pyc b/be/model/__pycache__/db_conn.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cd320a7ccf4e320226b94d1ddb9d06be3361c599 GIT binary patch literal 1264 zcmb`HOK%e~5P<#ISJI~C(ZZ$Th*$|Clw*ZZ)uJLHD38Ep70GJi4ccTk+u9pJt8k(m z`48=}zlOW7ocIfzn6WoB5j|qbvtxV4o^Qt9!&a+Fp#AvveUSNt{KUax<1pBPt~($k zku)a-O(;d3<*eWdFTBJn{KTi^Igwm?XGD5mSrSOUOXA=c_>q{J)={aek1FlHefj#` ztC$<_gHDxccB@jQVz(^ErinAcP7Kg%u`w9zK-UjJq$Ht|BurAt&Pc-Dsfj0j8Nk?= zp^V@g$Oc5vG{Ljoy>c=cP;i|$)N#)}=z0}IMMiW+1ndhw^dM#mmrbZst+R3h1fEXw z;U!TGnE&10-|qDxXpQ0bFnk;Lqc<-)y?)v&N}1+8*%t#ixP5eDA|bL#RtW(~CfWl* zXhcufU1;t3>HrU&H_Sa++87^$G9x2$PAhgn&w0g0-i(e>_bk0 zEejtgjgE{i)?{FQ#a7sbATIYcpJq{6j;$k%G%jcqFGIOf0=U0?EhBI zvAN1QHoP~EZDlwX%T#sQEY)>DYjbl)v~@*P*KM<|+p^t39OAv592Th%rYQv6>S>Pp zsu0K1!`!W?6%6ebicJ)EQCy|eYIs#t00K*7vl-FIj~Y?K&f1guY1=*<_weq_hwY^w dhrPe9&^9Bu=XHmf=!uK=DZX_3;8y7d`vYI^3kCoH literal 0 HcmV?d00001 diff --git a/be/model/__pycache__/error.cpython-39.pyc b/be/model/__pycache__/error.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..baee04bf4a9cca79fd42b099f80abff1a623e564 GIT binary patch literal 2079 zcmbVN%Wl&^6dgP77j2rP=^M9*MWnV8NGw1F@sL=sh>*IgB3Y@g16I=*jhzB%*|A{5 zf;|gZ_6OMVAK9|%f*)W5_l)Cql2)k7Saa^!zMgaE&Yk0SsgxJoeja~zex!u>g&Vz9 z`Q|bA;1dH0GRUL^B`HN|%21Yal)rQpzE<`G6{+-5>=|@}X4slEOJ%kRnxhKaBvq-# zHbwJPXPc%4T4bA{C0b^ir4?Fbo1-_Gt+OrA#;$1G8dTc-@U<_!K|A#Pp4Dl4 z-R(iO$3yp>7lc+naHZvub^Kv4d+AB-!Y>GY>5d%Bk)!@dn{nUw55{NIo-Ff6&Vki+ zkKC@+_1|t<+RKX9J8E}17+=zPRO>xIw1R%8<2jz&3$0GSN5Q7#ON3$&=A`VvwLsl542^%YuMZgRI(M5oj z4l5D!80#v(h*@zAreWnH6|r(|vMLFjoJsP9$z{im>skc$DI-Y75y%=w6YH+(>yBw} zYqSef(q>{>6a^~aigjPw?vYskDsx4;=Og-&7}>GgJ&oVG9=|!J35ljGfd4!QxrW<` zN?VGHJhU%V&sM5;pWWkwhLU%3TMK`T7Un7o9%< literal 0 HcmV?d00001 diff --git a/be/model/__pycache__/postgreSQLORM.cpython-39.pyc b/be/model/__pycache__/postgreSQLORM.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96a9eb2adee8a8ef649d6a882641fb37b048794b GIT binary patch literal 3332 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 literal 0 HcmV?d00001 diff --git a/be/model/buyer.py b/be/model/buyer.py index f8b6595..23e56f0 100644 --- a/be/model/buyer.py +++ b/be/model/buyer.py @@ -1,4 +1,11 @@ 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 @@ -18,43 +25,59 @@ class Buyer(db_conn.DBConn): 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: - 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() + 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[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,) - - 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("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, ) - self.conn.execute( - "INSERT INTO new_order_detail(order_id, book_id, count, price) " - "VALUES(?, ?, ?, ?);", - (uid, book_id, count, price)) - - self.conn.execute( - "INSERT INTO new_order(order_id, store_id, user_id) " - "VALUES(?, ?, ?);", - (uid, store_id, user_id)) - self.conn.commit() + # 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") + new_order_entity = New_Order(order_id=uid,fk_store_id=store_id,fk_user_id=user_id) + 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() + self.session.commit() order_id = uid - except sqlite.Error as e: + except SQLAlchemyError as e: logging.info("528, {}".format(str(e))) return 528, "{}".format(str(e)), "" except BaseException as e: @@ -64,72 +87,98 @@ class Buyer(db_conn.DBConn): return 200, "ok", order_id def payment(self, user_id: str, password: str, order_id: str) -> (int, str): - conn = self.conn + # conn = self.conn + session = self.session try: - cursor = conn.execute("SELECT order_id, user_id, store_id FROM new_order WHERE order_id = ?", (order_id,)) - row = cursor.fetchone() + 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[0] + # buyer_id = row[1] + # store_id = row[2] + order_id = row.order_id + buyer_id = row.fk_user_id + store_id = row.fk_store_id if buyer_id != user_id: return error.error_authorization_fail() - - cursor = conn.execute("SELECT balance, password FROM user WHERE user_id = ?;", (buyer_id,)) - row = cursor.fetchone() + + 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] - if password != row[1]: + # balance = row[0] + balance = row.balance + pwd = row.password + if password != pwd: return error.error_authorization_fail() - cursor = conn.execute("SELECT store_id, user_id FROM user_store WHERE store_id = ?;", (store_id,)) - row = cursor.fetchone() + row = session.query(postgreSQLORM.User_Store).filter(postgreSQLORM.User_Store.fk_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[1] + seller_id = row.fk_user_id if not self.user_id_exist(seller_id): return error.error_non_exist_user_id(seller_id) - cursor = conn.execute("SELECT book_id, count, price FROM new_order_detail WHERE order_id = ?;", (order_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] + # 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) - cursor = conn.execute("UPDATE user set balance = balance - ?" - "WHERE user_id = ? AND balance >= ?", - (total_price, buyer_id, total_price)) - if cursor.rowcount == 0: + # 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) - - cursor = conn.execute("UPDATE user set balance = balance + ?" - "WHERE user_id = ?", - (total_price, buyer_id)) - - if cursor.rowcount == 0: + # 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) - - cursor = conn.execute("DELETE FROM new_order WHERE order_id = ?", (order_id, )) - if cursor.rowcount == 0: + # print('touch2') + row = session.query(New_Order).filter(New_Order.order_id==order_id).delete() + # 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) - - cursor = conn.execute("DELETE FROM new_order_detail where order_id = ?", (order_id, )) - if cursor.rowcount == 0: + + 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() + # conn.commit() + session.commit() - except sqlite.Error as e: + except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: @@ -139,22 +188,26 @@ class Buyer(db_conn.DBConn): def add_funds(self, user_id, password, add_value) -> (int, str): try: - cursor = self.conn.execute("SELECT password from user where user_id=?", (user_id,)) - row = cursor.fetchone() + 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() - if row[0] != password: + pwd = row.password + if pwd != password: return error.error_authorization_fail() - cursor = self.conn.execute( - "UPDATE user SET balance = balance + ? WHERE user_id = ?", - (add_value, user_id)) - if cursor.rowcount == 0: + 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.conn.commit() - except sqlite.Error as e: + self.session.commit() + # self.conn.commit() + except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: return 530, "{}".format(str(e)) diff --git a/be/model/creatTB.py b/be/model/creatTB.py new file mode 100644 index 0000000..d3f48f2 --- /dev/null +++ b/be/model/creatTB.py @@ -0,0 +1,5 @@ +from be.model.postgreSQLORM import Base,engine + +def createTable(): + # 创建所有继承于Base的类对应的表 + Base.metadata.create_all(engine) diff --git a/be/model/db_conn.py b/be/model/db_conn.py index f322cfc..cf5ba69 100644 --- a/be/model/db_conn.py +++ b/be/model/db_conn.py @@ -1,29 +1,34 @@ -from be.model import store - +from be.model import postgreSQLORM +from be.model.postgreSQLORM import User, Store_Book, User_Store class DBConn: def __init__(self): - self.conn = store.get_db_conn() + self.session = postgreSQLORM.session + return + # self.conn = store.get_db_conn() def user_id_exist(self, user_id): - cursor = self.conn.execute("SELECT user_id FROM user WHERE user_id = ?;", (user_id,)) - row = cursor.fetchone() + row = self.session.query(User).filter(User.user_id==user_id).first() + # cursor = self.conn.execute("SELECT user_id FROM user WHERE user_id = ?;", (user_id,)) + # row = cursor.fetchone() if row is None: return False else: return True def book_id_exist(self, store_id, book_id): - cursor = self.conn.execute("SELECT book_id FROM store WHERE store_id = ? AND book_id = ?;", (store_id, book_id)) - row = cursor.fetchone() + row = self.session.query(Store_Book).filter(Store_Book.book_id==book_id and Store_Book.store_id==store_id).first() + # cursor = self.conn.execute("SELECT book_id FROM store WHERE store_id = ? AND book_id = ?;", (store_id, book_id)) + # row = cursor.fetchone() if row is None: return False else: return True def store_id_exist(self, store_id): - cursor = self.conn.execute("SELECT store_id FROM user_store WHERE store_id = ?;", (store_id,)) - row = cursor.fetchone() + row = self.session.query(User_Store).filter(User_Store.fk_store_id==store_id).first() + # cursor = self.conn.execute("SELECT store_id FROM user_store WHERE store_id = ?;", (store_id,)) + # row = cursor.fetchone() if row is None: return False else: diff --git a/be/model/postgreSQLORM.py b/be/model/postgreSQLORM.py new file mode 100644 index 0000000..23c9b71 --- /dev/null +++ b/be/model/postgreSQLORM.py @@ -0,0 +1,121 @@ +from sqlalchemy import create_engine,MetaData +from sqlalchemy import Integer,String,ForeignKey,Column,TEXT +from sqlalchemy.orm import relationship +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker +from sqlalchemy import PrimaryKeyConstraint,UniqueConstraint +import sqlalchemy +Base=declarative_base() +class con: + def connect(): + '''Returns a connection and a metadata object''' + # We connect with the help of the PostgreSQL URL + + url = 'postgresql://stu10205501415:Stu10205501415@dase-cdms-2022-pub.pg.rds.aliyuncs.com:5432/stu10205501415' + + # The return value of create_engine() is our connection object + con = create_engine(url, client_encoding='utf8') + + # We then bind the connection to MetaData() + meta = MetaData(bind=con) + + return con, meta + + +class User(Base): + __tablename__ = 'user' + user_id = Column(TEXT, primary_key=True, comment="主键") + password = Column(TEXT, nullable=False, comment="密码") + balance = Column(Integer, nullable=False, comment="") + token = Column(TEXT, comment="缓存的令牌") + terminal = Column(TEXT, comment="终端代码") + +class Store(Base): + __tablename__ = 'store' + store_id = Column(TEXT, primary_key=True,comment="主键") + stock_level = Column(Integer, comment = "货存") + +class Store_Book(Base): + __tablename__ = 'store_book' + store_id = Column(TEXT, comment="主键") + book_id = Column(TEXT, comment="主键") + book_info = Column(TEXT, comment="书籍信息") + stock_level = Column(Integer, comment = "货存") + + __table_args__ = ( + PrimaryKeyConstraint('store_id', 'book_id'), + ) + +class User_Store(Base): + __tablename__ = 'user_store' + + id = Column(Integer, primary_key=True, autoincrement=True, comment="主键") + + fk_user_id = Column( + TEXT, + ForeignKey( + "user.user_id", + ondelete="CASCADE", + onupdate="CASCADE", + ), + nullable=False, + comment="user外键" + ) + fk_store_id = Column( + TEXT, + ForeignKey( + "store.store_id", + ondelete="CASCADE", + onupdate="CASCADE", + ), + nullable=False, + comment="store外键" + ) + # 多对多关系的中间表必须使用联合唯一约束,防止出现重复数据 + __table_args__ = ( + UniqueConstraint("fk_user_id", "fk_store_id"), + ) + +class New_Order(Base): + __tablename__ = 'new_order' + order_id = Column(TEXT, primary_key = True, comment = '订单id') + + fk_user_id = Column( + TEXT, + ForeignKey( + "user.user_id", + ondelete="CASCADE", + onupdate="CASCADE", + ), + nullable=False, + comment="user外键" + ) + fk_store_id = Column( + TEXT, + ForeignKey( + "store.store_id", + ondelete="CASCADE", + onupdate="CASCADE", + ), + nullable=False, + comment="store外键" + ) + +class New_Order_Detail(Base): + __tablename__ = 'new_order_detail' + order_id = Column(TEXT, comment='订单id') + book_id = Column(TEXT, comment='订单书籍') + count = Column(Integer, comment='购买书籍数') + price = Column(Integer, comment='单价') + + __table_args__ = ( + PrimaryKeyConstraint('order_id','book_id'), + ) + +engine, meta = con.connect() + +Base.metadata.bind = engine + +DBSession = sessionmaker(bind=engine) + +session = DBSession() diff --git a/be/model/seller.py b/be/model/seller.py index 2cf47aa..6e345cc 100644 --- a/be/model/seller.py +++ b/be/model/seller.py @@ -1,7 +1,8 @@ -import sqlite3 as sqlite +from sqlalchemy.exc import SQLAlchemyError from be.model import error +from be.model import postgreSQLORM from be.model import db_conn - +from sqlalchemy import and_ class Seller(db_conn.DBConn): @@ -16,11 +17,15 @@ class Seller(db_conn.DBConn): return error.error_non_exist_store_id(store_id) if self.book_id_exist(store_id, book_id): return error.error_exist_book_id(book_id) - - self.conn.execute("INSERT into store(store_id, book_id, book_info, stock_level)" - "VALUES (?, ?, ?, ?)", (store_id, book_id, book_json_str, stock_level)) - self.conn.commit() - except sqlite.Error as e: + # self.session.query(postgreSQLORM.Store_Book). + new_book = postgreSQLORM.Store_Book(store_id=store_id,book_id=book_id,book_info=book_json_str,stock_level=stock_level) + self.session.add(new_book) + # self.conn.execute("INSERT into store(store_id, book_id, book_info, stock_level)" + # "VALUES (?, ?, ?, ?)", (store_id, book_id, book_json_str, stock_level)) + # self.conn.commit() + self.session.query(postgreSQLORM.Store).filter_by(store_id=store_id).update({'stock_level':postgreSQLORM.Store.stock_level+1}) + self.session.commit() + except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: return 530, "{}".format(str(e)) @@ -34,11 +39,14 @@ class Seller(db_conn.DBConn): return error.error_non_exist_store_id(store_id) if not self.book_id_exist(store_id, book_id): return error.error_non_exist_book_id(book_id) - - self.conn.execute("UPDATE store SET stock_level = stock_level + ? " - "WHERE store_id = ? AND book_id = ?", (add_stock_level, store_id, book_id)) - self.conn.commit() - except sqlite.Error as e: + self.session.query(postgreSQLORM.Store).filter_by(store_id=store_id).update({'stock_level':add_stock_level}) + self.session.query(postgreSQLORM.Store_Book).filter_by(store_id=store_id,book_id=book_id).update({'stock_level':add_stock_level}) + + # self.conn.execute("UPDATE store SET stock_level = stock_level + ? " + # "WHERE store_id = ? AND book_id = ?", (add_stock_level, store_id, book_id)) + # self.conn.commit() + self.session.commit() + except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: return 530, "{}".format(str(e)) @@ -50,11 +58,20 @@ class Seller(db_conn.DBConn): return error.error_non_exist_user_id(user_id) if self.store_id_exist(store_id): return error.error_exist_store_id(store_id) - self.conn.execute("INSERT into user_store(store_id, user_id)" - "VALUES (?, ?)", (store_id, user_id)) - self.conn.commit() - except sqlite.Error as e: + new_store = postgreSQLORM.Store(store_id=store_id,stock_level=0) + new_user_store = postgreSQLORM.User_Store(fk_user_id=user_id,fk_store_id=store_id) + self.session.add(new_store) + # self.session.commit() + self.session.add(new_user_store) + # self.conn.execute("INSERT into user_store(store_id, user_id)" + # "VALUES (?, ?)", (store_id, user_id)) + # self.conn.commit() + self.session.commit() + # print('touch1') + except SQLAlchemyError as e: + # print('touch2') return 528, "{}".format(str(e)) except BaseException as e: + # print('touch3') return 530, "{}".format(str(e)) return 200, "ok" diff --git a/be/model/store.py b/be/model/store.py index d82aeeb..e69de29 100644 --- a/be/model/store.py +++ b/be/model/store.py @@ -1,63 +0,0 @@ -import logging -import os -import sqlite3 as sqlite - - -class Store: - database: str - - def __init__(self, db_path): - self.database = os.path.join(db_path, "be.db") - self.init_tables() - - def init_tables(self): - try: - conn = self.get_db_conn() - conn.execute( - "CREATE TABLE IF NOT EXISTS user (" - "user_id TEXT PRIMARY KEY, password TEXT NOT NULL, " - "balance INTEGER NOT NULL, token TEXT, terminal TEXT);" - ) - - conn.execute( - "CREATE TABLE IF NOT EXISTS user_store(" - "user_id TEXT, store_id, PRIMARY KEY(user_id, store_id));" - ) - - conn.execute( - "CREATE TABLE IF NOT EXISTS store( " - "store_id TEXT, book_id TEXT, book_info TEXT, stock_level INTEGER," - " PRIMARY KEY(store_id, book_id))" - ) - - conn.execute( - "CREATE TABLE IF NOT EXISTS new_order( " - "order_id TEXT PRIMARY KEY, user_id TEXT, store_id TEXT)" - ) - - conn.execute( - "CREATE TABLE IF NOT EXISTS new_order_detail( " - "order_id TEXT, book_id TEXT, count INTEGER, price INTEGER, " - "PRIMARY KEY(order_id, book_id))" - ) - - conn.commit() - except sqlite.Error as e: - logging.error(e) - conn.rollback() - - def get_db_conn(self) -> sqlite.Connection: - return sqlite.connect(self.database) - - -database_instance: Store = None - - -def init_database(db_path): - global database_instance - database_instance = Store(db_path) - - -def get_db_conn(): - global database_instance - return database_instance.get_db_conn() diff --git a/be/model/user.py b/be/model/user.py index acd58c2..d59cf85 100644 --- a/be/model/user.py +++ b/be/model/user.py @@ -2,7 +2,10 @@ import jwt import time import logging import sqlite3 as sqlite +from sqlalchemy.exc import SQLAlchemyError from be.model import error +from be.model import postgreSQLORM +from be.model.postgreSQLORM import User from be.model import db_conn # encode a json string like: @@ -42,6 +45,7 @@ class User(db_conn.DBConn): def __check_token(self, user_id, db_token, token) -> bool: try: if db_token != token: + # print('touch') return False jwt_text = jwt_decode(encoded_token=token, user_id=user_id) ts = jwt_text["timestamp"] @@ -54,31 +58,47 @@ class User(db_conn.DBConn): return False def register(self, user_id: str, password: str): - try: + ## 判断用户是否注册过了 + if self.user_id_exist(user_id=user_id): + return error.error_exist_user_id(user_id) + else: + # try: terminal = "terminal_{}".format(str(time.time())) token = jwt_encode(user_id, terminal) - self.conn.execute( - "INSERT into user(user_id, password, balance, token, terminal) " - "VALUES (?, ?, ?, ?, ?);", - (user_id, password, 0, token, terminal), ) - self.conn.commit() - except sqlite.Error: - return error.error_exist_user_id(user_id) + ## 为新注册的用户创建对象 + new_user = postgreSQLORM.User(user_id=user_id,password=password,balance=0,token=token,terminal=terminal) + self.session.add(new_user) + self.session.commit() + + # self.conn.execute( + # "INSERT into user(user_id, password, balance, token, terminal) " + # "VALUES (?, ?, ?, ?, ?);", + # (user_id, password, 0, token, terminal), ) + # self.conn.commit() + # except sqlite.Error: + # return error.error_exist_user_id(user_id) return 200, "ok" def check_token(self, user_id: str, token: str) -> (int, str): - cursor = self.conn.execute("SELECT token from user where user_id=?", (user_id,)) - row = cursor.fetchone() + row = self.session.query(postgreSQLORM.User.token).filter(postgreSQLORM.User.user_id==user_id).first() + # cursor = self.conn.execute("SELECT token from user where user_id=?", (user_id,)) + # row = cursor.fetchone() + # print(row) if row is None: + # print('touch') return error.error_authorization_fail() db_token = row[0] + # print(db_token) + # print(token) if not self.__check_token(user_id, db_token, token): + # print('touch') return error.error_authorization_fail() return 200, "ok" def check_password(self, user_id: str, password: str) -> (int, str): - cursor = self.conn.execute("SELECT password from user where user_id=?", (user_id,)) - row = cursor.fetchone() + row = self.session.query(postgreSQLORM.User.password).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() @@ -95,13 +115,17 @@ class User(db_conn.DBConn): return code, message, "" token = jwt_encode(user_id, terminal) - cursor = self.conn.execute( - "UPDATE user set token= ? , terminal = ? where user_id = ?", - (token, terminal, user_id), ) - if cursor.rowcount == 0: + row = self.session.query(postgreSQLORM.User).filter_by(user_id=user_id).update({'token':token,'terminal':terminal}) + + # cursor = self.conn.execute( + # "UPDATE user set token= ? , terminal = ? where user_id = ?", + # (token, terminal, user_id), ) + # if cursor.rowcount == 0: + if row == 0: return error.error_authorization_fail() + ("", ) - self.conn.commit() - except sqlite.Error as e: + # self.conn.commit() + self.session.commit() + except SQLAlchemyError as e: return 528, "{}".format(str(e)), "" except BaseException as e: return 530, "{}".format(str(e)), "" @@ -115,15 +139,19 @@ class User(db_conn.DBConn): terminal = "terminal_{}".format(str(time.time())) dummy_token = jwt_encode(user_id, terminal) - - cursor = self.conn.execute( - "UPDATE user SET token = ?, terminal = ? WHERE user_id=?", - (dummy_token, terminal, user_id), ) - if cursor.rowcount == 0: + + row = self.session.query(postgreSQLORM.User).filter_by(user_id=user_id).update({'token':dummy_token,'terminal':terminal}) + # cursor = self.conn.execute( + # "UPDATE user SET token = ?, terminal = ? WHERE user_id=?", + # (dummy_token, terminal, user_id), ) + # if cursor.rowcount == 0: + # print(row) + if row == 0: return error.error_authorization_fail() - self.conn.commit() - except sqlite.Error as e: + # self.conn.commit() + self.session.commit() + except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: return 530, "{}".format(str(e)) @@ -135,12 +163,15 @@ class User(db_conn.DBConn): if code != 200: return code, message - cursor = self.conn.execute("DELETE from user where user_id=?", (user_id,)) - if cursor.rowcount == 1: - self.conn.commit() + row = self.session.query(postgreSQLORM.User).filter(postgreSQLORM.User.user_id==user_id).delete() + # cursor = self.conn.execute("DELETE from user where user_id=?", (user_id,)) + # if cursor.rowcount == 1: + if row == 1: + self.session.commit() + # self.conn.commit() else: return error.error_authorization_fail() - except sqlite.Error as e: + except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: return 530, "{}".format(str(e)) @@ -154,14 +185,16 @@ class User(db_conn.DBConn): terminal = "terminal_{}".format(str(time.time())) token = jwt_encode(user_id, terminal) - cursor = self.conn.execute( - "UPDATE user set password = ?, token= ? , terminal = ? where user_id = ?", - (new_password, token, terminal, user_id), ) - if cursor.rowcount == 0: + row = self.session.query(postgreSQLORM.User).filter_by(user_id=user_id).update({'password':new_password,'token':token,'terminal':terminal}) + # cursor = self.conn.execute( + # "UPDATE user set password = ?, token= ? , terminal = ? where user_id = ?", + # (new_password, token, terminal, user_id), ) + # if cursor.rowcount == 0: + if row == 0: return error.error_authorization_fail() - - self.conn.commit() - except sqlite.Error as e: + self.session.commit() + # self.conn.commit() + except SQLAlchemyError as e: return 528, "{}".format(str(e)) except BaseException as e: return 530, "{}".format(str(e)) diff --git a/be/postgreSQLORM.py b/be/postgreSQLORM.py new file mode 100644 index 0000000..23c9b71 --- /dev/null +++ b/be/postgreSQLORM.py @@ -0,0 +1,121 @@ +from sqlalchemy import create_engine,MetaData +from sqlalchemy import Integer,String,ForeignKey,Column,TEXT +from sqlalchemy.orm import relationship +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker +from sqlalchemy import PrimaryKeyConstraint,UniqueConstraint +import sqlalchemy +Base=declarative_base() +class con: + def connect(): + '''Returns a connection and a metadata object''' + # We connect with the help of the PostgreSQL URL + + url = 'postgresql://stu10205501415:Stu10205501415@dase-cdms-2022-pub.pg.rds.aliyuncs.com:5432/stu10205501415' + + # The return value of create_engine() is our connection object + con = create_engine(url, client_encoding='utf8') + + # We then bind the connection to MetaData() + meta = MetaData(bind=con) + + return con, meta + + +class User(Base): + __tablename__ = 'user' + user_id = Column(TEXT, primary_key=True, comment="主键") + password = Column(TEXT, nullable=False, comment="密码") + balance = Column(Integer, nullable=False, comment="") + token = Column(TEXT, comment="缓存的令牌") + terminal = Column(TEXT, comment="终端代码") + +class Store(Base): + __tablename__ = 'store' + store_id = Column(TEXT, primary_key=True,comment="主键") + stock_level = Column(Integer, comment = "货存") + +class Store_Book(Base): + __tablename__ = 'store_book' + store_id = Column(TEXT, comment="主键") + book_id = Column(TEXT, comment="主键") + book_info = Column(TEXT, comment="书籍信息") + stock_level = Column(Integer, comment = "货存") + + __table_args__ = ( + PrimaryKeyConstraint('store_id', 'book_id'), + ) + +class User_Store(Base): + __tablename__ = 'user_store' + + id = Column(Integer, primary_key=True, autoincrement=True, comment="主键") + + fk_user_id = Column( + TEXT, + ForeignKey( + "user.user_id", + ondelete="CASCADE", + onupdate="CASCADE", + ), + nullable=False, + comment="user外键" + ) + fk_store_id = Column( + TEXT, + ForeignKey( + "store.store_id", + ondelete="CASCADE", + onupdate="CASCADE", + ), + nullable=False, + comment="store外键" + ) + # 多对多关系的中间表必须使用联合唯一约束,防止出现重复数据 + __table_args__ = ( + UniqueConstraint("fk_user_id", "fk_store_id"), + ) + +class New_Order(Base): + __tablename__ = 'new_order' + order_id = Column(TEXT, primary_key = True, comment = '订单id') + + fk_user_id = Column( + TEXT, + ForeignKey( + "user.user_id", + ondelete="CASCADE", + onupdate="CASCADE", + ), + nullable=False, + comment="user外键" + ) + fk_store_id = Column( + TEXT, + ForeignKey( + "store.store_id", + ondelete="CASCADE", + onupdate="CASCADE", + ), + nullable=False, + comment="store外键" + ) + +class New_Order_Detail(Base): + __tablename__ = 'new_order_detail' + order_id = Column(TEXT, comment='订单id') + book_id = Column(TEXT, comment='订单书籍') + count = Column(Integer, comment='购买书籍数') + price = Column(Integer, comment='单价') + + __table_args__ = ( + PrimaryKeyConstraint('order_id','book_id'), + ) + +engine, meta = con.connect() + +Base.metadata.bind = engine + +DBSession = sessionmaker(bind=engine) + +session = DBSession() diff --git a/be/serve.py b/be/serve.py index 6499a7c..8d6ce72 100644 --- a/be/serve.py +++ b/be/serve.py @@ -1,16 +1,18 @@ import logging import os + from flask import Flask from flask import Blueprint from flask import request + +from be.view import testconn from be.view import auth from be.view import seller from be.view import buyer -from be.model.store import init_database +from be.model.creatTB import createTable bp_shutdown = Blueprint("shutdown", __name__) - def shutdown_server(): func = request.environ.get("werkzeug.server.shutdown") if func is None: @@ -23,13 +25,10 @@ def be_shutdown(): shutdown_server() return "Server shutting down..." - def be_run(): this_path = os.path.dirname(__file__) parent_path = os.path.dirname(this_path) log_file = os.path.join(parent_path, "app.log") - init_database(parent_path) - logging.basicConfig(filename=log_file, level=logging.ERROR) handler = logging.StreamHandler() formatter = logging.Formatter( @@ -37,10 +36,13 @@ def be_run(): ) handler.setFormatter(formatter) logging.getLogger().addHandler(handler) - + app = Flask(__name__) - app.register_blueprint(bp_shutdown) + createTable() + + app.register_blueprint(testconn.bp_testconn) app.register_blueprint(auth.bp_auth) app.register_blueprint(seller.bp_seller) app.register_blueprint(buyer.bp_buyer) - app.run() + + app.run(port=5000) \ No newline at end of file diff --git a/be/testconn.py b/be/testconn.py new file mode 100644 index 0000000..f880222 --- /dev/null +++ b/be/testconn.py @@ -0,0 +1,22 @@ +from flask import Blueprint +from flask import Flask, abort, request, jsonify +import json +from flask import jsonify +from sqlalchemy.ext.serializer import loads, dumps +import postgreSQLORM +from postgreSQLORM import User,Store,Store_Book,User_Store,New_Order,New_Order_Detail + +bp_testconn = Blueprint("testconn",__name__,url_prefix="/testconn") + +@bp_testconn.route("/test",methods=['GET']) +def test(): + user_id: str = request.args.get("user_id") + print(user_id) + try: + ss = postgreSQLORM.session.query(User).filter(User.user_id==user_id).all() + for i in ss: + print('user_id',i.user_id) + except: + print("error") + return "connect success" + diff --git a/be/view/__pycache__/__init__.cpython-39.pyc b/be/view/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d98c856808a372d93bf1912cb00d8e178d180ab9 GIT binary patch literal 137 zcmYe~<>g`k0WA;^Q;(GE3s)^$IF)aoFVMrl? literal 0 HcmV?d00001 diff --git a/be/view/__pycache__/auth.cpython-39.pyc b/be/view/__pycache__/auth.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..adcc07967e26baf1b90fa0224010509e3b088e20 GIT binary patch literal 1915 zcmchX&2HO95P-S6T$1{A;y6y5{vUc!fZ9NhMNt$fkV6ix0XIDm0tDK-mMK%DvLx$9 zrB3cuZ_tB%^eYs7lD+oSSLmrTLs3?Y)V-C&4rgb7IQz})M7>_yf#;83mM5=#$N3XG zn~#Lfx6tz6K`2MD#F?^?G1NKeJmjPc&_yUncN2FiL&+S?l+>Q`l)n_Aul-4&0@WHb z)n0PdQQcpiOBS}s-do%IYK!b`vOiecAF6G#cgX%|ZQoIk$=)UV?%MuDy+`(*djH57 zJpBv&cLvP1o+qWAnK&(=;~V|D)H$h>JWJ!#H(+(kTpQ~~WpOr_`}hH4yEMsYX7p+N z^W57{vT>YR_wf6pA8?zgF3vKQpWr{52WUD-?>lID2%>N%?20R<_%&ZNJwZLT8gr?~ z3vuOMI}1^XiL9K8Rb0uX7>b3vkPENyDp>*5-}oh~+*1yx^AD_#PLE<`9UIJ|Jio|{ zvO%HEG)|*rAPmOYbW!v`3^;n7=h0YOS!Cxr9r#ATfOQds6=Pi(bl&8CBJWJQI?<2@C7N>AG(06YY20`#8Xa^EBh(V5NPTB z5I%&BvE@{zC@Ba5+UA}8GHo{gKOmS7{^OYKTYu=F<|9~8hm?X#as3!X2jOXS(J|T?E)$-Uj6$|;P>WJ6!&MxXE0?C+MSZI!wilb z4Ek1{CQ*KFIPN7-;BRbjtoNo+u#&pO1*1_KP4#GG{o~mP>yecPN{yzr@kmY1IA#D=7Yr7@YT0$x( zr2YdA?UBE<&O z2u2V=M`TQ6N)a=_EM^uvfSuT}*d4iJ9&<`06pn`0g-TpU8tGQvw3rtykNx@wBll-)5rd;Z^5P z0|1ip6h`qLOi6a=2@~{`*5{Z3re}T!FdLBC(d-#{bEkH-3(+okxkVh1r=1f=bM5tE zCnbCLO81D=zV=VJCYoyJ)af{NP=|F?dOFmR@IJ94s)IfQD*R33SA|r`P?(@7GbIu6 zZkFv9h9T@_70|=5prS|z(ge0p2y6Swff|g9Y#C=DOXH<^E+;}^ktUq8qFk7_8w%S+ zAqlDpCTDyvFq+sZPl@Z6aW7ZowV bBRH@c$;T8T3hdQcgEm=^mBW%&{q8KiZ literal 0 HcmV?d00001 diff --git a/be/view/__pycache__/seller.cpython-39.pyc b/be/view/__pycache__/seller.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8802f94b2c7aca5a2c9089bbfa3888841ad483ea GIT binary patch literal 1415 zcmb`GO>fgM7{_Dhy-i>C0s<~b+$zB)aYP7BL*l?;Oe&|SB5G@QWJ{W2Cxcb#X}j*i zCuom+C0{x56*%!cPCEhvPDJvPzaLxA%g^?()oK{-lXB@zgpTRJL zk;F(zNC;{Qnub(s6SNtcT3d;g+M%troj9Sx33Is1T;^Syp~t;bpZTnDLRj;fvVgU& zj7t(Ww7-4h@35}+H?@E3#=p&Wv_D{W-{|drgSw0!QT}04@R^9GIZRx^KNMVQc`CDM zJh=d`BYBc=aU`&*xw~IYVWCloB$^36i9gL-`(wd}IgezX39hW;H~qI5G3ELDjL9*k z+k6T@(u&C?Da{Fm zcB~`i7Lto7X3EnQpn~L54o`T`6((d+7WSmf6Q1iJrO35 z`WDfE1jHj*w%!-qZ$z(i;LpvBvVZQFg}YCe$Ep?pejXUrb+cY zOO)dgKum_rNpnYO=M8Zvl2-n+E(2#Qy*cNUb$ehdI9>b?Zpo3Mo?^?4(wrhFSrw zuJNCMiU&~cZHV{58@d>9TBQF5sUtju{kP!lQoYt|DSMI(<(Z(E%iJVX-iYs|@H~?0 zeDS!I7e&)y%A-j6qghlPk+MZrNM_?mt{RPQ+iEE4_#FO<9s249GNCA3Z3 Kq~XB`+T;g#^*3n% literal 0 HcmV?d00001 diff --git a/be/view/__pycache__/testconn.cpython-39.pyc b/be/view/__pycache__/testconn.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06f9f69f266e3957b34efc7650e152afca9ce010 GIT binary patch literal 934 zcmY*X%We}f6!rDIC(o7&vEa3x1qHF_0wF-96bV5K6ojyXMoH|1N#~K;4y94LD%BsSaCg7Q1NKaoO|!szUS!nTdkPjdb~It{-A{Xvccu$VekZB^&No|4ml}+ z0a#9vQ$`DiIfcvI!ed^YcXFTkSa-3$%z1fGgeO^owF#s+m6U?m6j2ll# zS;=|FN)bbSTg`?;p;Xe4b|8$~mt$p|vCzh=eV2hv2MYhms?vDqxjd4gP5PrO*Ld8j z4V-?SC(Z?@N*Tz05_tnFf7Z7j^akj)vgY@!>$Tl?Ucb2C8;IVQOdR%>j;>FSjB5is zyUHF+XcI!9a2;_Kd}xEbh1q1ycq2Ow5@(x8>#KAvSQYgc7}w4P3kPDosJO^$A?)fh zT>o!GYC$rxd+p7#VWDZEg9lhq6ju>I6hFTu@v+e5s0mWxM# Tk?JBe;Tq~_;&Yp}X&e3m7Q62u literal 0 HcmV?d00001 diff --git a/be/view/auth.py b/be/view/auth.py index 8d9528a..5a3d781 100644 --- a/be/view/auth.py +++ b/be/view/auth.py @@ -3,8 +3,7 @@ from flask import request from flask import jsonify from be.model import user -bp_auth = Blueprint("auth", __name__, url_prefix="/auth") - +bp_auth = Blueprint("auth",__name__,url_prefix="/auth") @bp_auth.route("/login", methods=["POST"]) def login(): @@ -20,6 +19,7 @@ def login(): def logout(): user_id: str = request.json.get("user_id") token: str = request.headers.get("token") + print(token) u = user.User() code, message = u.logout(user_id=user_id, token=token) return jsonify({"message": message}), code diff --git a/be/view/buyer.py b/be/view/buyer.py index ce26221..315e484 100644 --- a/be/view/buyer.py +++ b/be/view/buyer.py @@ -3,8 +3,7 @@ from flask import request from flask import jsonify from be.model.buyer import Buyer -bp_buyer = Blueprint("buyer", __name__, url_prefix="/buyer") - +bp_buyer = Blueprint("buyer",__name__,url_prefix="/buyer") @bp_buyer.route("/new_order", methods=["POST"]) def new_order(): @@ -40,3 +39,4 @@ def add_funds(): b = Buyer() code, message = b.add_funds(user_id, password, add_value) return jsonify({"message": message}), code + diff --git a/be/view/seller.py b/be/view/seller.py index 3f56eed..72ea40e 100644 --- a/be/view/seller.py +++ b/be/view/seller.py @@ -4,8 +4,7 @@ from flask import jsonify from be.model import seller import json -bp_seller = Blueprint("seller", __name__, url_prefix="/seller") - +bp_seller = Blueprint("seller",__name__,url_prefix="/seller") @bp_seller.route("/create_store", methods=["POST"]) def seller_create_store(): diff --git a/be/view/testconn.py b/be/view/testconn.py new file mode 100644 index 0000000..aa06535 --- /dev/null +++ b/be/view/testconn.py @@ -0,0 +1,21 @@ +from flask import Blueprint +from flask import Flask, abort, request, jsonify +import json +from flask import jsonify +from be.model import postgreSQLORM +from be.model.postgreSQLORM import User,Store,Store_Book,User_Store,New_Order,New_Order_Detail + +bp_testconn = Blueprint("testconn",__name__,url_prefix="/testconn") + +@bp_testconn.route("/test",methods=['GET']) +def test(): + user_id: str = request.args.get("user_id") + print(user_id) + try: + ss = postgreSQLORM.session.query(User).filter(User.user_id==user_id).all() + for i in ss: + print('user_id',i.user_id) + except: + print("error") + return "connect success" + diff --git a/fe/__pycache__/__init__.cpython-39.pyc b/fe/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ac3e14b19b1cdf9d55e54a9ca97b9692115c0ab GIT binary patch literal 132 zcmYe~<>g`k0{^4-*zBgDr`~$$x%3zM zH$8jprTK-PI;&U;onhYYz8&7YUB6m23C8*JOJHb(e5%9WK#ugVgoVHe5T=2~a*)H) znGSiDhXN}=krlyU29#I{%B&0~GhNcCY))rVuDY#OyK~jFFx%Zr%d%SGhe1e|L(NRh z&(xUkOGoJ0H4;9(zLAU}HyAc5TYWNipl-+UoDS0k9r1*^GEO+ucgrt15j+9YAjUGKMB!{tJR@e+>5{2}E+?qv>SpHKZXl1ew2Q-?qD2C!>EWCCh^U;5Pc zWiX>|xZ!Ywm(=l-drtfIJ4x_ad-y&ZbiF(DER|%9w0=Qg2s_>K^a9T0*L}43lY+sES>JWYv+>lo|)StN(2>1 zH1HpslE1Vq6@P(>nRPIMJ>Bf=Yi7Qg$@~2-!*THC>vSd<`$3Dl!^6cf{>?RtQzn_@ z6-&9B#ljPevxT1qe0>t8p*xAv2xn2ni%!~cXI|A^^wOTw{VG}X(?04v-%`=}KyAz5 zh{;e!pIN#iW7)xZS9WC&=RL_!*f9Bt{@HlQZPY?_UY8oxpi%H%q2f<#J+q-X1C`4u z-Ml-Hi#^A`Nl+NJ;x`zzWN4L-hXM#O4GWb)tG_b{ap}ab;fupbQP&rZsX{&r z4nm=N3O^x6A+`Ea?)=H>EzJGvyY0wEPUde8GbH| zC&f3O`^H}dn;5ZP4_7q2{IDC$C5ynjGfJ3_}|%q1489)(I%}+=g#mE?fW* zpdU;YUU$zZ@N)ha6e2p`US5&iY<=2-+Q!|6vcW{m6AlB^{$U};4a)&8jH5sv@sS&E z<$vHeL>8<M~sdx2C@!5iqt!O^UB7c-nAHCV?AVE zBl*+^Kn;v#+``Fv*c|_Z?cRd5dV}@=?>1B$hG1PDbGVQC@Scr}wyaF48=D+2ud>bR zVYW6h${XxCQ`UL}>Jmz$Y-h7&qd$9HeC(2$1MHw>pq{V^23M8EXqf{VAwDY#<@(Qx znR2iW45(4*?_j!?bw!Mi7PV|E^_2Rop$a}ix`aNl<;OuB F{RWI+>T>`9 literal 0 HcmV?d00001 diff --git a/fe/access/__pycache__/__init__.cpython-39.pyc b/fe/access/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f0af22b3e7fd17bbe92e43be384ec20a59356a9 GIT binary patch literal 139 zcmYe~<>g`k0PrA432D literal 0 HcmV?d00001 diff --git a/fe/access/__pycache__/auth.cpython-39.pyc b/fe/access/__pycache__/auth.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b8ae41bf4027300f07e9ad588509ef58714f8b2 GIT binary patch literal 1833 zcmb_c%WfMt6y_A!txlL$$6_Kif5=ABukdB#5%-;y%@<`>%xGe> zMHt-2=YD`OY{E602+g%PVH0Uo_(ev|g_fsED;=GvN!-lp_*CkS?qa6Xdg?8B^>iO| z-E*%2yoP!kGg}+`cJwZ0diok*?s@gqs(L&VfY3JTQ^?=obGtAVtGVXKqGky&VwV^n zMJcv@J`$F^eGf4vOKaxY^O5k%nS5>)7S5Ojq3pNY-`<-(D$6IXDy^A*jow4*-Ffi+ z-Ray+)7i{8H>D%@moI!bNwOlVl7#lU0F56F3Fm&hGE(5x8JlFR(4ldN>mE8auSJb?oyxUBjBEk!kHtEw#6s3lt+ae8)^Qy#R2{#H zUb9!RRddcVF-=u!Z1F-Z<`Bk_fQxk$ImCf!YZ1I)>!o2tA7h7k|bogxM&gy?3Mn8b2s=om?nm zP?%>IBO3^Kt2A!o{QoYEK*2e^zK=^Ev})|*&UVnqgeb8e!n~2;A2RvTve$2&SR58%C3pzZ;=K(A;{0L@9nw%6stG!x$rLYE`9^P%a8i4pmE#( zC}8^m?!p^Zv>FQ94T-WJ5zs4Ayn(qp1h1*KUQ=y50o>&w<58bpvLZb+N#c7+a#-qB zPW?fWJYA)EvtsEGFI{E5%!(?MvL&%Mk|8QAUAO@vzzKCvX{A&;Dl5<=uXlqiejg0q t?d^3et)n2Q^85f#N1i>}U#1ohC%vj+`Jc}9-7gxjUvjuPsuW~E{sriRW!nG% literal 0 HcmV?d00001 diff --git a/fe/access/__pycache__/book.cpython-39.pyc b/fe/access/__pycache__/book.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa0135da0a0dc8a36ad660733fb3901ffd78ab31 GIT binary patch literal 2700 zcmaJ?&2QX96!-Xho!w2Eq#r4zwJJWkuq_Cx3ZV+BGzl$gQ)tV9RVvH7<7}O7?d{kr znw4{EBrY6!MjUpJ{4*Rm%&8Km{S)8;}*W`4g}XY8)%(UvyQIXM#oUv?3hYh9s4Vd>)hDaxbaHwIB1#NLd!zS zOwMkWTCcQGX|vK+rR_>P&=%&om9AC& zUZv+MU9WVb(oNERhMDs~wn7UxHGYaO?rR-~FJb@7(p*i`XHt*3wDLF~MA8mN`O{R$ z+Hlkz#M#qG$Yv_yew>7Zpd8}mB22PDm}8iWVZm+`3TX|)ew0CpxED#M8z($Y`qGTE zZX)aDszIFOB9&ejq!o60X_7}tF3mjbXIL-p)i#fa)6_>NcJXDGAw1^(&+9QySL6Q^inRS( zw8(XcgHYsik-_y}7&o}NZz13=r)doK1jS+hG&ElE#!x*@%raGlGX`HlsBaz|e8Y2DS z#4%;FALW6vjiPN~z3RkuoL2wa)Lk|{U7h&ESSD=|;p!$mI`P5N0C4b?!GVqUan2)F zFbk8cQ0N8QMkwrAg|()=W=}5f*}3^j+j9z=Y*ILZ1!O2>1DOiZUrQku$X2KZmT8Wxh0J zYub|wdtTv9PER$y{LBz<3TNlcdh8JB5KrIkP$bt%{VGw|$kM+kTmC z+x}q=Z~Mn{I7S}ka5YTja3IRzP?W>lJ|YD-qPH82kPh2^mD1ZjrSt=mGL7RW-6)mb zF|SPNAVEsUYGq3QH-P;I57*Wo`m5jjG57D?y?^(y|E2$6W8={}fQs%Jh4_rJ%#5OG zMi*&DNoHn~pop4LYMj+bQ0bq|k)Z22qnMjDNz9X=dLfx7wXrqIx37NIx+LC5m$*WL zu8g2KSJ_h#nIJMjWP->9kqIIbL?(z#5Lu^j%szs+1#t`F7Q`(Sx0MZXPo;%Q5D!(6 zLX{m3qXb14Ug)FfLhVzb3ITCO+?4snje3WVDIpsbMB zsFNZ>d`p7r`VpZD=0)^TD$mGoE?cO%j-b9)P54mKDHGs9 g6KRqxd1&ep3dKk~(!E(0`!6U;Rf0UM%|`R=KNRJHC;$Ke literal 0 HcmV?d00001 diff --git a/fe/access/__pycache__/buyer.cpython-39.pyc b/fe/access/__pycache__/buyer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9361493338946cb9c5b9367c29b91bbed34dec4 GIT binary patch literal 1813 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 VnszRI{AqWPdvx!22rt->{{^^Bgm(Y{ literal 0 HcmV?d00001 diff --git a/fe/bench/__pycache__/__init__.cpython-39.pyc b/fe/bench/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9323d2bea3db75fe88d2995dfc397821f018b174 GIT binary patch literal 138 zcmYe~<>g`k0vUbvGhHa;o4({D$`E zFYVQnzu?K)v`PnN_RX7_<;`x~XsiO+?%R9s0|CBlvTTf!BXYe%L4d#nMi?Sm%n~-@ zAt%g*^9rFO+zte_Z|Z~qjdzu)ha`&y;d)1EJ;>6Yt^Jup!1@WfzM+uA1WG7iiZejy zLy0*PSiq1^*eP6Zl`MA(m|)2ZoVo>{k&egh0;%Q`$EP(r_t;uu>J@V#fRwSeq7@u`)CLEJ zY5fVxr;(rCvsTp2vIm`KN=ClLBB3 zJ?7v#dgwC`SIN~H@$JA3H|}J!YHvO-o_4;;`ai#{z8b4UErkYMWxRt?CY};`XrDvd IFYwXlzo=Vy`Tzg` literal 0 HcmV?d00001 diff --git a/fe/bench/__pycache__/session.cpython-39.pyc b/fe/bench/__pycache__/session.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a49bb3b0f7bfcdd928f809f4ab86d3303af9b80b GIT binary patch literal 1770 zcmZuyO=}}Z5bd6xFMZn^>|K_S1ag`{bnr2RW!Z!z>_J)ZLO>`CV|B|bS)P%4Mi`sX z$%b6=6LOG_3;T=unv?%P4!I<+dL&t1c0|9as_veuepS^Ncc)(8`COB1jKF(6OajvFA2jAH~B$I<5F!Hy6f=&3! zDcKrlE_umfan69QMNg8&w-{IqE!Hg7EjA>rZ+?c~uUBwwu6KgeJsJt+pSw+y!P}>^Drtz?RZ0cKkc43+i z6VTel_)^6?lWAIgv)uSqXr^_p(s-t`p^^)&BFDJ7nvS%O1H5PYDPI3}fBJ54mSq=t zk!dw}1?iNeZ{NH=8I086Or^tjgS;ZWJG<6Yb2W_o8G!L7_doHwIoPDByCq~uq-`I{ z5>=l>MW71iF51x$bNsmwAxCn*%JAixGS%8D2wwpilw`;c~~V%?-HNGMhk=dwK2#~XYHdO@f}3@ z%hKOP=~I+Tu@_-yFTxIXv^Ej75a9>t?Ty}^f3Q6r&V8znNc8S01NRaT9aLF&sX_Et zu;?cQ9fCswszl?REv}W;Eiw@AMod*&l~!XhlS!fCyhsY&rUeHCp8=wvO5PW=!#`6a zbdGV*o?+GSV`;o(R48qNO>2IXXZi^BrXI(anOsasZpQI^kxZ)@O(kXf*p_$23B|A%8`ZqF9pFL2 zzYEI=Lf&qNUMMtK;q7pwy7q?XZm+xQf8QaI?EnA( literal 0 HcmV?d00001 diff --git a/fe/bench/__pycache__/workload.cpython-39.pyc b/fe/bench/__pycache__/workload.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95307b46454fd2de9129c07285ab924bfdba3567 GIT binary patch literal 5420 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 literal 0 HcmV?d00001 diff --git a/fe/test/__pycache__/test_add_book.cpython-39-pytest-7.2.0.pyc b/fe/test/__pycache__/test_add_book.cpython-39-pytest-7.2.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f847a4489f52752792fced8512f8718a58e81956 GIT binary patch literal 3144 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 F{sNKdGVTBX literal 0 HcmV?d00001 diff --git a/fe/test/__pycache__/test_add_stock_level.cpython-39-pytest-7.2.0.pyc b/fe/test/__pycache__/test_add_stock_level.cpython-39-pytest-7.2.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb0ae452792a78905ada5e2ded9662848be2bb17 GIT binary patch literal 3079 zcmd5;TW=dh6rS0;uW6Gsy>M$w3w1>eX=w$eL1`%V0hO1orAikvQ!in9ePlcfq(Gg4d&;zUT+7B^We!ca&Uw$`GkS;t9} z&yHb>Fe6L@sBpew?V_{fFv|A2Idg99MY69iyOPf z?3AoqpmP#8lh&P01Nt8Hyg?4o9@0LT-ZxU38cm~bre^#{k{=Yfm6{F8Z5(eHLyJ2} zaZnnP8zlY?^yL(Gl|O>cCa<#ZP^-*&EEEl{}xiL-TP<@6xyp>+WGI%y=PI$X>Jb+sLz$pKIQO9J$FM`9XPk!_ zFnC^K&TQELm4nJ@M6%^4%8V1KtZp~p%0`@5uC@*OUS3xURk|jU z%eBSw`v1XP=y1ZHQI$jRu_(;Ir*)sCI6txekO{cH1my2T9JDANsS%QR1?={K}@YUOd7s6KhACo;wdxc=_|P(=i)>Rz9wbe%%I zlXYMZK%lRKsI^mrL!I|cU<0WA)M}c2JGJBA5@+B78`zo+V0_F5z#p0oIOy}K32e{? zseqDZ1C*^DHgGf>IGPRIqzE%hP|*+B!0ubufygqILrMtB9`D8ey- zktbh+M$xr#TENoUzSnWaDTE5bX#~ua49JFz>) zyI*_O_+o5zjGv46$~WQM@*KhigvZ=9GjVRsIxOHAkw^V?a!-G4zxRI}2E_nn@jMj7 zzc_3%zcgh99Mk_%f9;)L%H58P47Ey;OID&!66BIFQstv<>UPtQPCXJFLC zVxI8g9PJ%`O4dcqrAl6TOkZn^sXSw?h<8H)a*?s?T|dMN4|+~^fhxBVY$RPNWEIVO z7vUnpdkB{h9+rickV>QlfQO2U03L8he#&$3r!|$5^0seZO=s#b%eJd#S0CJ=RVi-D zAc4DgXGpo@v5X8CVQDqn5LLfk7jayD_+6~O3~IR@mA;SV49wTtKgnX{UCJEsK7N>J LXC9|T_<80(M64aV literal 0 HcmV?d00001 diff --git a/fe/test/__pycache__/test_bench.cpython-39-pytest-7.2.0.pyc b/fe/test/__pycache__/test_bench.cpython-39-pytest-7.2.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f63b0114e24fe98b99c3c6c5800167319f118e5 GIT binary patch literal 840 zcmYjP&1(}u6rVS{n~$}vt%4$W=tXe_LyWb8m{OH`@KA&vic27DG7}BmFJ?B_glrG3 zkb~mMqlf_y3LZQb5xn|0%vD0oztEF!cH5ePdGGgrZ{~f?c=Pi%!F6-=w*3wDA8pJo zipDx_Swq1H1E08%X&M-m00~Uj0_~xGAt<^<#0E286Su@*i#XO4?~zRhR9W=GW{ZdI zmu*d*t^xvG!eiX>Gm3$okOK_7O~UskNud7`NQ(Ag$RGtqQ#ynp-Jz*5G~`}FKN$>B z2bih(4jr4wAs$1f=@^*xfnFl1<}Fr0yLg$f($MSzvQ|<+zBshTZ~*(*nn_Z?ZKQOY zJjcdTvPVKY*HuzQ2HPrcPJd&qQ-;EUV_L5}Ft~8-M%=&c$mM!{S;G}aI@C3g(_*D} z6%Qv|CixWp{u&*9c{3UPIC}Se@^gQ3csN+J*E}h?NV4mzj@0*7os!V6pvoJ&Z5}7x zC{*@(+|MF;LM=7hp6@pWk3~BQVoz{YZc4AiHG|$xBmysK=79tGLM=SZa$uYdAtIqJ zo*v=5vG0YR&fpXjaQ7UhIk{M!HSVYxPc8T4Y3|M%_r4Nw9xFetKDpm$MbVB-BEcJv z5N&C6>)F#-tGIlxj}bd1hT{ z=EJGvEn_zo!C#4Pf`d7uRPlrpMU3Xob$BKFn-%<}*|@VTS@|dEtsQ3^E3n>*sR;1O7cU@lc>}PiO zk;JtxxDppYoDm26=>LSjVNXb$%Ab%EGy6ht+VsSQC+)o1nc1D$ncwWDtE+Va-_0L> z?4}+ef8u2M0~vV$Lw^oL5J7X&q3+N69wU_W{Z2qDP1p%R!}6#fcj6OStyBAq2v7J= ziSVbaQx|lbB*8P-jkFVL*Oh#nX(JUM$OEoro=eq570%U_XT@F7L3WB4>~yiSCA7yz^&IFZ5i;(yUsD!=$V5@#h*+@S6)CnF$*py=^160nFpd9Jyht^+BNooXUp`_7+5~LhQ%ye|mps zwKLk~D_2HD&T=5#^@ov<+-vwb%4 z#-9G!gtJJnvDbsLqrAuFzVJ;vtIf%GM1KwX`WPyuc7a<#Zooi~JeyMy{KhuP#1{aO zv7b@k1JeNQ>KMFD>GyzbpG>?7b2W_H&whsp7xb95S_?XQ<;GjXqg#o-+G<@z_HLrB z-z|h(FzbN^$=%~MsE1U>S=<8)5Z+s?DF!>K8j=+tHmtyI8_W1m*p0USV0h&4kt%zM zchfxQN)A=G=nqpRZ3EPNx6E>r4YUpO0xYz>%=I@#nG0viALqqxn)5;0m$t@r+LO40 zUHiy|2F3hDsY2OxULlRk!(pBdT$vZ4YG9Nb7|IIzs?Kv~d2+j&RIA@zp1kM4SCKW` zB63G5_AkIhWAzEWNZ07-wdcWeV)t^iT!;Srf1>3jnDr2|zfipi2!kuhp|*AoYX1Oz zh1$OyQvVxj>uq%rvaBv4Sx17URIehrjARQ)0+_zmN|rEv?G)4M3R>Mjf)~kBEvp+% zB6a{WaB-hpYneb7+Px*Nx`zxZoSa+X^H#T$*v8z!m2+F?ykCeim%ukT|F%qX1TxIR zsxfTT%MMMcq(V@sn@HY1jr45H3SSSraNN}u(>kq(ap0uMijDv2BlQND*ezZ;XjYJi zK4~g>pfUqpbSkpZiA=qYKJihq8$H=fyIrYu^WTT8YI*eS+$|;3h3L8?{-8SQhxqom L_PEX(H1_@m7aj{h literal 0 HcmV?d00001 diff --git a/fe/test/__pycache__/test_login.cpython-39-pytest-7.2.0.pyc b/fe/test/__pycache__/test_login.cpython-39-pytest-7.2.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..615d1b8b0e75c511bc88343ee4bd0a7614690926 GIT binary patch literal 3262 zcmc&$&2QX96rY*3*B{wUo3!+c7DA!Wz8Xm$8>7 zTe}BR2?+rz5+_ul-D9|MbBgK_zxI&u`|v@%-k!dB3q! zt(pXW&wl!O{Rf4RU$ImCm7sG8TDS~?6Ha|%QTb%e5+jr}6-%X=rEHa@MYA+`GGA{R zmLY8=-)xRpBb2;FxWd(2gsa=ks&IOh)XI0^&19)YQ^n~-*YH^nT8%o67Jow|3ozk6lweL;DNE4RotwN$S1@+|^bG_J!_;|4e3sq+z7t&$qcZWvt&*1Xm-tfj%4 zK__(Uw6GS2qyh~wgezc)NRLKrz0{{Mu^|XOB~p88pU8fhvzV-xj}x$IyfoBx&`3gK zx^5)WBSD*%C^3smv9iq)l`Ba(R^##pOSD+KO~d)f?2T|W)*6&cOM~?lu0@qzwNE}K z;n!dvjbUB!Eog^OYca5+PWx0oS)UeW{5YKP^L;a5KLyX)P1bR#+pGsj}1Pq*nOa7+}~KQsod1WkdaLemmBDDT7J;RI4Lved0ckQ3X- zq}VqS%V;}ccs&r@wv5OXO|Rwn_T8T#8#{EDEiTq*_xp3_+gsB!wa~mV&?XiqP@Nl$ zfszjm-9X8QrfT6N9yc?Y6z-ZA!ZK!Z9_L>i%m*cRz5vc}MuhEgGkIRFG7T@tmj*5O zTL8ZSbTg@$$;4uYX&T;;DxvE)YDQXWZ%tVsW>A|$aRIv*Q7l*rY->u&87VJx4?!?o z5oOB)C^>wwHZB+hBvmfME(8`wT6*u@D`~kAh^7;zO5`=&RLfzf`T$p|4kT0Sksh%#e73vU_MMg!fu&{&1M!dGGTCOQi=A1kV3{v= zUbG~%e9rW~-rT<4Y}U&bpPt{>Ti7AuaR9J8_2x?}t3j|4MuBiwUIpzcYA?L=_RLDd zUBL)Rk)71Z_EvhVEnHi4TDI5nBG2)?uG|q4NH_|Duu*oHR^a~!IYYY>L++V8c;Y@9 z(qKNe*Pw;3L$;AndO$(z3>uP&(l4#BgeHtrAQu{!fJl^B2|ojRLRwOQM&!7p5hc=k zx}=e1up3Ai;zQ6()PP2i)XW%3LA}GEoPkHV7OS$f%h3o}D=`%Qu(TCPXrxy~L|g{~ zWPL!xjUpBxwG%M&L1=yfdxqvWiQplii6x!`(R}w{G=Mi6;JHo3&4-6bqS=?H+bmr8 z8#F9rLo`fO{u>%ex8{;4!+{cbvUX^9963)?SVmQ|$W--!yE{zaF-Crx-5o7(5OA5m z+c9PK=H0L0cC3wNRHRA*7i0MLaTG^TJc8mFisL9wpg4)*6pBYtoCblkvKDlr9Ziyf zcoN6dDA;gYMJ|{TXV4%CAuHy&VrO0!awaCwQIoV5Y#fD7co+nsr|2d-O1sc*LTz@( z_G&Ws{p%w92Ij+I&x?>#yz}oVL{>cf;g>SKaN9#6Dp;Vh5Y=HJelSR`SS_Shl{yw; zIWI)`lzDI=VrqAcCGiX(6z5T3e#Kc77)tRJil2USqS&I z455ouZ|7If6W|fTrzJ%GG1@(SPqg>B{?ou?(DUH$G2s6gcrlGpm_cz+P>vLWGPs7% zf%9He&Kww(f$tK0H0ZXxT5UTuZMzxpj_-nAvF(pKj*piv^vc;Ko@xzmGwKLeVCcmZ zidhtMDE1O2wFw-`eg;DC+%#V$&3@=0*6ni>%xoR z;vWvBT0WN5KUSW=4|mIGxRXx3?uKDT8Vo)Z@ash`b`ZK$e>vOlD?l|Q)IpqOI)gj4 F^e4e7MHm18 literal 0 HcmV?d00001 diff --git a/fe/test/__pycache__/test_new_order.cpython-39-pytest-7.2.0.pyc b/fe/test/__pycache__/test_new_order.cpython-39-pytest-7.2.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..02e38ce738741c3621034002267f65488056967c GIT binary patch literal 3556 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 literal 0 HcmV?d00001 diff --git a/fe/test/__pycache__/test_payment.cpython-39-pytest-7.2.0.pyc b/fe/test/__pycache__/test_payment.cpython-39-pytest-7.2.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5d89821267a0ca51946920638ab7b2d53daa85a GIT binary patch literal 4254 zcmd^C&5s;M6|d^=>G{}C?|KO&u|*&g$by|Xh+rGX1Up2?M8xDUS}3)rdYswq>7G>g z#OtLehj=9}iDYr$grZ%E%S!wq964~R1480t{sf=+z3SQ7+3XsezyXOF&8ye%)yJ!< z-~08OsM!n|J}>>|lkR4XvA@&9?8nB#HT?1fLNdt{*5RhL2DZgG8#o=8S01n9!DA)< zAm{|fW+$~l*a?m9B=td~(=fW5GzYCtYcg)GGk23oPx`w|`VXwmyyWk)cJK%*vRiGg z-Rqwle!*fpb|k-C zwbrDyC#{3lz01+Vh3294CLSNHkLLhwuvwEe8Gg!TT{d>v1KtT`Q?_8y13th|OB*9ktQU`gFsn}>{Q$`y`d44ZbQZK?L z?qH9ipY}45-~@EN$ciWtL)GubIzX>#BG(MRO{W%(ifoj}T|RRtE$BXebXfTx;E{Zf z6}+(a?0xKGpO;KH(mG*trG3KYm2A^Nf4>MSZPR^Vjd{s&Iu5?B^ggvWtg$t=VGGeS zEUo;H(wBj(74^NwKKqd6pA^l#R%z{X^*d;Dq@|Xu_4x`LJHcP79y(A{gzd9;Uv1SicT_zjf1f-7ZAfLVhZ16 zzkGdMFY9t)jg1><7tuD$#^zbcMhq+MKI9+#Dy3bmlC^9uvsFf;$u8M@$TP`+o26Sj zYXyKKh81$e6gcA7I?}LL9?#BoshaDOBEUW((O%PDFH?i4&~{!Z?Tkjq6_?}%MKD$Y z2@n`l#Ak|9UfXx$RMkmqTpJ>9M*XDdr@8i$tQ#e{4q-J%7AbvJCOg3Kn5 z*~F~S%?86r#i~Je*W_-yr5#*nPX`Fw9J4w@-ua`Pmy?XA-Bc@I(EN`23U#ZKvAU3p zvkw=lhpPLlvk$Lnr(eVa?GT}8I~@%UnEClKPJWBk?T6L30AzNJ`Ng zr7}10RNtfyFOztI#5YLLjjA?@mq>gILi-a^GGIUO)OW~Z)_Ik*OC(++@jVg*v`Sot zrhSu$+19u5kW(@<;A0!VouyekOnN;T0O$Xw0I*q?0TKBo69fge*MMvu1B6Ym1Rz!n zAZiAf;VHoU+Y}K0_%8sW{xpElme?j5KX;7A&rNB(-7iHM1HFQRj9idKV=dBVuoPhjMfflmg_$}!MLewLXlLd7z}93Ptt z!exOuoaqI*Q|9>T^n%`-xggi*#2ns)IZ*X{A?7%Y;t(jIiR1G?If~;i(>VV6pT%LA z13-C>Zs*_AhkBFx-5_z5#A%nhWb!x73XzX`y^3VMkIs{fU#v3zxf8c}e8iJ4^0Q+X zc`VQVPwC&V&dJx%A((z^z!Vrz*QTJJz7D}l8;5X0ncABH)R%ZA8bF0l!#q!er8$Eo z)MasG>S1D`oa(9Ro5KP#JaYm|Mu(n$ly+BORo6+}B=HuBpO82rI-}9+Pf-y= zoR)u;6jKgSNi@-{kcX>*7x;l^dbSsIa9GWnm$F_H)$;3A1&BIyUB&kl>N{PVnzTQ$ zRj>4)VX4ksFJ6zj-8j$J&EJA*GiP9><6S>2MTLxtsH&=$jz&!XdYhuR(>n4{^=M8= eoyRIB=+pMCgUi*KUq#|pw|CxZpc15SVE+@45H~~s literal 0 HcmV?d00001 diff --git a/fe/test/__pycache__/test_register.cpython-39-pytest-7.2.0.pyc b/fe/test/__pycache__/test_register.cpython-39-pytest-7.2.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e241fe6a43b38b8d2217c5e7299cad60a953432 GIT binary patch literal 3080 zcmd5;Pj4GV6rY)0@2=N&NCOR|P?|Ipa8XU0P(X;F6a+}9iclMRup*5%o^`v)+G}Rl z)G_v@iNpm^KLCgLg5)cof{%bkoIpbASICL?W@E>0oCql#VrhQ!=gsbWp5JfZ8?R7s z3H+}A@MGnz3?YBxWb|jiWEEPx4j_o2At_VcvzoyOB{j30p{d0xTiRlmZRlC()UxHQ zwi%&Y%awDKd`W~UGJ8a1c3C+u=zUVOp23^RT9GQ#YbKAduSE4~1y@IZ!$?+P)z?v! znQv^Ff(rH%6^1bP$Sy5sL`GP91Y)s;1HCP>!iC-uIgy7xD+=IsO6Ax6IJxIP4C2I> z>)_S~_fa$UD|Eyyj!kG7PW&N&p!+1D`?N=Tv_m)(Y;0~M=6)uzwrp)R1$h8xBnWsk z*4h^naLMJNPY%8$|GwLv8((gCar`)v0!&3mS=C6^yhNEvQ1g|op9zF=2D>DKppadhMBua-8d{s#KjFpRC# z*io|$>2ukv^PnCiffojCFA1VL>Lqpn2%DzUbc(hYM^Cae`Khr(wcueJ+Go(>p8+~# zi|oU3ZZT*^k9Db_UDlx;w#~Xm$B3Wcu?p5Psz5ZZS6R;#W@7EzJ@Ori?}FXw&>oc! zV3fsCoq-+4tVc!W7dA_}rT|fN%z(l;lel2bbuvA=OP_$GP0}^G45{inYtMd%sQUDP zt*rEEd*<5Pjh&mtcz$JN9*4`t7)2`lK2ru*5S9<7fHz+zddF?p0gJc$`IH}LK)S?} zlUV@et~Pcw^PW@}c*P4tIR1vLM74$|eU%3@-)sh964Ya5g%RwC)hj%H6g5MkxAKQ! zwCRPs?twJ2Joc(SzClgh(UAaIpGz4@^&(G2#Qjzy^y-?%z9sV*%0&z%hrZJAmqsVI z(ni#Xc80IM;6I)u*9_T@2+Jiqs3bzFiE@cgJlN0L8Tr%!1- z1*$qtsegbyRq9__oo7<2oQC7=7qrIYYcM{Nm%NPA*AcED%p)uyTt!$!cmqJW&H7NB z*Kidx#t5-9nyjNuJlaOhq$vQXZ84zt%5i$fo;aD{-_9w)!g(2mH=c|POh!QRj3zm& z(~&zN9sM~Z`Jc0qJT5qlX)HMo;`#OTcp&1&Afl&Kw$B!mu4cJ4i66L}L3jxPMImPq z<`6CcD8^fuL>I=A=)y3G%6D+*B+)HCFFGF+8OIAkBo7M_>OICBh6$#{W@#JS%~O>) z;WZ~q^Bm@$$u)8ygEaRzT9!})k5$S4HTM+V{~`hTE>e68;Z=l5WG`s42T6#h9QiG{ zn59>wK)eZ$jwhVbahgwi!CKK(4%dZ}bLDbgi$pW@VVvju+ol&{35A)JmSkmDgI3a% zzI*|LzK(DMVF_Uw;V4V$5!OJ7)ecL$R;5E->ROKJ*p90$#e#AM^<3vX*Dq#gF6kj=`Y%;|)+dn-rgNK2HDkCwQyX M=XsSmEKl>szdW}Qa{vGU literal 0 HcmV?d00001 diff --git a/script/test.sh b/script/test.sh index ae7bfb0..977254d 100644 --- a/script/test.sh +++ b/script/test.sh @@ -3,4 +3,4 @@ export PATHONPATH=`pwd` coverage run --timid --branch --source fe,be --concurrency=thread -m pytest -v --ignore=fe/data coverage combine coverage report -coverage html +coverage html \ No newline at end of file