From 1ff1108ba31301a0da8ace2749f437b46c28f49d Mon Sep 17 00:00:00 2001 From: Lunaresk Date: Fri, 3 Dec 2021 04:37:21 +0100 Subject: [PATCH] patch: deal with items not inserted to database --- client/src/connection.py | 5 +++-- client/src/main.py | 25 ++++++++++++++++++++---- server/src/database.py | 41 +++++++++++++++++++++++----------------- server/src/main.py | 14 ++++++++------ 4 files changed, 56 insertions(+), 29 deletions(-) diff --git a/client/src/connection.py b/client/src/connection.py index 17e6e3e..244b07f 100644 --- a/client/src/connection.py +++ b/client/src/connection.py @@ -39,6 +39,7 @@ def send_scan(login: str, scanned: dict[int: int], date:str = None): try: response = put(url=":".join([SERVER, str( PORT)]) + '/scan2kasse/insert', json=infos) - return True if response.status_code == 201 else False - except: + return True if response.status_code == 201 else response.json + except Exception as e: + LOGGER.exception(e) return False diff --git a/client/src/main.py b/client/src/main.py index f0c3e30..1cdd387 100644 --- a/client/src/main.py +++ b/client/src/main.py @@ -1,4 +1,7 @@ from datetime import date +from json import dump as jdump, load as jload +from os import remove +from os.path import exists from select import select as timedInput from sys import stdin import connection @@ -20,6 +23,7 @@ consoleHandler.setLevel(logging.DEBUG) LOGGER.addHandler(consoleHandler) TEMP = [] +TEMPFILE = "scans.json" TIMEOUT = 60 # Number of seconds for a timeout after being logged in @@ -27,16 +31,26 @@ TIMEOUT = 60 # Number of seconds for a timeout after being logged in def main() -> None: while True: login = input("Enter Login: ") + if login == "quit": + break if not connection.check_login(login): continue # Send Error that login wasn't possible scanned = scanning() scanned = group_scanning(scanned) - if not connection.send_scan(login, scanned): - TEMP.append({'login': login, 'items': scanned, 'date': str(date.today())}) + result = connection.send_scan(login, scanned) + if result != True: + result['date'] = str(date.now()) + TEMP.append(result) if TEMP: for bought in TEMP: - if connection.send_scan(bought['login'], bought['items'], bought['date']): - TEMP.remove(bought) + result = connection.send_scan(bought['login'], bought['items'], bought['date']) + TEMP.remove(bought) + if result != True: + TEMP.append(result) + with open(TEMPFILE, "w") as file: + jdump(TEMP, file) + elif exists(TEMPFILE): + remove(TEMPFILE) def scanning() -> list: @@ -74,4 +88,7 @@ def group_scanning(scanned: list[int]) -> dict[int: int]: return scan_dict if __name__ == '__main__': + if exists(TEMPFILE): + with open(TEMPFILE, "r") as file: + TEMP = jload(file) main() \ No newline at end of file diff --git a/server/src/database.py b/server/src/database.py index 1e0505d..a0d83b0 100644 --- a/server/src/database.py +++ b/server/src/database.py @@ -1,4 +1,4 @@ -from psycopg2 import connect as psyconn, ProgrammingError +from psycopg2 import connect as psyconn, ProgrammingError, errors from yaml import safe_load import logging @@ -33,6 +33,7 @@ class Database: LOGGER.info('Connecting to Database.') self.conn = psyconn(host=kwargs["host"], port=kwargs["port"], dbname=kwargs["database"], user=kwargs["user"], password=kwargs["password"]) + self.conn.autocommit = True def test_connection(self): if not hasattr(self, "conn"): @@ -72,23 +73,23 @@ class Database: @connectionpersistence def get_report(self, **kwargs) -> list: - query = "SELECT u.name, bp.buy_date, i.name, bp.amount, bp.buy_price FROM bought_with_prices bp INNER JOIN items i ON bp.item = i.id INNER JOIN users u ON bp.user = u.login" + query = "SELECT u.name, bp.date, i.name, bp.amount, bp.price FROM bought_with_prices bp INNER JOIN items i ON bp.item = i.id INNER JOIN users u ON bp.user = u.login" if kwargs: query += " WHERE " tempquery = [] if "user" in kwargs and kwargs['user']: tempquery.append(f"bp.user = '{kwargs['user']}'") if "year" in kwargs and kwargs['year']: - tempstring = "" + tempstring = "bp.date BETWEEN " if "month" in kwargs and kwargs['month']: - tempstring += f"bp.buy_date BETWEEN '{kwargs['year']}-{kwargs['month']}-01' AND " + tempstring += f"'{kwargs['year']}-{kwargs['month']}-01' AND " tempstring += f"'{kwargs['year']+1}-01-01'" if kwargs['month'] == 12 else f"'{kwargs['year']}-{kwargs['month']+1}-01'" else: - tempstring += f"bp.buy_date BETWEEN '{kwargs['year']}-01-01' AND '{kwargs['year']+1}-01-01'" + tempstring += f"'{kwargs['year']}-01-01' AND '{kwargs['year']+1}-01-01'" tempstring += "::date - INTERVAL '1' DAY" tempquery.append(tempstring) query += " AND ".join(tempquery) - query += " ORDER BY u.name, bp.buy_date, i.name ASC;" + query += " ORDER BY u.name, bp.date, i.name ASC;" LOGGER.debug(f"Executing query: {query}") result = [] with self.conn.cursor() as cursor: @@ -103,23 +104,29 @@ class Database: @connectionpersistence def insert_bought_items(self, user: str, items: dict, date: str = None): - temp = ["user, item, amount", "%(user)s, %(item)s, %(amount)s", + temp = ['"user", item, amount', "%(user)s, %(item)s, %(amount)s", "bought.user = %(user)s AND bought.item = %(item)s AND bought.date = " + ("%(date)s" if date else "NOW()")] if date: temp[0] += ", date" temp[1] += ", %(date)s" - values = [{'user': user, 'item': key, 'amount': value, 'date': date} for key, value in items.items()] + values = [{'user': user, 'item': int(key), 'amount': value, 'date': date} for key, value in items.items()] else: - values = [{'user': user, 'item': key, 'amount': value} for key, value in items.items()] - query = f"INSERT INTO bought({temp[0]}) VALUES({temp[1]}) ON CONFLICT ON CONSTRAINT bought_user_item_buy_date DO UPDATE SET amount = bought.amount + %(amount)s WHERE {temp[2]};" + values = [{'user': user, 'item': int(key), 'amount': value} for key, value in items.items()] + query = f"INSERT INTO bought({temp[0]}) VALUES({temp[1]}) ON CONFLICT ON CONSTRAINT bought_user_item_date DO UPDATE SET amount = bought.amount + %(amount)s WHERE {temp[2]};" with self.conn.cursor() as cursor: - try: - cursor.executemany(query, values) - self.conn.commit() - return True - except Exception as e: - LOGGER.debug(e) - return False + failed = {} + for value in values: + try: + cursor.execute(query, value) + except errors.ForeignKeyViolation as e: + if failed: + failed['items'][value['item']] = value['amount'] + else: + failed = dict(value) + LOGGER.exception(e) + except Exception as e: + LOGGER.exception(e) + return failed def __delete__(self): self.conn.close() diff --git a/server/src/main.py b/server/src/main.py index f369a9f..86035e0 100644 --- a/server/src/main.py +++ b/server/src/main.py @@ -41,13 +41,15 @@ def login(): def insert(): match request.json: case {'login': login, 'items': items, 'date': date}: - if DATABASE.insert_bought_items(login, items, date): - return jsonify({'insert': True}), 201 - return jsonify({'insert': False}), 400 + failed = DATABASE.insert_bought_items(login, items, date) + if failed: + return jsonify(failed), 400 + return jsonify({'inserted': True}), 201 case {'login': login, 'items': items}: - if DATABASE.insert_bought_items(login, items): - return jsonify({'insert': True}), 201 - return jsonify({'insert': False}), 400 + failed = DATABASE.insert_bought_items(login, items) + if failed: + return jsonify(failed), 400 + return jsonify({'inserted': True}), 201 case _: abort(400)