diff --git a/__pycache__/api.cpython-312.pyc b/__pycache__/api.cpython-312.pyc index 65cb803..86796ff 100644 Binary files a/__pycache__/api.cpython-312.pyc and b/__pycache__/api.cpython-312.pyc differ diff --git a/__pycache__/config.cpython-312.pyc b/__pycache__/config.cpython-312.pyc index 05684f2..10a5f90 100644 Binary files a/__pycache__/config.cpython-312.pyc and b/__pycache__/config.cpython-312.pyc differ diff --git a/__pycache__/main.cpython-312.pyc b/__pycache__/main.cpython-312.pyc index ba529c2..899b7b5 100644 Binary files a/__pycache__/main.cpython-312.pyc and b/__pycache__/main.cpython-312.pyc differ diff --git a/__pycache__/webserver.cpython-312.pyc b/__pycache__/webserver.cpython-312.pyc index 0020478..af3ec6c 100644 Binary files a/__pycache__/webserver.cpython-312.pyc and b/__pycache__/webserver.cpython-312.pyc differ diff --git a/api.py b/api.py index 01dc3a1..f8d209f 100644 --- a/api.py +++ b/api.py @@ -1,9 +1,14 @@ from flask import Blueprint, request, render_template, redirect, session, url_for, send_file, jsonify, Response -import psycopg2, math -from config import config +import psycopg2, math, json, datetime, main, copy +from config import config, sites_config database_api= Blueprint('database_api', __name__) +@database_api.route("/changeSite") +def changeSite(): + site = request.args.get('site', 'main') + session['selected_site'] = site + return jsonify({'status': 'SUCCESS'}) def paginate_with_params(cur, limit, offset, params): sql = f"SELECT * FROM main_items LEFT JOIN main_logistics_info ON main_items.logistics_info_id = main_logistics_info.id" @@ -48,15 +53,87 @@ def paginate_default(cur, limit, offset): count = cur.fetchone()[0] return pantry_inventory, count +def paginate_with_params_groups(cur, limit, offset, params): + sql = f"SELECT * FROM main_groups" + count = f"SELECT COUNT(*) FROM main_groups" + # WHERE search_string LIKE '%{search_string}%' + strings = [] + count_strings = [] + if params['search_string'] != "": + s = params['search_string'] + strings.append(f" search_string LIKE '%{s}%'") + count_strings.append(f" search_string LIKE '%{s}%'") + + + # LIMIT {limit} OFFSET {offset};" + + if len(strings) > 0: + sql = f"{sql} WHERE{" AND".join(strings)}" + + if len(count_strings) > 0: + count = f"{count} WHERE{" AND".join(count_strings)}" + + sql = f"{sql} ORDER BY main_logistics_info.quantity_on_hand LIMIT {limit} OFFSET {offset};" + count = f"{count};" + print(count) + print(sql) + cur.execute(sql) + pantry_inventory = cur.fetchall() + cur.execute(count) + count = cur.fetchone()[0] + return pantry_inventory, count + +@database_api.route("/getGroups") +def paginate_groups(): + page = int(request.args.get('page', 1)) + limit = int(request.args.get('limit', 10)) + site_name = session['selected_site'] + offset = (page - 1) * limit + + groups = [] + count = 0 + + database_config = config() + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + sql = f"SELECT * FROM {site_name}_groups LIMIT %s OFFSET %s;" + count = f"SELECT COUNT(*) FROM {site_name}_groups" + + cur.execute(sql, (limit, offset)) + groups = cur.fetchall() + cur.execute(count) + count = cur.fetchone()[0] + + + sql_item = f"SELECT {site_name}_items.barcode, {site_name}_items.item_name, {site_name}_logistics_info.quantity_on_hand FROM {site_name}_items LEFT JOIN {site_name}_logistics_info ON {site_name}_items.logistics_info_id = {site_name}_logistics_info.id WHERE {site_name}_items.id = %s; " + new_groups = [] + for group in groups: + qty = 0 + group = list(group) + items = [] + print(group[3]) + for item_id in group[3]: + cur.execute(sql_item, (item_id,)) + item_row = cur.fetchone() + qty += float(item_row[2]) + items.append(item_row) + group[3] = items + group.append(qty) + new_groups.append(group) + except (Exception, psycopg2.DatabaseError) as error: + print(error) + + return jsonify({'groups': new_groups, "end": math.ceil(count/limit)}) @database_api.route("/getItems") def pagninate_items(): - print("hello") page = int(request.args.get('page', 1)) limit = int(request.args.get('limit', 10)) search_string = str(request.args.get('search_text', "")) sort_order = int(request.args.get('sort_order', 1)) view = int(request.args.get('view', 0)) + site_name = session['selected_site'] offset = (page - 1) * limit @@ -67,30 +144,25 @@ def pagninate_items(): with psycopg2.connect(**database_config) as conn: try: with conn.cursor() as cur: - pantry_inventory, count = paginate_with_params( - cur, limit, offset, - {'search_string': search_string, - 'view': view} - ) + sql = f"SELECT * FROM {site_name}_items LEFT JOIN {site_name}_logistics_info ON {site_name}_items.logistics_info_id = {site_name}_logistics_info.id LIMIT {limit} OFFSET {offset};" + count = f"SELECT COUNT(*) FROM {site_name}_items LEFT JOIN {site_name}_logistics_info ON {site_name}_items.logistics_info_id = {site_name}_logistics_info.id;" + cur.execute(sql) + pantry_inventory = cur.fetchall() + cur.execute(count) + count = cur.fetchone()[0] except (Exception, psycopg2.DatabaseError) as error: print(error) - if sort_order == 0: - pantry_inventory = sorted(pantry_inventory, key=lambda x: x[1]) - - if sort_order == 1: - pantry_inventory = sorted(pantry_inventory, key=lambda x: x[2]) - - if sort_order == 2: - pantry_inventory = sorted(pantry_inventory, key=lambda x: x[18]) - return jsonify({'items': pantry_inventory, "end": math.ceil(count/limit)}) @database_api.route("/getItem") def get_item(): id = int(request.args.get('id', 1)) database_config = config() - site_name = "main" + site_name = session['selected_site'] + sites = sites_config() + + item = [] with psycopg2.connect(**database_config) as conn: try: @@ -99,24 +171,351 @@ def get_item(): sql = file.read() cur.execute(sql, (id, )) item = list(cur.fetchone()) - item[5] = {'walmart': 'https://www.walmart.com/ip/Ptasie-Mleczko-Chocolate-Covered-Vanilla-Marshmallow-birds-milk-chocolate-13-4-Oz-Includes-Our-Exclusive-HolanDeli-Chocolate-Mints/965551629?classType=REGULAR&from=/search', 'target': 'https://www.target.com/p/hershey-39-s-cookies-39-n-39-cr-232-me-fangs-halloween-candy-snack-size-9-45oz/-/A-79687769#lnk=sametab'} - item[22] = ['test_list', 'main_list'] - item[23] = ['test_recipe',] - item[24] = ['test_group', 'main_group', 'test2_group'] + SQL_groups = f"SELECT * FROM {site_name}_groups WHERE included_items @> ARRAY[%s];" + cur.execute(SQL_groups, (item[0], )) + item[25] = list(cur.fetchall()) + SQL_shopping_lists = f"SELECT * FROM {site_name}_shopping_lists WHERE pantry_items @> ARRAY[%s];" + cur.execute(SQL_shopping_lists, (item[0], )) + item[23] = list(cur.fetchall()) + print(item) except (Exception, psycopg2.DatabaseError) as error: print(error) - return render_template(f"item_page/index.html", item=item) + return render_template(f"items/item.html", item=item, current_site=site_name, sites=sites['sites']) + +@database_api.route("/addItem") +def addItem(): + barcode = str(request.args.get('barcode', "")) + name = str(request.args.get('item_name', "")) + description = str(request.args.get('item_description', "")) + item_type = str(request.args.get('item_type', "")) + subtype = str(request.args.get('sub_type', "")) + site_name = session['selected_site'] + state = "FAILED" + + payload = copy.deepcopy(main.payload_food_item) + + defaults = config(filename=f"sites/{site_name}/site.ini", section="defaults") + uuid = f"{defaults["default_zone"]}@{defaults["default_primary_location"]}" + name = name.replace("'", "@&apostraphe&") + payload["logistics_info"]["primary_location"] = uuid + payload["logistics_info"]["auto_issue_location"] = uuid + + + database_config = config() + with psycopg2.connect(**database_config) as conn: + logistics_info_id = main.create_logistics_info(conn, site_name, barcode, payload["logistics_info"]) + if not logistics_info_id: + return jsonify({'state': str(logistics_info_id)}) + item_info_id = main.create_item_info(conn, site_name, barcode, payload["item_info"]) + if not item_info_id: + return jsonify({'state': str(item_info_id)}) + food_info_id = main.create_food_info(conn, site_name, payload["food_info"]) + if not food_info_id: + return jsonify({'state': str(food_info_id)}) + + sqltwo = f"INSERT INTO {site_name}_items(barcode, item_name, description, item_info_id, logistics_info_id, food_info_id, row_type, item_type, search_string) VALUES('{barcode}', '{name}', '{description}', {item_info_id}, {logistics_info_id}, {food_info_id}, '{item_type}', '{subtype}', '{barcode}%{name}') RETURNING *;" + row = None + try: + with conn.cursor() as cur: + cur.execute(sqltwo) + rows = cur.fetchone() + if rows: + row = rows[:] + except (Exception, psycopg2.DatabaseError) as error: + print(error) + conn.rollback() + return jsonify({'state': str(error)}) + + + conn.commit() + + + main.add_transaction(site_name, barcode, qty=0, user_id=1, description="Added Item to System!") + + + + return jsonify({'state': "SUCCESS"}) @database_api.route("/addGroup") def addGroup(): name = str(request.args.get('name', "")) description = str(request.args.get('description', "")) group_type = str(request.args.get('type', "")) - + site_name = session['selected_site'] state = "FAILED" - if name or description or group_type == "": - print("this is empty") + database_config = config() + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + sql = f"INSERT INTO {site_name}_groups (name, description, included_items, group_type) VALUES (%s, %s, %s, %s);" + cur.execute(sql, (name, description, json.dumps({}), group_type)) + state = "SUCCESS" + conn.commit() + except (Exception, psycopg2.DatabaseError) as error: + print(error) + conn.rollback() - return jsonify({'state': state}) \ No newline at end of file + + return jsonify({'state': state}) + +@database_api.route("/getGroup") +def get_group(): + id = int(request.args.get('id', 1)) + database_config = config() + site_name = session['selected_site'] + + group = [] + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + sql = f"SELECT * FROM {site_name}_groups WHERE id=%s;" + cur.execute(sql, (id, )) + group = list(cur.fetchone()) + + sql_item = f"SELECT {site_name}_items.id, {site_name}_items.barcode, {site_name}_items.item_name, {site_name}_logistics_info.quantity_on_hand FROM {site_name}_items LEFT JOIN {site_name}_logistics_info ON {site_name}_items.logistics_info_id = {site_name}_logistics_info.id WHERE {site_name}_items.id = %s;" + qty = 0 + group = list(group) + items = [] + print(group[3]) + for item_id in group[3]: + cur.execute(sql_item, (item_id,)) + item_row = cur.fetchone() + qty += float(item_row[3]) + items.append(item_row) + group[3] = items + group.append(qty) + except (Exception, psycopg2.DatabaseError) as error: + print(error) + + return jsonify(group=group) + +@database_api.route("/updateGroup", methods=["POST"]) +def update_group(): + if request.method == "POST": + site_name = session['selected_site'] + group_id = request.get_json()['id'] + items = request.get_json()['items'] + name = request.get_json()['name'] + description = request.get_json()['description'] + group_type = request.get_json()['group_type'] + data = (name, description, items, group_type, group_id) + database_config = config() + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + # Start by updating the group -> included items with the up to date list + sql = f"UPDATE {site_name}_groups SET name = %s, description = %s, included_items = %s, group_type = %s WHERE id=%s;" + cur.execute(sql, data) + + update_item_sql = f"UPDATE {site_name}_item_info SET groups = %s WHERE id = %s;" + select_item_sql = f"SELECT {site_name}_item_info.id, {site_name}_item_info.groups FROM {site_name}_items LEFT JOIN {site_name}_item_info ON {site_name}_items.item_info_id = {site_name}_item_info.id WHERE {site_name}_items.id = %s;" + # Now we will fetch each item row one by one and check if the group id is already inside of its groups array + for item_id in items: + cur.execute(select_item_sql, (item_id, )) + item = cur.fetchone() + print(item) + item_groups: set = set(item[1]) + # Condition check, adds it if it doesnt exist. + if group_id not in item_groups: + item_groups.add(group_id) + cur.execute(update_item_sql, (list(item_groups), item[0])) + + # Now we fetch all items that have the group id in its groups array + fetch_items_with_group = f"SELECT {site_name}_items.id, groups, {site_name}_item_info.id FROM {site_name}_item_info LEFT JOIN {site_name}_items ON {site_name}_items.item_info_id = {site_name}_item_info.id WHERE groups @> ARRAY[%s];" + cur.execute(fetch_items_with_group, (group_id, )) + group_items = cur.fetchall() + print(items) + # We will then check each item id against the groups new included_items list to see if the item should be in there + for item_id, group, info_id in group_items: + # If it is not we remove the group form the items list and update the item + if item_id not in items: + groups: list = list(group) + groups.remove(group_id) + cur.execute(update_item_sql, (list(groups), info_id)) + + conn.commit() + except (Exception, psycopg2.DatabaseError) as error: + print(error) + conn.rollback() + + return jsonify({"state": "SUCCESS"}) + return jsonify({"state": "FAILED"}) + +@database_api.route("/addList") +def addList(): + name = str(request.args.get('name', "")) + description = str(request.args.get('description', "")) + list_type = str(request.args.get('type', "")) + site_name = session['selected_site'] + + print(name, description, list_type) + state = "FAILED" + + #if name or description or group_type == "": + # print("this is empty") + # return jsonify({'state': state}) + timestamp = datetime.datetime.now() + data = (name, description, [], json.dumps({}), [], [], 0, timestamp, list_type) + database_config = config() + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + sql = f"INSERT INTO {site_name}_shopping_lists (name, description, pantry_items, custom_items, recipes, groups, author, creation_date, type) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s);" + cur.execute(sql, data) + state = "SUCCESS" + conn.commit() + except (Exception, psycopg2.DatabaseError) as error: + print(error) + conn.rollback() + + + return jsonify({'state': state}) + +@database_api.route("/getLists") +def paginate_lists(): + page = int(request.args.get('page', 1)) + limit = int(request.args.get('limit', 10)) + site_name = session['selected_site'] + + offset = (page - 1) * limit + + lists = [] + count = 0 + + database_config = config() + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + sql = f"SELECT * FROM {site_name}_shopping_lists LIMIT %s OFFSET %s;" + count = f"SELECT COUNT(*) FROM {site_name}_shopping_lists;" + + cur.execute(sql, (limit, offset)) + temp_lists = list(cur.fetchall()) + cur.execute(count) + count = cur.fetchone()[0] + + for shopping_list in temp_lists: + shopping_list: list = list(shopping_list) + pantry_items = shopping_list[3] + custom_items = shopping_list[4] + list_length = len(custom_items) + + if shopping_list[10] == 'calculated': + item_sql = f"SELECT COUNT(*) FROM {site_name}_items LEFT JOIN {site_name}_logistics_info ON {site_name}_items.logistics_info_id = {site_name}_logistics_info.id LEFT JOIN {site_name}n_item_info ON {site_name}_items.item_info_id = {site_name}_item_info.id LEFT JOIN {site_name}_food_info ON {site_name}_items.food_info_id = {site_name}_food_info.id WHERE {site_name}_logistics_info.quantity_on_hand < {site_name}_item_info.safety_stock AND shopping_lists @> ARRAY[%s];" + cur.execute(item_sql, (shopping_list[0], )) + list_length += cur.fetchone()[0] + else: + list_length += len(pantry_items) + + shopping_list.append(list_length) + lists.append(shopping_list) + + except (Exception, psycopg2.DatabaseError) as error: + print(error) + + return jsonify({'lists': lists, 'end': math.ceil(count/limit)}) + +@database_api.route("/getListView") +def get_list_view(): + id = int(request.args.get('id', 1)) + site_name = session['selected_site'] + shopping_list = [] + database_config = config() + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + sql = f"SELECT * FROM {site_name}_shopping_lists WHERE id=%s;" + cur.execute(sql, (id, )) + shopping_list = list(cur.fetchone()) + + if shopping_list[10] == "calculated": + itemSQL = f"SELECT {site_name}_items.id, {site_name}_items.barcode, {site_name}_items.item_name, {site_name}_items.links, {site_name}_logistics_info.quantity_on_hand, {site_name}_item_info.safety_stock, {site_name}_item_info.uom FROM {site_name}_items LEFT JOIN {site_name}_logistics_info ON {site_name}_items.logistics_info_id = {site_name}_logistics_info.id LEFT JOIN {site_name}_item_info ON {site_name}_items.item_info_id = {site_name}_item_info.id LEFT JOIN {site_name}_food_info ON {site_name}_items.food_info_id = {site_name}_food_info.id WHERE {site_name}_logistics_info.quantity_on_hand < {site_name}_item_info.safety_stock AND shopping_lists @> ARRAY[%s];" + else: + itemSQL = f"SELECT {site_name}_items.id, {site_name}_items.barcode, {site_name}_items.item_name, {site_name}_items.links, {site_name}_logistics_info.quantity_on_hand, {site_name}_item_info.safety_stock, {site_name}_item_info.uom FROM {site_name}_items LEFT JOIN {site_name}_logistics_info ON {site_name}_items.logistics_info_id = {site_name}_logistics_info.id LEFT JOIN {site_name}_item_info ON {site_name}_items.item_info_id = {site_name}_item_info.id LEFT JOIN {site_name}_food_info ON {site_name}_items.food_info_id = {site_name}_food_info.id WHERE shopping_lists @> ARRAY[%s];" + + cur.execute(itemSQL, (id, )) + shopping_list[3] = list(cur.fetchall()) + print(shopping_list) + + except (Exception, psycopg2.DatabaseError) as error: + print(error) + + return jsonify(shopping_list=shopping_list) + +@database_api.route("/getList") +def get_list(): + id = int(request.args.get('id', 1)) + database_config = config() + site_name = session['selected_site'] + shopping_list = [] + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + sql = f"SELECT * FROM {site_name}_shopping_lists WHERE id=%s;" + cur.execute(sql, (id, )) + shopping_list = list(cur.fetchone()) + itemSQL = f"SELECT {site_name}_items.id, {site_name}_items.barcode, {site_name}_items.item_name, {site_name}_items.links, {site_name}_item_info.uom FROM {site_name}_items LEFT JOIN {site_name}_item_info ON {site_name}_items.item_info_id = {site_name}_item_info.id WHERE {site_name}_item_info.shopping_lists @> ARRAY[%s];" + cur.execute(itemSQL, (id, )) + shopping_list[3] = list(cur.fetchall()) + print(shopping_list) + except (Exception, psycopg2.DatabaseError) as error: + print(error) + + return jsonify(shopping_list=shopping_list) + +@database_api.route("/updateList", methods=["POST"]) +def update_list(): + if request.method == "POST": + site_name = session['selected_site'] + list_id = request.get_json()['id'] + items = request.get_json()['items'] + print(items) + custom_items = request.get_json()['custom'] + name = request.get_json()['name'] + description = request.get_json()['description'] + list_type = request.get_json()['list_type'] + quantities = request.get_json()['quantities'] + data = (name, description, items, json.dumps(custom_items), list_type, json.dumps(quantities), list_id) + database_config = config() + with psycopg2.connect(**database_config) as conn: + try: + with conn.cursor() as cur: + # Start by updating the group -> included items with the up to date list + sql = f"UPDATE {site_name}_shopping_lists SET name = %s, description = %s, pantry_items = %s, custom_items = %s, type = %s, quantities = %s WHERE id=%s;" + cur.execute(sql, data) + + update_item_sql = f"UPDATE {site_name}_item_info SET shopping_lists = %s WHERE id = %s;" + select_item_sql = f"SELECT {site_name}_item_info.id, {site_name}_item_info.shopping_lists FROM {site_name}_items LEFT JOIN {site_name}_item_info ON {site_name}_items.item_info_id = {site_name}_item_info.id WHERE {site_name}_items.id = %s;" + # Now we will fetch each item row one by one and check if the group id is already inside of its groups array + for item_id in items: + cur.execute(select_item_sql, (item_id, )) + item = cur.fetchone() + print(item) + shopping_lists: set = set(item[1]) + # Condition check, adds it if it doesnt exist. + if list_id not in shopping_lists: + shopping_lists.add(list_id) + cur.execute(update_item_sql, (list(shopping_lists), item[0])) + + # Now we fetch all items that have the group id in its groups array + fetch_items_with_list = f"SELECT {site_name}_items.id, {site_name}_item_info.shopping_lists, {site_name}_item_info.id FROM {site_name}_item_info LEFT JOIN {site_name}_items ON {site_name}_items.item_info_id = {site_name}_item_info.id WHERE {site_name}_item_info.shopping_lists @> ARRAY[%s];" + cur.execute(fetch_items_with_list, (list_id, )) + list_items = cur.fetchall() + print(items) + # We will then check each item id against the groups new included_items list to see if the item should be in there + for item_id, shopping_list, info_id in list_items: + # If it is not we remove the group form the items list and update the item + if item_id not in items: + shopping_lists: list = list(shopping_list) + shopping_lists.remove(list_id) + cur.execute(update_item_sql, (list(shopping_lists), info_id)) + + conn.commit() + except (Exception, psycopg2.DatabaseError) as error: + print(error) + conn.rollback() + + return jsonify({"state": "SUCCESS"}) + return jsonify({"state": "FAILED"}) \ No newline at end of file diff --git a/config.py b/config.py index e131417..0d83e02 100644 --- a/config.py +++ b/config.py @@ -1,5 +1,6 @@ #!/usr/bin/python -from configparser import ConfigParser +from configparser import ConfigParser +import json def config(filename='database.ini', section='postgresql'): @@ -19,3 +20,47 @@ def config(filename='database.ini', section='postgresql'): return db +def sites_config(filename='database.ini', section='manage'): + # create a parser + parser = ConfigParser() + # read config file + parser.read(filename) + + # get section, default to postgresql + sites = {} + if parser.has_section(section): + params = parser.items(section) + for param in params: + sites[param[0]] = param[1].split(',') + else: + raise Exception('Section {0} not found in the {1} file'.format(section, filename)) + + return sites + + +def write_new_site(site_name): + + old_value = sites_config()['sites'] + print(old_value) + + old_value.append(site_name) + old_value = set(old_value) + + config = ConfigParser() + config.read('database.ini') + config.set('manage', 'sites', ','.join(old_value)) + + with open('database.ini', 'w') as configFile: + config.write(configFile) + +def delete_site(site_name): + old_value = sites_config()['sites'] + old_value.remove(site_name) + + config = ConfigParser() + config.read('database.ini') + config.set('manage', 'sites', ','.join(old_value)) + + with open('database.ini', 'w') as configFile: + config.write(configFile) + diff --git a/database.ini b/database.ini index 4b683f2..e7ad19d 100644 --- a/database.ini +++ b/database.ini @@ -1,6 +1,10 @@ [postgresql] -host=192.168.1.67 -database=test -user=test -password=test -port=5432 \ No newline at end of file +host = 192.168.1.67 +database = test +user = test +password = test +port = 5432 + +[manage] +sites = test,test2,main + diff --git a/main.py b/main.py index dc996f3..caee6ac 100644 --- a/main.py +++ b/main.py @@ -35,7 +35,7 @@ def update_item_primary(site_name, barcode, new_primary: str): return False def insert_row(table_name, name): - sql = f"INSERT INTO {table_name}(id, name) VALUES(%s, %s) RETURNING id" + sql = f"INSERT INTO {table_name}(id, name) VALUES(%s, %s) RETURNING id;" id = None try: database_config = config() @@ -85,7 +85,7 @@ def create_logistics_info(conn, site_name, barcode, payload): except (Exception, psycopg2.DatabaseError) as error: print(error) conn.rollback() - return False + return error return logistics_info_id @@ -103,7 +103,7 @@ def create_item_info(conn, site_name, barcode, payload): except (Exception, psycopg2.DatabaseError) as error: print(error) conn.rollback() - return False + return error return item_info_id @@ -136,7 +136,7 @@ def add_location(site_name, name, zone_id): except (Exception, psycopg2.DatabaseError) as error: print(error) conn.rollback() - return False + return error uuid = f"{zone_name}@{name}" try: @@ -145,7 +145,7 @@ def add_location(site_name, name, zone_id): except (Exception, psycopg2.DatabaseError) as error: print(error) conn.rollback() - return False + return error def add_zone(site_name, name): database_config = config() @@ -157,7 +157,7 @@ def add_zone(site_name, name): except (Exception, psycopg2.DatabaseError) as error: print(error) conn.rollback() - return False + return error def add_transaction(site_name, barcode, qty, user_id, transaction_type = "info", description = "", data = {}, location=None): database_config = config() @@ -192,7 +192,7 @@ def add_transaction(site_name, barcode, qty, user_id, transaction_type = "info", except (Exception, psycopg2.DatabaseError) as error: print(error) conn.rollback() - return False + return error if not location: mover = logistics_info[2] @@ -211,7 +211,7 @@ def add_transaction(site_name, barcode, qty, user_id, transaction_type = "info", except (Exception, psycopg2.DatabaseError) as error: print(error) conn.rollback() - return False + return error if logistics_info[3] in location_items.keys(): location_items[logistics_info[3]] = location_items[logistics_info[3]] + qty @@ -234,11 +234,11 @@ def add_transaction(site_name, barcode, qty, user_id, transaction_type = "info", except (Exception, psycopg2.DatabaseError) as error: print(error) conn.rollback() - return False + return error conn.commit() -def add_food_item(site_name: str, barcode: str, name: str, qty: float, payload: dict): +def add_food_item(site_name: str, barcode: str, name: str, payload: dict): # TODO: I need to validate the name so that it doesnt have characters against the SQL database schema such as ' @@ -279,7 +279,6 @@ def add_food_item(site_name: str, barcode: str, name: str, qty: float, payload: add_transaction(site_name, barcode, qty=0, user_id=1, description="Added Item to System!") - add_transaction(site_name, barcode, qty=qty, user_id=1, description="scan in") def drop_table(sql_file: str): database_config = config() diff --git a/manage.py b/manage.py index 9f84298..c955e49 100644 --- a/manage.py +++ b/manage.py @@ -1,5 +1,6 @@ import sys, os, shutil import main +import config as cfg """ Manage.py is where the databases and configuration is set up. Its a CLI for quick serving the databases necessary for @@ -90,6 +91,7 @@ def create(): config.write(f"default_primary_location={default_location_name}\n") config.write(f"default_auto_issue_location={default_location_name}\n") + cfg.write_new_site(site_name) print(f"Site {site_name} config created!") print(f"Site {site_name} created!") @@ -108,6 +110,8 @@ if __name__ == "__main__": if func_name == "delete" and argument == "site": main.delete_site(sys.argv[3]) shutil.rmtree(f"sites/{sys.argv[3]}") + cfg.delete_site(sys.argv[3]) + if func_name == "item": if argument == "add": diff --git a/sites/default/sql/create/item.sql b/sites/default/sql/create/item.sql index 2d6081d..3e08ff9 100644 --- a/sites/default/sql/create/item.sql +++ b/sites/default/sql/create/item.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS %sitename%_items( barcode VARCHAR(255) NOT NULL, item_name VARCHAR(255) NOT NULL, brand INTEGER, - description TEXT; + description TEXT, tags TEXT [], links JSONB, item_info_id INTEGER NOT NULL, diff --git a/sites/default/sql/create/shopping_lists.sql b/sites/default/sql/create/shopping_lists.sql index 5569a9f..3496d8d 100644 --- a/sites/default/sql/create/shopping_lists.sql +++ b/sites/default/sql/create/shopping_lists.sql @@ -2,10 +2,11 @@ CREATE TABLE IF NOT EXISTS %sitename%_shopping_lists ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, description TEXT, - pantry_items JSONB, + pantry_items INTEGER [], custom_items JSONB, - recipes JSONB, - groups JSONB, + recipes INTEGER [], + groups INTEGER [], + quantities JSONB, author INTEGER, creation_date TIMESTAMP, type VARCHAR(64), diff --git a/sites/main/sql/create/item.sql b/sites/main/sql/create/item.sql index d736b6b..8295054 100644 --- a/sites/main/sql/create/item.sql +++ b/sites/main/sql/create/item.sql @@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS main_items( barcode VARCHAR(255) NOT NULL, item_name VARCHAR(255) NOT NULL, brand INTEGER, + description TEXT, tags TEXT [], links JSONB, item_info_id INTEGER NOT NULL, diff --git a/sites/main/sql/create/shopping_lists.sql b/sites/main/sql/create/shopping_lists.sql index ec12db3..cfd9945 100644 --- a/sites/main/sql/create/shopping_lists.sql +++ b/sites/main/sql/create/shopping_lists.sql @@ -2,10 +2,11 @@ CREATE TABLE IF NOT EXISTS main_shopping_lists ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, description TEXT, - pantry_items JSONB, + pantry_items INTEGER [], custom_items JSONB, - recipes JSONB, - groups JSONB, + recipes INTEGER [], + groups INTEGER [], + quantities JSONB, author INTEGER, creation_date TIMESTAMP, type VARCHAR(64), diff --git a/sites/main/sql/unique/select_item_all.sql b/sites/main/sql/unique/select_item_all.sql index b5ca580..23e4f69 100644 --- a/sites/main/sql/unique/select_item_all.sql +++ b/sites/main/sql/unique/select_item_all.sql @@ -9,36 +9,37 @@ WHERE main_items.id=%s; 01 - barcode 02 - item_name 03 - brand (id) -04 - tags -05 - links -06 - item_info_id -07 - logistics_info_id -08 - food_info_id -09 - row_type -10 - item_type -11 - search_string -12 - logistics_info_id -13 - barcode -14 - primary_location -15 - auto_issue_location -16 - dynamic_locations -17 - location_data -18 - quantity_on_hand -19 - item_info_id -20 - barcode -21 - linked_items -22 - shopping_lists -23 - recipes -24 - groups -25 - packaging -26 - uom -27 - cost -28 - safety_stock -29 - lead_time_days -30 - ai_pick -31 - food_info_id -32 - food_groups -33 - ingrediants -34 - nutrients -35 - expires +04 - description +05 - tags +06 - links +07 - item_info_id +08 - logistics_info_id +09 - food_info_id +10 - row_type +11 - item_type +12 - search_string +13 - logistics_info_id +14 - barcode +15 - primary_location +16 - auto_issue_location +17 - dynamic_locations +18 - location_data +19 - quantity_on_hand +20 - item_info_id +21 - barcode +22 - linked_items +23 - shopping_lists +24 - recipes +25 - groups +26 - packaging +27 - uom +28 - cost +29 - safety_stock +30 - lead_time_days +31 - ai_pick +32 - food_info_id +33 - food_groups +34 - ingrediants +35 - nutrients +36 - expires */ \ No newline at end of file diff --git a/sites/test/site.ini b/sites/test/site.ini new file mode 100644 index 0000000..388ddf8 --- /dev/null +++ b/sites/test/site.ini @@ -0,0 +1,9 @@ +[site] +site_name=test +site_owner= +email= + +[defaults] +default_zone=default +default_primary_location=all +default_auto_issue_location=all diff --git a/sites/test/sql/create/brands.sql b/sites/test/sql/create/brands.sql new file mode 100644 index 0000000..6cd9f9c --- /dev/null +++ b/sites/test/sql/create/brands.sql @@ -0,0 +1,4 @@ +CREATE TABLE IF NOT EXISTS test_brands ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) +); \ No newline at end of file diff --git a/sites/test/sql/create/food_info.sql b/sites/test/sql/create/food_info.sql new file mode 100644 index 0000000..bedbe47 --- /dev/null +++ b/sites/test/sql/create/food_info.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS test_food_info ( + id SERIAL PRIMARY KEY, + food_groups TEXT [], + ingrediants TEXT [], + nutrients JSONB, + expires BOOLEAN +); \ No newline at end of file diff --git a/sites/test/sql/create/groups.sql b/sites/test/sql/create/groups.sql new file mode 100644 index 0000000..b97fdab --- /dev/null +++ b/sites/test/sql/create/groups.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS test_groups( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + included_items INTEGER [], + group_type VARCHAR(255), + UNIQUE (name) +); \ No newline at end of file diff --git a/sites/test/sql/create/item.sql b/sites/test/sql/create/item.sql new file mode 100644 index 0000000..c9606af --- /dev/null +++ b/sites/test/sql/create/item.sql @@ -0,0 +1,28 @@ +CREATE TABLE IF NOT EXISTS test_items( + id SERIAL PRIMARY KEY, + barcode VARCHAR(255) NOT NULL, + item_name VARCHAR(255) NOT NULL, + brand INTEGER, + description TEXT, + tags TEXT [], + links JSONB, + item_info_id INTEGER NOT NULL, + logistics_info_id INTEGER NOT NULL, + food_info_id INTEGER, + row_type VARCHAR(255) NOT NULL, + item_type VARCHAR(255) NOT NULL, + search_string TEXT NOT NULL, + UNIQUE(barcode, item_info_id), + CONSTRAINT fk_item_info + FOREIGN KEY(item_info_id) + REFERENCES test_item_info(id), + CONSTRAINT fk_food_info + FOREIGN KEY(food_info_id) + REFERENCES test_food_info(id), + CONSTRAINT fk_brand + FOREIGN KEY(brand) + REFERENCES test_brands(id), + CONSTRAINT fk_logistics_info + FOREIGN KEY(logistics_info_id) + REFERENCES test_logistics_info(id) +); diff --git a/sites/test/sql/create/item_info.sql b/sites/test/sql/create/item_info.sql new file mode 100644 index 0000000..317106c --- /dev/null +++ b/sites/test/sql/create/item_info.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOt EXISTS test_item_info ( + id SERIAL PRIMARY KEY, + barcode VARCHAR(255) NOT NULL, + linked_items INTEGER [], + shopping_lists INTEGER [], + recipes INTEGER [], + groups INTEGER [], + packaging VARCHAR(255), + uom VARCHAR(255), + cost FLOAT8, + safety_stock FLOAT8, + lead_time_days FLOAT8, + ai_pick BOOLEAN, + UNIQUE(barcode) +); \ No newline at end of file diff --git a/sites/test/sql/create/linked_items.sql b/sites/test/sql/create/linked_items.sql new file mode 100644 index 0000000..16a24e2 --- /dev/null +++ b/sites/test/sql/create/linked_items.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS test_itemlinks ( + id SERIAL PRIMARY KEY, + barcode VARCHAR(255) NOt NULL, + link INTEGER NOT NULL, + data JSONB NOT NULL, + conv_factor FLOAT8 NOt NULL, + UNIQUE(barcode) +); \ No newline at end of file diff --git a/sites/test/sql/create/locations.sql b/sites/test/sql/create/locations.sql new file mode 100644 index 0000000..da7ecdc --- /dev/null +++ b/sites/test/sql/create/locations.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS test_locations( + id SERIAL PRIMARY KEY, + uuid VARCHAR(255) NOT NULL, + name VARCHAR(32) NOT NULL, + zone_id INTEGER NOT NULL, + items JSONB, + UNIQUE(uuid), + CONSTRAINT fk_zone + FOREIGN KEY(zone_id) + REFERENCES test_zones(id) +); \ No newline at end of file diff --git a/sites/test/sql/create/logins.sql b/sites/test/sql/create/logins.sql new file mode 100644 index 0000000..f69b01b --- /dev/null +++ b/sites/test/sql/create/logins.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS logins( + id SERIAL PRIMARY KEY, + username VARCHAR(255), + password VARCHAR(255), + favorites JSONB, + unseen_pantry_items INTEGER [], + unseen_groups INTEGER [], + unseen_shopping_lists INTEGER [], + unseen_recipes INTEGER [], + seen_pantry_items INTEGER [], + seen_groups INTEGER[], + seen_shopping_lists INTEGER [], + seen_recipes INTEGER [], + flags JSONB +); + diff --git a/sites/test/sql/create/logistics_info.sql b/sites/test/sql/create/logistics_info.sql new file mode 100644 index 0000000..7a77d79 --- /dev/null +++ b/sites/test/sql/create/logistics_info.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS test_logistics_info( + id SERIAL PRIMARY KEY, + barcode VARCHAR(255) NOT NULL, + primary_location VARCHAR(64), + auto_issue_location VARCHAR(64), + dynamic_locations JSONB, + location_data JSONB, + quantity_on_hand FLOAT8 NOT NULL, + UNIQUE(barcode) +); \ No newline at end of file diff --git a/sites/test/sql/create/receipt_items.sql b/sites/test/sql/create/receipt_items.sql new file mode 100644 index 0000000..f52a7eb --- /dev/null +++ b/sites/test/sql/create/receipt_items.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS test_receipt_items ( + id SERIAL PRIMARY KEY, + type VARCHAR(255) NOT NULL, + barcode VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + qty FLOAT8 NOT NULL, + data JSONB, + status VARCHAR (64) +); \ No newline at end of file diff --git a/sites/test/sql/create/receipts.sql b/sites/test/sql/create/receipts.sql new file mode 100644 index 0000000..c89b484 --- /dev/null +++ b/sites/test/sql/create/receipts.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS test_receipts ( + id SERIAL PRIMARY KEY, + receipt_id INTEGER NOT NULL, + receipt_status VARCHAR (64) NOT NULL, + date_submitted TIMESTAMP NOT NULL, + submitted_by INTEGER NOT NULL, + vendor_id INTEGER, + files JSONB, + UNIQUE(receipt_id) +); \ No newline at end of file diff --git a/sites/test/sql/create/recipes.sql b/sites/test/sql/create/recipes.sql new file mode 100644 index 0000000..150b4cc --- /dev/null +++ b/sites/test/sql/create/recipes.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS test_recipes ( + id SERIAL PRIMARY KEY, + name VARCHAR, + author INTEGER, + description TEXT, + creation_date TIMESTAMP, + custom_items JSONB, + pantry_items JSONB, + group_items JSONB, + instructions TEXT [], + picture_path TEXT +); \ No newline at end of file diff --git a/sites/test/sql/create/shopping_lists.sql b/sites/test/sql/create/shopping_lists.sql new file mode 100644 index 0000000..9661ef6 --- /dev/null +++ b/sites/test/sql/create/shopping_lists.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS test_shopping_lists ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + pantry_items INTEGER [], + custom_items JSONB, + recipes INTEGER [], + groups INTEGER [], + quantities JSONB, + author INTEGER, + creation_date TIMESTAMP, + type VARCHAR(64), + UNIQUE(name) +); \ No newline at end of file diff --git a/sites/test/sql/create/transactions.sql b/sites/test/sql/create/transactions.sql new file mode 100644 index 0000000..c781b14 --- /dev/null +++ b/sites/test/sql/create/transactions.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS test_Transactions ( + id SERIAL PRIMARY KEY, + timestamp TIMESTAMP, + logistics_info_id INTEGER NOT NULL, + barcode VARCHAR(255) NOT NULL, + name VARCHAR(255), + transaction_type VARCHAR(255) NOT NULL, + quantity FLOAT8 NOT NULL, + description TEXT, + user_id INTEGER NOT NULL, + data JSONB, + CONSTRAINT fk_logistics_info + FOREIGN KEY(logistics_info_id) + REFERENCES test_logistics_info(id) +); \ No newline at end of file diff --git a/sites/test/sql/create/vendors.sql b/sites/test/sql/create/vendors.sql new file mode 100644 index 0000000..bc113b6 --- /dev/null +++ b/sites/test/sql/create/vendors.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS test_vendors ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + address VARCHAR(255), + creation_date TIMESTAMP NOT NULL, + created_by TIMESTAMP NOT NULL, + phone_number VARCHAR(32) +); \ No newline at end of file diff --git a/sites/test/sql/create/zones.sql b/sites/test/sql/create/zones.sql new file mode 100644 index 0000000..0ed0a9e --- /dev/null +++ b/sites/test/sql/create/zones.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS test_zones( + id SERIAL PRIMARY KEY, + name VARCHAR(32) NOT NULL, + UNIQUE(name) +); diff --git a/sites/test/sql/drop/brands.sql b/sites/test/sql/drop/brands.sql new file mode 100644 index 0000000..f407a8c --- /dev/null +++ b/sites/test/sql/drop/brands.sql @@ -0,0 +1 @@ +DROP TABLE test_brands CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/food_info.sql b/sites/test/sql/drop/food_info.sql new file mode 100644 index 0000000..a4c3056 --- /dev/null +++ b/sites/test/sql/drop/food_info.sql @@ -0,0 +1 @@ +DROP TABLE test_food_info CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/groups.sql b/sites/test/sql/drop/groups.sql new file mode 100644 index 0000000..6b62f3b --- /dev/null +++ b/sites/test/sql/drop/groups.sql @@ -0,0 +1 @@ +DROP TABLE test_groups CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/item_info.sql b/sites/test/sql/drop/item_info.sql new file mode 100644 index 0000000..c84b0d1 --- /dev/null +++ b/sites/test/sql/drop/item_info.sql @@ -0,0 +1 @@ +DROP TABLE test_item_info CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/items.sql b/sites/test/sql/drop/items.sql new file mode 100644 index 0000000..097b9a7 --- /dev/null +++ b/sites/test/sql/drop/items.sql @@ -0,0 +1 @@ +DROP TABLE test_items CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/linked_items.sql b/sites/test/sql/drop/linked_items.sql new file mode 100644 index 0000000..bcc9093 --- /dev/null +++ b/sites/test/sql/drop/linked_items.sql @@ -0,0 +1 @@ +DROP TABLE test_itemlinks CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/locations.sql b/sites/test/sql/drop/locations.sql new file mode 100644 index 0000000..4a1f42e --- /dev/null +++ b/sites/test/sql/drop/locations.sql @@ -0,0 +1 @@ +DROP TABLE test_locations CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/logistics_info.sql b/sites/test/sql/drop/logistics_info.sql new file mode 100644 index 0000000..cb5abcd --- /dev/null +++ b/sites/test/sql/drop/logistics_info.sql @@ -0,0 +1 @@ +DROP TABLE test_logistics_info CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/receipt_items.sql b/sites/test/sql/drop/receipt_items.sql new file mode 100644 index 0000000..0f77f60 --- /dev/null +++ b/sites/test/sql/drop/receipt_items.sql @@ -0,0 +1 @@ +DROP TABLE test_receipt_items CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/receipts.sql b/sites/test/sql/drop/receipts.sql new file mode 100644 index 0000000..1d9502f --- /dev/null +++ b/sites/test/sql/drop/receipts.sql @@ -0,0 +1 @@ +DROP TABLE test_receipts CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/recipes.sql b/sites/test/sql/drop/recipes.sql new file mode 100644 index 0000000..0a626bd --- /dev/null +++ b/sites/test/sql/drop/recipes.sql @@ -0,0 +1 @@ +DROP TABLE test_recipes CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/shopping_lists.sql b/sites/test/sql/drop/shopping_lists.sql new file mode 100644 index 0000000..a4cec6d --- /dev/null +++ b/sites/test/sql/drop/shopping_lists.sql @@ -0,0 +1 @@ +DROP TABLE test_shopping_lists CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/transactions.sql b/sites/test/sql/drop/transactions.sql new file mode 100644 index 0000000..1356e47 --- /dev/null +++ b/sites/test/sql/drop/transactions.sql @@ -0,0 +1 @@ +DROP TABLE test_transactions CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/vendors.sql b/sites/test/sql/drop/vendors.sql new file mode 100644 index 0000000..28351e8 --- /dev/null +++ b/sites/test/sql/drop/vendors.sql @@ -0,0 +1 @@ +DROP TABLE test_vendors CASCADE; \ No newline at end of file diff --git a/sites/test/sql/drop/zones.sql b/sites/test/sql/drop/zones.sql new file mode 100644 index 0000000..c84c67b --- /dev/null +++ b/sites/test/sql/drop/zones.sql @@ -0,0 +1 @@ +DROP TABLE test_zones CASCADE; \ No newline at end of file diff --git a/sites/test/sql/unique/select_item_all.sql b/sites/test/sql/unique/select_item_all.sql new file mode 100644 index 0000000..0824e68 --- /dev/null +++ b/sites/test/sql/unique/select_item_all.sql @@ -0,0 +1,45 @@ +SELECT * FROM test_items + LEFT JOIN test_logistics_info ON test_items.logistics_info_id = test_logistics_info.id + LEFT JOIN test_item_info ON test_items.item_info_id = test_item_info.id + LEFT JOIN test_food_info ON test_items.food_info_id = test_food_info.id +WHERE test_items.id=%s; + +/* +00 - item_id +01 - barcode +02 - item_name +03 - brand (id) +04 - description +05 - tags +06 - links +07 - item_info_id +08 - logistics_info_id +09 - food_info_id +10 - row_type +11 - item_type +12 - search_string +13 - logistics_info_id +14 - barcode +15 - primary_location +16 - auto_issue_location +17 - dynamic_locations +18 - location_data +19 - quantity_on_hand +20 - item_info_id +21 - barcode +22 - linked_items +23 - shopping_lists +24 - recipes +25 - groups <-- +26 - packaging +27 - uom +28 - cost +29 - safety_stock +30 - lead_time_days +31 - ai_pick +32 - food_info_id +33 - food_groups +34 - ingrediants +35 - nutrients +36 - expires +*/ \ No newline at end of file diff --git a/sites/test2/site.ini b/sites/test2/site.ini new file mode 100644 index 0000000..719bed4 --- /dev/null +++ b/sites/test2/site.ini @@ -0,0 +1,9 @@ +[site] +site_name=test2 +site_owner=joe +email=jdoe@gmail.com + +[defaults] +default_zone=default +default_primary_location=all +default_auto_issue_location=all diff --git a/sites/test2/sql/create/brands.sql b/sites/test2/sql/create/brands.sql new file mode 100644 index 0000000..bb70d3c --- /dev/null +++ b/sites/test2/sql/create/brands.sql @@ -0,0 +1,4 @@ +CREATE TABLE IF NOT EXISTS test2_brands ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) +); \ No newline at end of file diff --git a/sites/test2/sql/create/food_info.sql b/sites/test2/sql/create/food_info.sql new file mode 100644 index 0000000..a37324a --- /dev/null +++ b/sites/test2/sql/create/food_info.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS test2_food_info ( + id SERIAL PRIMARY KEY, + food_groups TEXT [], + ingrediants TEXT [], + nutrients JSONB, + expires BOOLEAN +); \ No newline at end of file diff --git a/sites/test2/sql/create/groups.sql b/sites/test2/sql/create/groups.sql new file mode 100644 index 0000000..b5d51f1 --- /dev/null +++ b/sites/test2/sql/create/groups.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS test2_groups( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + included_items INTEGER [], + group_type VARCHAR(255), + UNIQUE (name) +); \ No newline at end of file diff --git a/sites/test2/sql/create/item.sql b/sites/test2/sql/create/item.sql new file mode 100644 index 0000000..71c9b76 --- /dev/null +++ b/sites/test2/sql/create/item.sql @@ -0,0 +1,28 @@ +CREATE TABLE IF NOT EXISTS test2_items( + id SERIAL PRIMARY KEY, + barcode VARCHAR(255) NOT NULL, + item_name VARCHAR(255) NOT NULL, + brand INTEGER, + description TEXT, + tags TEXT [], + links JSONB, + item_info_id INTEGER NOT NULL, + logistics_info_id INTEGER NOT NULL, + food_info_id INTEGER, + row_type VARCHAR(255) NOT NULL, + item_type VARCHAR(255) NOT NULL, + search_string TEXT NOT NULL, + UNIQUE(barcode, item_info_id), + CONSTRAINT fk_item_info + FOREIGN KEY(item_info_id) + REFERENCES test2_item_info(id), + CONSTRAINT fk_food_info + FOREIGN KEY(food_info_id) + REFERENCES test2_food_info(id), + CONSTRAINT fk_brand + FOREIGN KEY(brand) + REFERENCES test2_brands(id), + CONSTRAINT fk_logistics_info + FOREIGN KEY(logistics_info_id) + REFERENCES test2_logistics_info(id) +); diff --git a/sites/test2/sql/create/item_info.sql b/sites/test2/sql/create/item_info.sql new file mode 100644 index 0000000..1df3026 --- /dev/null +++ b/sites/test2/sql/create/item_info.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOt EXISTS test2_item_info ( + id SERIAL PRIMARY KEY, + barcode VARCHAR(255) NOT NULL, + linked_items INTEGER [], + shopping_lists INTEGER [], + recipes INTEGER [], + groups INTEGER [], + packaging VARCHAR(255), + uom VARCHAR(255), + cost FLOAT8, + safety_stock FLOAT8, + lead_time_days FLOAT8, + ai_pick BOOLEAN, + UNIQUE(barcode) +); \ No newline at end of file diff --git a/sites/test2/sql/create/linked_items.sql b/sites/test2/sql/create/linked_items.sql new file mode 100644 index 0000000..3bfa112 --- /dev/null +++ b/sites/test2/sql/create/linked_items.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS test2_itemlinks ( + id SERIAL PRIMARY KEY, + barcode VARCHAR(255) NOt NULL, + link INTEGER NOT NULL, + data JSONB NOT NULL, + conv_factor FLOAT8 NOt NULL, + UNIQUE(barcode) +); \ No newline at end of file diff --git a/sites/test2/sql/create/locations.sql b/sites/test2/sql/create/locations.sql new file mode 100644 index 0000000..aadb380 --- /dev/null +++ b/sites/test2/sql/create/locations.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS test2_locations( + id SERIAL PRIMARY KEY, + uuid VARCHAR(255) NOT NULL, + name VARCHAR(32) NOT NULL, + zone_id INTEGER NOT NULL, + items JSONB, + UNIQUE(uuid), + CONSTRAINT fk_zone + FOREIGN KEY(zone_id) + REFERENCES test2_zones(id) +); \ No newline at end of file diff --git a/sites/test2/sql/create/logins.sql b/sites/test2/sql/create/logins.sql new file mode 100644 index 0000000..f69b01b --- /dev/null +++ b/sites/test2/sql/create/logins.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS logins( + id SERIAL PRIMARY KEY, + username VARCHAR(255), + password VARCHAR(255), + favorites JSONB, + unseen_pantry_items INTEGER [], + unseen_groups INTEGER [], + unseen_shopping_lists INTEGER [], + unseen_recipes INTEGER [], + seen_pantry_items INTEGER [], + seen_groups INTEGER[], + seen_shopping_lists INTEGER [], + seen_recipes INTEGER [], + flags JSONB +); + diff --git a/sites/test2/sql/create/logistics_info.sql b/sites/test2/sql/create/logistics_info.sql new file mode 100644 index 0000000..3917bf0 --- /dev/null +++ b/sites/test2/sql/create/logistics_info.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS test2_logistics_info( + id SERIAL PRIMARY KEY, + barcode VARCHAR(255) NOT NULL, + primary_location VARCHAR(64), + auto_issue_location VARCHAR(64), + dynamic_locations JSONB, + location_data JSONB, + quantity_on_hand FLOAT8 NOT NULL, + UNIQUE(barcode) +); \ No newline at end of file diff --git a/sites/test2/sql/create/receipt_items.sql b/sites/test2/sql/create/receipt_items.sql new file mode 100644 index 0000000..04145f1 --- /dev/null +++ b/sites/test2/sql/create/receipt_items.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS test2_receipt_items ( + id SERIAL PRIMARY KEY, + type VARCHAR(255) NOT NULL, + barcode VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + qty FLOAT8 NOT NULL, + data JSONB, + status VARCHAR (64) +); \ No newline at end of file diff --git a/sites/test2/sql/create/receipts.sql b/sites/test2/sql/create/receipts.sql new file mode 100644 index 0000000..806ec2f --- /dev/null +++ b/sites/test2/sql/create/receipts.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS test2_receipts ( + id SERIAL PRIMARY KEY, + receipt_id INTEGER NOT NULL, + receipt_status VARCHAR (64) NOT NULL, + date_submitted TIMESTAMP NOT NULL, + submitted_by INTEGER NOT NULL, + vendor_id INTEGER, + files JSONB, + UNIQUE(receipt_id) +); \ No newline at end of file diff --git a/sites/test2/sql/create/recipes.sql b/sites/test2/sql/create/recipes.sql new file mode 100644 index 0000000..ab89b63 --- /dev/null +++ b/sites/test2/sql/create/recipes.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS test2_recipes ( + id SERIAL PRIMARY KEY, + name VARCHAR, + author INTEGER, + description TEXT, + creation_date TIMESTAMP, + custom_items JSONB, + pantry_items JSONB, + group_items JSONB, + instructions TEXT [], + picture_path TEXT +); \ No newline at end of file diff --git a/sites/test2/sql/create/shopping_lists.sql b/sites/test2/sql/create/shopping_lists.sql new file mode 100644 index 0000000..cb52654 --- /dev/null +++ b/sites/test2/sql/create/shopping_lists.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS test2_shopping_lists ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + pantry_items INTEGER [], + custom_items JSONB, + recipes INTEGER [], + groups INTEGER [], + quantities JSONB, + author INTEGER, + creation_date TIMESTAMP, + type VARCHAR(64), + UNIQUE(name) +); \ No newline at end of file diff --git a/sites/test2/sql/create/transactions.sql b/sites/test2/sql/create/transactions.sql new file mode 100644 index 0000000..77c42d0 --- /dev/null +++ b/sites/test2/sql/create/transactions.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS test2_Transactions ( + id SERIAL PRIMARY KEY, + timestamp TIMESTAMP, + logistics_info_id INTEGER NOT NULL, + barcode VARCHAR(255) NOT NULL, + name VARCHAR(255), + transaction_type VARCHAR(255) NOT NULL, + quantity FLOAT8 NOT NULL, + description TEXT, + user_id INTEGER NOT NULL, + data JSONB, + CONSTRAINT fk_logistics_info + FOREIGN KEY(logistics_info_id) + REFERENCES test2_logistics_info(id) +); \ No newline at end of file diff --git a/sites/test2/sql/create/vendors.sql b/sites/test2/sql/create/vendors.sql new file mode 100644 index 0000000..2d7a277 --- /dev/null +++ b/sites/test2/sql/create/vendors.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS test2_vendors ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + address VARCHAR(255), + creation_date TIMESTAMP NOT NULL, + created_by TIMESTAMP NOT NULL, + phone_number VARCHAR(32) +); \ No newline at end of file diff --git a/sites/test2/sql/create/zones.sql b/sites/test2/sql/create/zones.sql new file mode 100644 index 0000000..17a555e --- /dev/null +++ b/sites/test2/sql/create/zones.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS test2_zones( + id SERIAL PRIMARY KEY, + name VARCHAR(32) NOT NULL, + UNIQUE(name) +); diff --git a/sites/test2/sql/drop/brands.sql b/sites/test2/sql/drop/brands.sql new file mode 100644 index 0000000..0159f3f --- /dev/null +++ b/sites/test2/sql/drop/brands.sql @@ -0,0 +1 @@ +DROP TABLE test2_brands CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/food_info.sql b/sites/test2/sql/drop/food_info.sql new file mode 100644 index 0000000..7c1cb91 --- /dev/null +++ b/sites/test2/sql/drop/food_info.sql @@ -0,0 +1 @@ +DROP TABLE test2_food_info CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/groups.sql b/sites/test2/sql/drop/groups.sql new file mode 100644 index 0000000..0513fb2 --- /dev/null +++ b/sites/test2/sql/drop/groups.sql @@ -0,0 +1 @@ +DROP TABLE test2_groups CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/item_info.sql b/sites/test2/sql/drop/item_info.sql new file mode 100644 index 0000000..c786efe --- /dev/null +++ b/sites/test2/sql/drop/item_info.sql @@ -0,0 +1 @@ +DROP TABLE test2_item_info CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/items.sql b/sites/test2/sql/drop/items.sql new file mode 100644 index 0000000..df1f8a9 --- /dev/null +++ b/sites/test2/sql/drop/items.sql @@ -0,0 +1 @@ +DROP TABLE test2_items CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/linked_items.sql b/sites/test2/sql/drop/linked_items.sql new file mode 100644 index 0000000..0795351 --- /dev/null +++ b/sites/test2/sql/drop/linked_items.sql @@ -0,0 +1 @@ +DROP TABLE test2_itemlinks CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/locations.sql b/sites/test2/sql/drop/locations.sql new file mode 100644 index 0000000..8ea7d24 --- /dev/null +++ b/sites/test2/sql/drop/locations.sql @@ -0,0 +1 @@ +DROP TABLE test2_locations CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/logistics_info.sql b/sites/test2/sql/drop/logistics_info.sql new file mode 100644 index 0000000..5d5a625 --- /dev/null +++ b/sites/test2/sql/drop/logistics_info.sql @@ -0,0 +1 @@ +DROP TABLE test2_logistics_info CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/receipt_items.sql b/sites/test2/sql/drop/receipt_items.sql new file mode 100644 index 0000000..18c80dd --- /dev/null +++ b/sites/test2/sql/drop/receipt_items.sql @@ -0,0 +1 @@ +DROP TABLE test2_receipt_items CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/receipts.sql b/sites/test2/sql/drop/receipts.sql new file mode 100644 index 0000000..7795023 --- /dev/null +++ b/sites/test2/sql/drop/receipts.sql @@ -0,0 +1 @@ +DROP TABLE test2_receipts CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/recipes.sql b/sites/test2/sql/drop/recipes.sql new file mode 100644 index 0000000..ba30922 --- /dev/null +++ b/sites/test2/sql/drop/recipes.sql @@ -0,0 +1 @@ +DROP TABLE test2_recipes CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/shopping_lists.sql b/sites/test2/sql/drop/shopping_lists.sql new file mode 100644 index 0000000..e4475ab --- /dev/null +++ b/sites/test2/sql/drop/shopping_lists.sql @@ -0,0 +1 @@ +DROP TABLE test2_shopping_lists CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/transactions.sql b/sites/test2/sql/drop/transactions.sql new file mode 100644 index 0000000..330d9af --- /dev/null +++ b/sites/test2/sql/drop/transactions.sql @@ -0,0 +1 @@ +DROP TABLE test2_transactions CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/vendors.sql b/sites/test2/sql/drop/vendors.sql new file mode 100644 index 0000000..5fa0868 --- /dev/null +++ b/sites/test2/sql/drop/vendors.sql @@ -0,0 +1 @@ +DROP TABLE test2_vendors CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/drop/zones.sql b/sites/test2/sql/drop/zones.sql new file mode 100644 index 0000000..fc30e59 --- /dev/null +++ b/sites/test2/sql/drop/zones.sql @@ -0,0 +1 @@ +DROP TABLE test2_zones CASCADE; \ No newline at end of file diff --git a/sites/test2/sql/unique/select_item_all.sql b/sites/test2/sql/unique/select_item_all.sql new file mode 100644 index 0000000..c339e15 --- /dev/null +++ b/sites/test2/sql/unique/select_item_all.sql @@ -0,0 +1,45 @@ +SELECT * FROM test2_items + LEFT JOIN test2_logistics_info ON test2_items.logistics_info_id = test2_logistics_info.id + LEFT JOIN test2_item_info ON test2_items.item_info_id = test2_item_info.id + LEFT JOIN test2_food_info ON test2_items.food_info_id = test2_food_info.id +WHERE test2_items.id=%s; + +/* +00 - item_id +01 - barcode +02 - item_name +03 - brand (id) +04 - description +05 - tags +06 - links +07 - item_info_id +08 - logistics_info_id +09 - food_info_id +10 - row_type +11 - item_type +12 - search_string +13 - logistics_info_id +14 - barcode +15 - primary_location +16 - auto_issue_location +17 - dynamic_locations +18 - location_data +19 - quantity_on_hand +20 - item_info_id +21 - barcode +22 - linked_items +23 - shopping_lists +24 - recipes +25 - groups +26 - packaging +27 - uom +28 - cost +29 - safety_stock +30 - lead_time_days +31 - ai_pick +32 - food_info_id +33 - food_groups +34 - ingrediants +35 - nutrients +36 - expires +*/ \ No newline at end of file diff --git a/templates/groups/group.html b/templates/groups/group.html new file mode 100644 index 0000000..1f1f5d4 --- /dev/null +++ b/templates/groups/group.html @@ -0,0 +1,352 @@ + + + + + My Pantry - Groups + + + + + + + + + + + + + + + +
+
+
+
+
+
+

menu

+
+
+

+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+
+
+
+ +
+ + + + \ No newline at end of file diff --git a/templates/groups/index.html b/templates/groups/index.html new file mode 100644 index 0000000..8007a27 --- /dev/null +++ b/templates/groups/index.html @@ -0,0 +1,448 @@ + + + + + My Pantry - Groups + + + + + + + + + + + + + + + + +
+
+ +
+
+ menu +
+
+ search + +
+
+ tune +
+
+
+ +
+
+

Set Items Per Page

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + more_vert + + +
+ + + + + + \ No newline at end of file diff --git a/templates/item_page/index.html b/templates/item_page/index.html deleted file mode 100644 index 703602c..0000000 --- a/templates/item_page/index.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - -
-
-
-

{{item[2]}}

-
Database ID: {{item[0]}}
-
Barcode: {{item[1]}}
-
-
- - -
-
- - -
- -
-
-

Links

- -
-
- -
-
- -
- - - - - - - - - -
Reference TypeReference Name
-
-
Food Info
-
Logistics Info
-
Linked Items
-
-
-
-
- - - \ No newline at end of file diff --git a/templates/home.html b/templates/items/index.html similarity index 64% rename from templates/home.html rename to templates/items/index.html index 0aaf1d4..01c2c21 100644 --- a/templates/home.html +++ b/templates/items/index.html @@ -2,7 +2,7 @@ - My Pantry + My Pantry - Items @@ -22,17 +22,57 @@ border: 2px solid rgb(0 128 0 / 30%); /* Outline color */ background-color: rgb(0 128 0 / 30%); /* Fill color */ } + header, main, footer, body { + padding-left: 300px; + } + + @media only screen and (max-width : 992px) { + header, main, footer, body { + padding-left: 0; + } + } + .dropdown-disabled { + pointer-events: none; + opacity: 0.5; /* or your desired degree of transparency */ + } + - + +
-
- search - -
-
- tune +
+
+ menu +
+
+ search + +
+
+ tune +
@@ -146,10 +186,64 @@ more_vert
+ \ No newline at end of file diff --git a/templates/items/item.html b/templates/items/item.html new file mode 100644 index 0000000..35eaeca --- /dev/null +++ b/templates/items/item.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + +
+
+
+

{{item[2]}}

+
Database ID: {{item[0]}}
+
Barcode: {{item[1]}}
+
+
+ + +
+
+ + +
+ +
+
+
+
+ Links +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + + + + +
Reference TypeReference Name
+
+
Food Info
+
Logistics Info
+
Linked Items
+
+
+
+
+ + + + \ No newline at end of file diff --git a/templates/shopping-lists/edit.html b/templates/shopping-lists/edit.html new file mode 100644 index 0000000..4c11d01 --- /dev/null +++ b/templates/shopping-lists/edit.html @@ -0,0 +1,522 @@ + + + + + My Pantry + + + + + + + + + + + + + + + +
+
+
+
+
+
+

menu

+
+
+

+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+
+ + + + +
+
+
+
+
+
+
+ +
+ + + + + + + \ No newline at end of file diff --git a/templates/shopping-lists/index.html b/templates/shopping-lists/index.html new file mode 100644 index 0000000..ccd307d --- /dev/null +++ b/templates/shopping-lists/index.html @@ -0,0 +1,332 @@ + + + + + My Pantry + + + + + + + + + + + + + + + +
+
+
+
+ menu +
+
+ search + +
+
+ tune +
+
+
+ +
+
+

Set Items Per Page

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ + more_vert + + +
+ + + + + \ No newline at end of file diff --git a/templates/shopping-lists/view.html b/templates/shopping-lists/view.html new file mode 100644 index 0000000..53b2978 --- /dev/null +++ b/templates/shopping-lists/view.html @@ -0,0 +1,173 @@ + + + + + My Pantry + + + + + + + + + + + + + + + +
+
+
+

+
+

+
+
+

+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/webserver.py b/webserver.py index b12ddea..ea3e3bc 100644 --- a/webserver.py +++ b/webserver.py @@ -1,15 +1,47 @@ -from flask import Flask, render_template -import api +from flask import Flask, render_template, session +import api, config app = Flask(__name__) - +app.secret_key = '11gs22h2h1a4h6ah8e413a45' app.register_blueprint(api.database_api) +@app.route("/group/") +def group(id): + sites = config.sites_config() + return render_template("groups/group.html", id=id, current_site=session['selected_site'], sites=sites['sites']) + @app.route("/workshop") def workshop(): - return render_template("workshop.html") + sites = config.sites_config() + return render_template("workshop.html", current_site=session['selected_site'], sites=sites['sites']) + +@app.route("/shopping-list/view/") +def shopping_lists_view(id): + sites = config.sites_config() + return render_template("shopping-lists/view.html", id=id, current_site=session['selected_site'], sites=sites['sites']) + +@app.route("/shopping-list/edit/") +def shopping_lists_edit(id): + sites = config.sites_config() + return render_template("shopping-lists/edit.html", id=id, current_site=session['selected_site'], sites=sites['sites']) + +@app.route("/shopping-lists") +def shopping_lists(): + sites = config.sites_config() + return render_template("shopping-lists/index.html", current_site=session['selected_site'], sites=sites['sites']) + +@app.route("/groups") +def groups(): + sites = config.sites_config() + return render_template("groups/index.html", current_site=session['selected_site'], sites=sites['sites']) + +@app.route("/items") +def items(): + sites = config.sites_config() + return render_template("items/index.html", current_site=session['selected_site'], sites=sites['sites']) @app.route("/") def home(): - return render_template("home.html") + session['selected_site'] = 'main' + return render_template("items/index.html") app.run(host="0.0.0.0", port=5002, debug=True) \ No newline at end of file