Really started setting the foundation for

adding items to the database.
This commit is contained in:
Jadowyne Ulve 2024-09-29 21:53:19 -05:00
parent c3349bde55
commit ef9d6f8c52
41 changed files with 228 additions and 47 deletions

Binary file not shown.

Binary file not shown.

18
database.md Normal file
View File

@ -0,0 +1,18 @@
# Database Management
- the way I look at it is
## Adding a new item
- item info, food info, logistics info created using the barcode and then attached to item.
- Transcation created against logistics info description "Item added", qty X into primary location within logistics info.
- QTY of X inserted into sites default location with {logistics_info_id: X}
- returns location_id and adds the location to the logistics info, location_data {location_id: X}
## Associating a item to a linkedItem
All transaction history needs to have its associated logistic id changed to the new number (barcode stays the same?) and the new items location info and qty on hand needs to be updated.

175
main.py
View File

@ -1,7 +1,10 @@
#!/usr/bin/python #!/usr/bin/python
import psycopg2 import psycopg2
from config import config from config import config
import json, datetime, copy
def lst2pgarr(alist):
return '{' + ','.join(alist) + '}'
def insert_row(table_name, name): 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"
@ -39,12 +42,14 @@ def create_table(sql_file: str):
if conn is not None: if conn is not None:
conn.close() conn.close()
def create_logistics_info(conn, site_name, barcode, quantity_on_hand=0.0): def create_logistics_info(conn, site_name, barcode, payload):
sql = f"INSERT INTO {site_name}_logistics_info(barcode, quantity_on_hand) VALUES ('{barcode}', {quantity_on_hand}) RETURNING id;" sql = f"INSERT INTO {site_name}_logistics_info(barcode, primary_location, auto_issue_location, dynamic_locations, location_data, quantity_on_hand) VALUES (%s, %s, %s, %s, %s, %s) RETURNING id;"
logistics_info_id = None logistics_info_id = None
try: try:
with conn.cursor() as cur: with conn.cursor() as cur:
cur.execute(sql) cur.execute(sql,
(barcode, payload["primary_location"], payload["auto_issue_location"], json.dumps(payload["dynamic_locations"]),
json.dumps(payload["location_data"]), payload["quantity_on_hand"]))
rows = cur.fetchone() rows = cur.fetchone()
if rows: if rows:
logistics_info_id = rows[0] logistics_info_id = rows[0]
@ -55,12 +60,14 @@ def create_logistics_info(conn, site_name, barcode, quantity_on_hand=0.0):
return logistics_info_id return logistics_info_id
def create_item_info(conn, site_name, barcode): def create_item_info(conn, site_name, barcode, payload):
sql = f"INSERT INTO {site_name}_item_info(barcode) VALUES ('{barcode}') RETURNING id;" sql = f"INSERT INTO {site_name}_item_info(barcode, linked_items, shopping_lists, recipes, groups, packaging, uom, cost, safety_stock, lead_time_days, ai_pick) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING id;"
item_info_id = None item_info_id = None
try: try:
with conn.cursor() as cur: with conn.cursor() as cur:
cur.execute(sql) cur.execute(sql, (barcode, lst2pgarr(payload["linked_items"]), lst2pgarr(payload["shopping_lists"]), lst2pgarr(payload["recipes"]),
lst2pgarr(payload["groups"]), payload["packaging"], payload["uom"], payload["cost"], payload["safety_stock"], payload["lead_time_days"],
payload["ai_pick"]))
rows = cur.fetchone() rows = cur.fetchone()
if rows: if rows:
item_info_id = rows[0] item_info_id = rows[0]
@ -71,17 +78,102 @@ def create_item_info(conn, site_name, barcode):
return item_info_id return item_info_id
def add_item(site_name: str, barcode: str, name: str):
database_config = config() def create_food_info(conn, site_name, payload):
with psycopg2.connect(**database_config) as conn: sql = f"INSERT INTO {site_name}_food_info(ingrediants, food_groups, nutrients, expires) VALUES (%s, %s, %s, %s) RETURNING id;"
logistics_info_id = create_logistics_info(conn, site_name, barcode) food_info_id = None
if not logistics_info_id: try:
return False with conn.cursor() as cur:
item_info_id = create_item_info(conn, site_name, barcode) cur.execute(sql, (lst2pgarr(payload["ingrediants"]), lst2pgarr(payload["food_groups"]), json.dumps(payload["nutrients"]), payload["expires"]))
if not item_info_id: rows = cur.fetchone()
if rows:
food_info_id = rows[0]
except (Exception, psycopg2.DatabaseError) as error:
print(error)
conn.rollback()
return False return False
sqltwo = f"INSERT INTO {site_name}_items(barcode, item_name, item_info_id, logistics_info_id, row_type, item_type, search_string) VALUES('{barcode}', '{name}', {item_info_id}, {logistics_info_id}, 'item', 'other', '{barcode}%{name}') RETURNING *;" return food_info_id
def add_transaction(site_name, barcode, qty, user_id, transaction_type = "info", description = "", data = {}, location=None):
database_config = config()
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(f"SELECT item_name, logistics_info_id FROM {site_name}_items WHERE barcode=%s;", (barcode, ))
row = cur.fetchone()
print(row)
with conn.cursor() as cur:
cur.execute(f"SELECT location_data, quantity_on_hand, primary_location FROM {site_name}_logistics_info WHERE id=%s;", (row[1],))
logistics_info = cur.fetchone()
print(logistics_info)
new_trans = copy.deepcopy(transaction_payload)
new_trans["timestamp"] = datetime.datetime.now()
new_trans["logistics_info_id"] = row[1]
new_trans["barcode"] = barcode
new_trans["user_id"] = user_id
new_trans["name"] = row[0]
new_trans["transaction_type"] = transaction_type
new_trans["description"] = description
new_trans["quantity"] = qty
new_trans["data"] = data
sql = f"INSERT INTO {site_name}_transactions(timestamp, logistics_info_id, barcode, name, transaction_type, quantity, description, user_id, data) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s);"
database_config = config()
with psycopg2.connect(**database_config) as conn:
try:
with conn.cursor() as cur:
cur.execute(sql, (new_trans["timestamp"], new_trans["logistics_info_id"], new_trans["barcode"], new_trans["name"], new_trans["transaction_type"],
new_trans["quantity"], new_trans["description"], new_trans["user_id"], json.dumps(new_trans["data"])))
except (Exception, psycopg2.DatabaseError) as error:
print(error)
conn.rollback()
return False
if not location:
mover = logistics_info[2]
else:
mover = location
if mover in logistics_info[0].keys():
logistics_info[0][mover] = logistics_info[0][mover] + qty
else:
logistics_info[0][mover] = qty
qty = logistics_info[1] + qty
set_quantity_on_hand = f"UPDATE {site_name}_logistics_info SET quantity_on_hand = %s, location_data = %s WHERE id = %s;"
try:
with conn.cursor() as cur:
cur.execute(set_quantity_on_hand, (qty, json.dumps(logistics_info[0]), new_trans["logistics_info_id"]))
except (Exception, psycopg2.DatabaseError) as error:
print(error)
conn.rollback()
return False
conn.commit()
def add_food_item(site_name: str, barcode: str, name: str, qty: float, payload: dict):
defaults = config(filename=f"sites/{site_name}/site.ini", section="defaults")
payload["logistics_info"]["primary_location"] = defaults["default_primary_location"]
payload["logistics_info"]["auto_issue_location"] = defaults["default_auto_issue_location"]
database_config = config()
with psycopg2.connect(**database_config) as conn:
logistics_info_id = create_logistics_info(conn, site_name, barcode, payload["logistics_info"])
if not logistics_info_id:
return False
item_info_id = create_item_info(conn, site_name, barcode, payload["item_info"])
if not item_info_id:
return False
food_info_id = create_food_info(conn, site_name, payload["food_info"])
if not food_info_id:
return False
sqltwo = f"INSERT INTO {site_name}_items(barcode, item_name, item_info_id, logistics_info_id, food_info_id, row_type, item_type, search_string) VALUES('{barcode}', '{name}', {item_info_id}, {logistics_info_id}, {food_info_id}, 'item', 'FOOD', '{barcode}%{name}') RETURNING *;"
row = None row = None
try: try:
with conn.cursor() as cur: with conn.cursor() as cur:
@ -94,9 +186,13 @@ def add_item(site_name: str, barcode: str, name: str):
conn.rollback() conn.rollback()
return False return False
conn.commit() conn.commit()
return row
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): def drop_table(sql_file: str):
database_config = config() database_config = config()
@ -132,16 +228,61 @@ def create_site(site_name):
create_table(f'sites/{site_name}/sql/create/logins.sql') create_table(f'sites/{site_name}/sql/create/logins.sql')
create_table(f'sites/{site_name}/sql/create/groups.sql') create_table(f'sites/{site_name}/sql/create/groups.sql')
create_table(f'sites/{site_name}/sql/create/linked_items.sql') create_table(f'sites/{site_name}/sql/create/linked_items.sql')
create_table(f'sites/{site_name}/sql/create/transactions.sql')
create_table(f'sites/{site_name}/sql/create/brands.sql') create_table(f'sites/{site_name}/sql/create/brands.sql')
create_table(f'sites/{site_name}/sql/create/food_info.sql') create_table(f'sites/{site_name}/sql/create/food_info.sql')
create_table(f'sites/{site_name}/sql/create/item_info.sql') create_table(f'sites/{site_name}/sql/create/item_info.sql')
create_table(f'sites/{site_name}/sql/create/logistics_info.sql') create_table(f'sites/{site_name}/sql/create/logistics_info.sql')
create_table(f'sites/{site_name}/sql/create/transactions.sql')
create_table(f'sites/{site_name}/sql/create/item.sql') create_table(f'sites/{site_name}/sql/create/item.sql')
create_table(f'sites/{site_name}/sql/create/zones.sql') create_table(f'sites/{site_name}/sql/create/zones.sql')
create_table(f'sites/{site_name}/sql/create/locations.sql') create_table(f'sites/{site_name}/sql/create/locations.sql')
transaction_payload = {
"timestamp": None,
"logistics_info_id": 0,
"barcode": "",
"name": "",
"transaction_type": "info",
"quantity": 0.0,
"description": "",
"user_id": 0,
"data": {}
}
payload_food_item = {
"item_info": {
"linked_items": [],
"shopping_lists": [],
"recipes": [],
"groups": [],
"packaging": "Each",
"uom": "Each",
"cost": 0.0,
"safety_stock": 0.0,
"lead_time_days": 0.0,
"ai_pick": False
},
"food_info": {
"food_groups": [],
"ingrediants": [],
"nutrients": {},
"expires": False
},
"logistics_info":{
"primary_location": "",
"auto_issue_location": "",
"dynamic_locations": {},
"location_data": {},
"quantity_on_hand": 0.0
}
}
if __name__ == "__main__": if __name__ == "__main__":
#print(add_item(site_name="main", barcode="1235", name="testone")) #print(add_item(site_name="main", barcode="1235", name="testone"))
database_config = config() database_config = config()

View File

@ -89,3 +89,16 @@ if __name__ == "__main__":
main.delete_site(sys.argv[2]) main.delete_site(sys.argv[2])
shutil.rmtree(f"sites/{sys.argv[2]}") shutil.rmtree(f"sites/{sys.argv[2]}")
if func_name == "add_item":
barcode = input("barcode: ")
name = input("name: ")
qty = float(input("qty: "))
main.add_food_item(sys.argv[2], barcode, name, qty, payload=main.payload_food_item)
if func_name == "transact":
barcode = input("barcode: ")
qty = float(input("qty: "))
location = input("TO: ")
main.add_transaction(sys.argv[2], barcode, qty, 1, description="manual", location=location)

View File

@ -3,5 +3,5 @@ CREATE TABLE IF NOT EXISTS %sitename%_food_info (
food_groups TEXT [], food_groups TEXT [],
ingrediants TEXT [], ingrediants TEXT [],
nutrients JSONB, nutrients JSONB,
exires BOOLEAN expires BOOLEAN
); );

View File

@ -11,7 +11,6 @@ CREATE TABLE IF NOT EXISTS %sitename%_items(
row_type VARCHAR(255) NOT NULL, row_type VARCHAR(255) NOT NULL,
item_type VARCHAR(255) NOT NULL, item_type VARCHAR(255) NOT NULL,
search_string TEXT NOT NULL, search_string TEXT NOT NULL,
quantity_on_hand FLOAT8,
UNIQUE(barcode, item_info_id), UNIQUE(barcode, item_info_id),
CONSTRAINT fk_item_info CONSTRAINT fk_item_info
FOREIGN KEY(item_info_id) FOREIGN KEY(item_info_id)

View File

@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS %sitename%_locations(
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
name VARCHAR(32) NOT NULL, name VARCHAR(32) NOT NULL,
zone_id INTEGER NOT NULL, zone_id INTEGER NOT NULL,
items JSONB,
UNIQUE(name), UNIQUE(name),
CONSTRAINT fk_zone CONSTRAINT fk_zone
FOREIGN KEY(zone_id) FOREIGN KEY(zone_id)

View File

@ -1,11 +1,15 @@
CREATE TABLE IF NOT EXISTS %sitename%_Transactions ( CREATE TABLE IF NOT EXISTS %sitename%_Transactions (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
timestamp TIMESTAMP, timestamp TIMESTAMP,
logistics_info_id INTEGER NOT NULL,
barcode VARCHAR(255) NOT NULL, barcode VARCHAR(255) NOT NULL,
name VARCHAR(255), name VARCHAR(255),
transaction_type VARCHAR(255) NOT NULL, transaction_type VARCHAR(255) NOT NULL,
quantity FLOAT8 NOT NULL, quantity FLOAT8 NOT NULL,
description TEXT, description TEXT,
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
data JSONB data JSONB,
CONSTRAINT fk_logistics_info
FOREIGN KEY(logistics_info_id)
REFERENCES %sitename%_logistics_info(id)
); );

View File

@ -1 +0,0 @@
DROP TABLE main_brands CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_food_info CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_groups CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_item_info CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_items CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_itemlinks CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_locations CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_logistics_info CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_transactions CASCADE;

View File

@ -1 +0,0 @@
DROP TABLE main_zones CASCADE;

View File

@ -1,7 +1,8 @@
[site] [site]
site_name=main site_name=test
site_owner=jadowyne site_owner=test
email= email=
[defaults] [defaults]
default_zone=default default_zone=default
default_primary_location=all default_primary_location=all

View File

@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS main_brands ( CREATE TABLE IF NOT EXISTS test_brands (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
name VARCHAR(255) name VARCHAR(255)
); );

View File

@ -1,7 +1,7 @@
CREATE TABLE IF NOT EXISTS main_food_info ( CREATE TABLE IF NOT EXISTS test_food_info (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
food_groups TEXT [], food_groups TEXT [],
ingrediants TEXT [], ingrediants TEXT [],
nutrients JSONB, nutrients JSONB,
exires BOOLEAN expires BOOLEAN
); );

View File

@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS main_groups( CREATE TABLE IF NOT EXISTS test_groups(
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL,
description TEXT, description TEXT,

View File

@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS main_items( CREATE TABLE IF NOT EXISTS test_items(
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
barcode VARCHAR(255) NOT NULL, barcode VARCHAR(255) NOT NULL,
item_name VARCHAR(255) NOT NULL, item_name VARCHAR(255) NOT NULL,
@ -11,18 +11,17 @@ CREATE TABLE IF NOT EXISTS main_items(
row_type VARCHAR(255) NOT NULL, row_type VARCHAR(255) NOT NULL,
item_type VARCHAR(255) NOT NULL, item_type VARCHAR(255) NOT NULL,
search_string TEXT NOT NULL, search_string TEXT NOT NULL,
quantity_on_hand FLOAT8,
UNIQUE(barcode, item_info_id), UNIQUE(barcode, item_info_id),
CONSTRAINT fk_item_info CONSTRAINT fk_item_info
FOREIGN KEY(item_info_id) FOREIGN KEY(item_info_id)
REFERENCES main_item_info(id), REFERENCES test_item_info(id),
CONSTRAINT fk_food_info CONSTRAINT fk_food_info
FOREIGN KEY(food_info_id) FOREIGN KEY(food_info_id)
REFERENCES main_food_info(id), REFERENCES test_food_info(id),
CONSTRAINT fk_brand CONSTRAINT fk_brand
FOREIGN KEY(brand) FOREIGN KEY(brand)
REFERENCES main_brands(id), REFERENCES test_brands(id),
CONSTRAINT fk_logistics_info CONSTRAINT fk_logistics_info
FOREIGN KEY(logistics_info_id) FOREIGN KEY(logistics_info_id)
REFERENCES main_logistics_info(id) REFERENCES test_logistics_info(id)
); );

View File

@ -1,4 +1,4 @@
CREATE TABLE IF NOt EXISTS main_item_info ( CREATE TABLE IF NOt EXISTS test_item_info (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
barcode VARCHAR(255) NOT NULL, barcode VARCHAR(255) NOT NULL,
linked_items INTEGER [], linked_items INTEGER [],

View File

@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS main_itemlinks ( CREATE TABLE IF NOT EXISTS test_itemlinks (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
barcode VARCHAR(255) NOt NULL, barcode VARCHAR(255) NOt NULL,
link INTEGER NOT NULL, link INTEGER NOT NULL,

View File

@ -1,9 +1,10 @@
CREATE TABLE IF NOT EXISTS main_locations( CREATE TABLE IF NOT EXISTS test_locations(
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
name VARCHAR(32) NOT NULL, name VARCHAR(32) NOT NULL,
zone_id INTEGER NOT NULL, zone_id INTEGER NOT NULL,
items JSONB,
UNIQUE(name), UNIQUE(name),
CONSTRAINT fk_zone CONSTRAINT fk_zone
FOREIGN KEY(zone_id) FOREIGN KEY(zone_id)
REFERENCES main_zones(id) REFERENCES test_zones(id)
); );

View File

@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS main_logistics_info( CREATE TABLE IF NOT EXISTS test_logistics_info(
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
barcode VARCHAR(255) NOT NULL, barcode VARCHAR(255) NOT NULL,
primary_location VARCHAR(16), primary_location VARCHAR(16),

View File

@ -1,11 +1,15 @@
CREATE TABLE IF NOT EXISTS main_Transactions ( CREATE TABLE IF NOT EXISTS test_Transactions (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
timestamp TIMESTAMP, timestamp TIMESTAMP,
logistics_info_id INTEGER NOT NULL,
barcode VARCHAR(255) NOT NULL, barcode VARCHAR(255) NOT NULL,
name VARCHAR(255), name VARCHAR(255),
transaction_type VARCHAR(255) NOT NULL, transaction_type VARCHAR(255) NOT NULL,
quantity FLOAT8 NOT NULL, quantity FLOAT8 NOT NULL,
description TEXT, description TEXT,
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
data JSONB data JSONB,
CONSTRAINT fk_logistics_info
FOREIGN KEY(logistics_info_id)
REFERENCES test_logistics_info(id)
); );

View File

@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS main_zones( CREATE TABLE IF NOT EXISTS test_zones(
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
name VARCHAR(32) NOT NULL, name VARCHAR(32) NOT NULL,
UNIQUE(name) UNIQUE(name)

View File

@ -0,0 +1 @@
DROP TABLE test_brands CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_food_info CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_groups CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_item_info CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_items CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_itemlinks CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_locations CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_logistics_info CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_transactions CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE test_zones CASCADE;