pantry-track/application/items/database_items.py
2025-06-01 09:51:57 -05:00

1251 lines
46 KiB
Python

from application import postsqldb
import config
import psycopg2
import datetime
def getTransactions(site:str, payload: tuple, convert:bool=True):
""" Page through a sites Transactions by passing a logistics id, limit, and offset through a payload
Args:
site (str): _description_
payload (tuple): (logistics_id, limit, offset)
convert (bool, optional): _description_. Defaults to True.
Returns:
_type_: _description_
"""
database_config = config.config()
sql = f"SELECT * FROM {site}_transactions WHERE logistics_info_id=%s LIMIT %s OFFSET %s;"
sql_count = f"SELECT COUNT(*) FROM {site}_transactions WHERE logistics_info_id=%s;"
recordset = ()
count = 0
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
recordset = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
if rows and not convert:
recordset = rows
cur.execute(sql_count, (payload[0],))
count = cur.fetchone()[0]
return recordset, count
except Exception as error:
postsqldb.DatabaseError(error, payload, sql)
def getTransaction(site:str, payload: tuple, convert:bool=True):
database_config = config.config()
sql = f"SELECT * FROM {site}_transactions WHERE id=%s;"
record = ()
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
record = postsqldb.tupleDictionaryFactory(cur.description, rows)
if rows and not convert:
record = rows
return record
except Exception as error:
postsqldb.DatabaseError(error, payload, sql)
def getItemAllByID(site:str, payload: tuple, convert:bool=True):
database_config = config.config()
with open('application/items/sql/getItemAllByID.sql', 'r+') as file:
sql = file.read().replace("%%site_name%%", site)
record = ()
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
record = postsqldb.tupleDictionaryFactory(cur.description, rows)
if rows and not convert:
record = rows
return record
except Exception as error:
postsqldb.DatabaseError(error, payload, sql)
def getItemAllByBarcode(site:str, payload: tuple, convert:bool=True):
database_config = config.config()
with open('application/items/sql/getItemAllByBarcode.sql', 'r+') as file:
sql = file.read().replace("%%site_name%%", site)
record = ()
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
record = postsqldb.tupleDictionaryFactory(cur.description, rows)
if rows and not convert:
record = rows
return record
except Exception as error:
postsqldb.DatabaseError(error, payload, sql)
def getItemsWithQOH(site:str, payload: tuple, convert:bool=True):
database_config = config.config()
with open('application/items/sql/getItemsWithQOH.sql', 'r+') as file:
sql = file.read().replace("%%site_name%%", site).replace("%%sort_order%%", payload[3])
payload = list(payload)
payload.pop(3)
sql_count = f"SELECT COUNT(*) FROM {site}_items WHERE search_string LIKE '%%' || %s || '%%';"
recordset = ()
count = 0
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
recordset = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
if rows and not convert:
recordset = rows
cur.execute(sql_count, (payload[0],))
count = cur.fetchone()[0]
return recordset, count
except Exception as error:
postsqldb.DatabaseError(error, payload, sql)
def getModalSKUs(site:str, payload:tuple, convert:bool=True):
database_config = config.config()
with open("application/items/sql/itemsModal.sql") as file:
sql = file.read().replace("%%site_name%%", site)
with open("application/items/sql/itemsModalCount.sql") as file:
sql_count = file.read().replace("%%site_name%%", site)
recordset = []
count = 0
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
print(payload)
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
recordset = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
if rows and not convert:
recordset = rows
cur.execute(sql_count, (payload[0],))
count = cur.fetchone()[0]
return recordset, count
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def getPrefixes(site:str, payload:tuple, convert:bool=True):
database_config = config.config()
recordset = []
count = 0
with open(f"application/items/sql/getSkuPrefixes.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
recordset = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
if rows and not convert:
recordset = rows
cur.execute(f"SELECT COUNT(*) FROM {site}_sku_prefix;")
count = cur.fetchone()[0]
return recordset, count
except (Exception, psycopg2.DatabaseError) as error:
raise postsqldb.DatabaseError(error, payload, sql)
def getItemLink(site: str, payload:tuple, convert:bool=True):
database_config = config.config()
item_link = ()
sql = f"SELECT * FROM {site}_itemlinks WHERE id=%s;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
item_link = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
item_link = rows
return item_link
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def getLocation(site:str, payload:tuple, convert:bool=True):
selected = ()
database_config = config.config()
sql = f"SELECT * FROM {site}_locations WHERE id=%s;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
selected = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
selected = rows
return selected
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def getZone(site:str, payload:tuple, convert:bool=True):
selected = ()
database_config = config.config()
sql = f"SELECT * FROM {site}_zones WHERE id=%s;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
selected = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
selected = rows
return selected
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def getItemInfoTuple(site:str, payload:tuple, convert=True):
"""_summary_
Args:
conn (_type_): _description_
site (_type_): _description_
payload (_type_): (item_info_id,)
convert (bool, optional): _description_. Defaults to True.
Raises:
DatabaseError: _description_
Returns:
_type_: _description_
"""
selected = ()
database_config = config.config()
sql = f"SELECT * FROM {site}_item_info WHERE id=%s;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
selected = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
selected = rows
return selected
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def selectItemLocationsTuple(site_name, payload, convert=True):
"""select a single tuple from ItemLocations table for site_name
Args:
conn (_T_connector@connect):
site_name (str):
payload (tuple): [item_id, location_id]
convert (bool): defaults to False, used to determine return of tuple/dict
Returns:
tuple: the row that was returned from the table
"""
item_locations = ()
database_config = config.config()
select_item_location_sql = f"SELECT * FROM {site_name}_item_locations WHERE part_id = %s AND location_id = %s;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(select_item_location_sql, payload)
rows = cur.fetchone()
if rows and convert:
item_locations = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
item_locations = rows
return item_locations
except Exception as error:
return error
def selectCostLayersTuple(site_name, payload, convert=True):
"""select a single or series of cost layers from the database for site_name
Args:
conn (_T_connector@connect):
site_name (str):
payload (tuple): (item_locations_id, )
convert (bool): defaults to False, used for determining return as tuple/dict
Returns:
list: list of tuples/dict from the cost_layers table for site_name
"""
cost_layers = ()
database_config = config.config()
select_cost_layers_sql = f"SELECT cl.* FROM {site_name}_item_locations il JOIN {site_name}_cost_layers cl ON cl.id = ANY(il.cost_layers) where il.id=%s;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(select_cost_layers_sql, payload)
rows = cur.fetchall()
if rows and convert:
cost_layers = rows
cost_layers = [postsqldb.tupleDictionaryFactory(cur.description, layer) for layer in rows]
elif rows and not convert:
cost_layers = rows
return cost_layers
except Exception as error:
return error
def selectSiteTuple(payload, convert=True):
"""Select a single Site from sites using site_name
Args:
conn (_T_connector@connect): Postgresql Connector
payload (tuple): (site_name,)
convert (bool, optional): determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: selected tuples
"""
site = ()
database_config = config.config()
select_site_sql = f"SELECT * FROM sites WHERE site_name = %s;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(select_site_sql, payload)
rows = cur.fetchone()
if rows and convert:
site = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
site = rows
except Exception as error:
raise postsqldb.DatabaseError(error, payload, select_site_sql)
return site
def paginateZonesBySku(site: str, payload: tuple, convert=True):
database_config = config.config()
zones, count = (), 0
with open(f"application/items/sql/paginateZonesBySku.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
with open(f"application/items/sql/paginateZonesBySkuCount.sql", "r+") as file:
sql_count = file.read().replace("%%site_name%%", site)
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
zones = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
elif rows and not convert:
zones = rows
cur.execute(sql_count, payload)
count = cur.fetchone()[0]
return zones, count
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def paginateLocationsWithZone(site:str, payload:tuple, convert:bool=True):
recordset, count = (), 0
database_config = config.config()
with open(f"application/items/sql/getLocationsWithZone.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
recordset = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
elif rows and not convert:
recordset = rows
cur.execute(f"SELECT COUNT(*) FROM {site}_locations;")
count = cur.fetchone()[0]
return recordset, count
except Exception as error:
raise postsqldb.DatabaseError(error, (), sql)
def paginateLocationsBySkuZone(site: str, payload: tuple, convert=True):
database_config = config.config()
locations, count = (), 0
with open(f"application/items/sql/paginateLocationsBySkuZone.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
with open(f"application/items/sql/paginateLocationsBySkuZoneCount.sql", "r+") as file:
sql_count = file.read().replace("%%site_name%%", site)
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
locations = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
elif rows and not convert:
locations = rows
cur.execute(sql_count, payload)
count = cur.fetchone()[0]
return locations, count
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def paginateBrands(site:str, payload:tuple, convert:bool=True):
database_config = config.config()
recordset, count = [], 0
sql = f"SELECT brand.id, brand.name FROM {site}_brands brand LIMIT %s OFFSET %s;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
recordset = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
if rows and not convert:
recordset = rows
cur.execute(f"SELECT COUNT(*) FROM {site}_brands")
count = cur.fetchone()[0]
return recordset, count
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertCostLayersTuple(site, payload, convert=True, conn=None):
cost_layer = ()
self_conn = False
with open(f"application/items/sql/insertCostLayersTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = True
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
cost_layer = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
cost_layer = rows
if self_conn:
conn.commit()
conn.close()
return cost_layer
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertItemLocationsTuple(site, payload, convert=True, conn=None):
"""insert payload into item_locations table for site
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
payload (tuple): (part_id[int], location_id[int], quantity_on_hand[float], cost_layers[lst2pgarr])
convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: inserted tuple
"""
location = ()
self_conn = False
database_config = config.config()
with open(f"application/items/sql/insertItemLocationsTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = True
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
location = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
location = rows
if self_conn:
conn.commit()
conn.close()
return location
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertLogisticsInfoTuple(site, payload, convert=True, conn=None):
"""insert payload into logistics_info table for site
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
payload (tuple): (barcode[str], primary_location[str], auto_issue_location[str], dynamic_locations[jsonb],
location_data[jsonb], quantity_on_hand[float])
convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: inserted tuple
"""
logistics_info = ()
self_conn = False
with open(f"application/items/sql/insertLogisticsInfoTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = True
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
logistics_info = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
logistics_info = rows
if self_conn:
conn.commit()
conn.close()
return logistics_info
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertItemInfoTuple(site, payload, convert=True, conn=None):
"""inserts payload into the item_info table of site
Args:
conn (_T_connector@connect): Postgresql Connector
site_name (str):
payload (tuple): (barcode[str], linked_items[lst2pgarr], shopping_lists[lst2pgarr], recipes[lst2pgarr], groups[lst2pgarr],
packaging[str], uom[str], cost[float], safety_stock[float], lead_time_days[float], ai_pick[bool])
convert (bool optional): Determines if to return tuple as dictionary. DEFAULTS to False.
Raises:
DatabaseError:
Returns:
tuple or dict: inserted tuple
"""
item_info = ()
self_conn = False
with open(f"application/items/sql/insertItemInfoTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = True
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
item_info = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
item_info = rows
if self_conn:
conn.commit()
conn.close()
return item_info
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertFoodInfoTuple(site, payload, convert=True, conn=None):
"""insert payload into food_info table for site
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
payload (_type_): (ingrediants[lst2pgarr], food_groups[lst2pgarr], nutrients[jsonstr], expires[bool])
convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: inserted tuple
"""
food_info = ()
self_conn = False
with open(f"application/items/sql/insertFoodInfoTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = True
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
food_info = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
food_info = rows
if self_conn:
conn.commit()
conn.close()
return food_info
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertItemTuple(site, payload, convert=True, conn=None):
"""insert payload into items table for site
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
payload (tuple): (barcode[str], item_name[str], brand[int], description[str],
tags[lst2pgarr], links[jsonb], item_info_id[int], logistics_info_id[int],
food_info_id[int], row_type[str], item_type[str], search_string[str])
convert (bool, optional): Determines if to return tuple as a dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: inserted tuple
"""
item = ()
self_conn = False
with open(f"application/items/sql/insertItemTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = True
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
item = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
item = rows
if self_conn:
conn.commit()
conn.close()
return item
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertSKUPrefixtuple(site:str, payload:tuple, convert=True, conn=None):
"""insert payload into zones table of site
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
payload (tuple): (name[str],)
convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: inserted tuple
"""
prefix = ()
self_conn = False
with open(f"application/items/sql/insertSKUPrefixTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = True
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
prefix = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
prefix = rows
if self_conn:
conn.commit()
conn.close()
return prefix
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertConversionTuple(site: str, payload: list, convert=True, conn=None):
"""insert into recipes table for site
Args:
conn (_T_connector@connect): Postgresql Connector
site (stre):
payload (tuple): (item_id, uom_id, conversion_factor)
convert (bool, optional): Determines if to return tuple as a dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: inserted tuple
"""
record = ()
self_conn = False
with open(f"sql/INSERT/insertConversionsTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = True
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
record = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
record = rows
if self_conn:
conn.commit()
conn.close()
return record
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def postDeleteCostLayer(site_name, payload, convert=True, conn=None):
"""
payload (tuple): (table_to_delete_from, tuple_id)
Raises:
DatabaseError:
Returns:
tuple or dict: deleted tuple
"""
deleted = ()
self_conn = False
sql = f"WITH deleted_rows AS (DELETE FROM {site_name}_cost_layers WHERE id IN ({','.join(['%s'] * len(payload))}) RETURNING *) SELECT * FROM deleted_rows;"
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchall()
if rows and convert:
deleted = [postsqldb.tupleDictionaryFactory(cur.description, r) for r in rows]
elif rows and not convert:
deleted = rows
if self_conn:
conn.commit()
conn.close()
return deleted
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def deleteConversionTuple(site_name: str, payload: tuple, convert=True, conn=None):
"""This is a basic funtion to delete a tuple from a table in site with an id. All
tables in this database has id's associated with them.
Args:
conn (_T_connector@connect): Postgresql Connector
site_name (str):
payload (tuple): (tuple_id,...)
convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: deleted tuple
"""
deleted = ()
self_conn = False
sql = f"WITH deleted_rows AS (DELETE FROM {site_name}_conversions WHERE id IN ({','.join(['%s'] * len(payload))}) RETURNING *) SELECT * FROM deleted_rows;"
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
deleted = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
deleted = rows
if self_conn:
conn.commit()
conn.close()
return deleted
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def updateConversionTuple(site:str, payload: dict, convert=True, conn=None):
"""_summary_
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
table (str):
payload (dict): {'id': row_id, 'update': {... column_to_update: value_to_update_to...}}
convert (bool, optional): determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: updated tuple
"""
updated = ()
self_conn = False
set_clause, values = postsqldb.updateStringFactory(payload['update'])
values.append(payload['id'])
sql = f"UPDATE {site}_conversions SET {set_clause} WHERE id=%s RETURNING *;"
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, values)
rows = cur.fetchone()
if rows and convert:
updated = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
updated = rows
if self_conn:
conn.commit()
conn.close()
return updated
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def updateItemInfoTuple(site:str, payload: dict, convert=True, conn=None):
"""_summary_
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
table (str):
payload (dict): {'id': row_id, 'update': {... column_to_update: value_to_update_to...}}
convert (bool, optional): determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: updated tuple
"""
updated = ()
self_conn = False
set_clause, values = postsqldb.updateStringFactory(payload['update'])
values.append(payload['id'])
sql = f"UPDATE {site}_item_info SET {set_clause} WHERE id=%s RETURNING *;"
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, values)
rows = cur.fetchone()
if rows and convert:
updated = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
updated = rows
if self_conn:
conn.commit()
conn.close()
return updated
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def postUpdateItemLocation(site: str, payload: tuple, conn=None):
item_location = ()
self_conn = False
with open(f"sql/updateItemLocation.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows:
item_location = rows
if self_conn:
conn.commit()
conn.close()
return item_location
except Exception as error:
return error
# TODO: This should be in the item's process module
def postUpdateItem(site:str, payload:dict):
""" POST and update to an item
Args:
site (str): name of the site the item exists in.
payload (dict): STRICT FORMAT
{id: item_id, data: SEE BELOW, user_id: updater}
data is complex structure
top level keys should be a combo of: ['item', 'item_info', 'logistics_info', 'food_info']
with in each of these top levels there are key value pairs in this format
{'column_name': 'new_value'}
"""
def postUpdateData(conn, table, payload, convert=True):
updated = ()
set_clause, values = postsqldb.updateStringFactory(payload['update'])
values.append(payload['id'])
sql = f"UPDATE {table} SET {set_clause} WHERE id=%s RETURNING *;"
try:
with conn.cursor() as cur:
cur.execute(sql, values)
rows = cur.fetchone()
if rows and convert:
updated = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
updated = rows
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
return updated
def postAddTransaction(conn, site, payload, convert=False):
transaction = ()
with open(f"application/items/sql/insertTransactionsTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
transaction = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
transaction = rows
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
return transaction
transaction_data = {}
database_config = config.config()
data = payload['update']
for key in data.keys():
for key_2 in data[key].keys():
transaction_data[f"{key_2}_new"] = data[key][key_2]
try:
with psycopg2.connect(**database_config) as conn:
item = getItemAllByID(site, (payload['id'], ))
if 'item_info' in data.keys() and data['item_info'] != {}:
for key in data['item_info'].keys():
transaction_data[f"{key}_old"] = item['item_info'][key]
postUpdateData(conn, f"{site}_item_info", {'id': item['item_info_id'], 'update': data['item_info']})
if 'food_info' in data.keys() and data['food_info'] != {}:
for key in data['food_info'].keys():
transaction_data[f"{key}_old"] = item['food_info'][key]
postUpdateData(conn, f"{site}_food_info", {'id': item['food_info_id'], 'update': data['food_info']})
if 'logistics_info' in data.keys() and data['logistics_info'] != {}:
for key in data['logistics_info'].keys():
transaction_data[f"{key}_old"] = item['logistics_info'][key]
postUpdateData(conn, f"{site}_logistics_info", {'id': item['logistics_info_id'], 'update': data['logistics_info']})
if 'item' in data.keys() and data['item'] != {}:
for key in data['item'].keys():
if key == "brand":
transaction_data[f"{key}_old"] = item['brand']['id']
else:
transaction_data[f"{key}_old"] = item[key]
postUpdateData(conn, f"{site}_items", {'id': payload['id'], 'update': data['item']})
trans = postsqldb.TransactionPayload(
timestamp=datetime.datetime.now(),
logistics_info_id=item['logistics_info_id'],
barcode=item['barcode'],
name=item['item_name'],
transaction_type="UPDATE",
quantity=0.0,
description="Item was updated!",
user_id=payload['user_id'],
data=transaction_data
)
postAddTransaction(conn, site, trans.payload())
except Exception as error:
raise postsqldb.DatabaseError(error, payload, "MULTICALL!")
def postUpdateItemLink(site: str, payload: dict):
""" POST update to ItemLink
Args:
site (str): _description_
payload (dict): {id, update, old_conv_factor, user_id}
"""
def postUpdateData(conn, table, payload, convert=True):
updated = ()
set_clause, values = postsqldb.updateStringFactory(payload['update'])
values.append(payload['id'])
sql = f"UPDATE {table} SET {set_clause} WHERE id=%s RETURNING *;"
try:
with conn.cursor() as cur:
cur.execute(sql, values)
rows = cur.fetchone()
if rows and convert:
updated = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
updated = rows
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
return updated
def postAddTransaction(conn, site, payload, convert=False):
transaction = ()
with open(f"application/items/sql/insertTransactionsTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
transaction = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
transaction = rows
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
return transaction
database_config = config.config()
transaction_time = datetime.datetime.now()
barcode = payload['barcode']
with psycopg2.connect(**database_config) as conn:
linkedItem = getItemAllByBarcode(site, (barcode, ))
transaction = postsqldb.TransactionPayload(
timestamp=transaction_time,
logistics_info_id=linkedItem['logistics_info_id'],
barcode=barcode,
name=linkedItem['item_name'],
transaction_type='UPDATE',
quantity=0.0,
description='Link updated!',
user_id=payload['user_id'],
data={'new_conv_factor': payload['update']['conv_factor'], 'old_conv_factor': payload['old_conv_factor']}
)
postUpdateData(conn, f"{site}_itemlinks", {'id': payload['id'], 'update': {'conv_factor': payload['update']['conv_factor']}})
postAddTransaction(conn, site, transaction.payload())
def postUpdateCostLayer(site, payload, convert=True, conn=None):
"""_summary_
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
table (str):
payload (dict): {'id': row_id, 'update': {... column_to_update: value_to_update_to...}}
convert (bool, optional): determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: updated tuple
"""
updated = ()
self_conn = False
set_clause, values = postsqldb.updateStringFactory(payload['update'])
values.append(payload['id'])
sql = f"UPDATE {site}_cost_layers SET {set_clause} WHERE id=%s RETURNING *;"
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, values)
rows = cur.fetchone()
if rows and convert:
updated = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
updated = rows
if self_conn:
conn.commit()
conn.close()
return updated
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def postAddTransaction(site, payload, convert=False, conn=None):
transaction = ()
self_conn = False
with open(f"application/items/sql/insertTransactionsTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
transaction = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
transaction = rows
if self_conn:
conn.commit()
conn.close()
return transaction
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def postInsertItemLink(site, payload, convert=True, conn=None):
"""insert payload into itemlinks table of site
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
payload (tuple): (barcode[str], link[int], data[jsonb], conv_factor[float])
convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: inserted tuple
"""
link = ()
self_conn = False
with open(f"application/items/sql/insertItemLinksTuple.sql", "r+") as file:
sql = file.read().replace("%%site_name%%", site)
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, payload)
rows = cur.fetchone()
if rows and convert:
link = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
link = rows
if self_conn:
conn.commit()
conn.close()
return link, conn
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def postUpdateItemByID(site, payload, convert=True, conn=None):
""" high level update of an item specific data, none of its relationships
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
table (str):
payload (dict): {'id': row_id, 'update': {... column_to_update: value_to_update_to...}}
convert (bool, optional): determines if to return tuple as dictionary. Defaults to False.
Raises:
DatabaseError:
Returns:
tuple or dict: updated tuple
"""
updated = ()
self_conn = False
set_clause, values = postsqldb.updateStringFactory(payload['update'])
values.append(payload['id'])
sql = f"UPDATE {site}_items SET {set_clause} WHERE id=%s RETURNING *;"
try:
if not conn:
database_config = config.config()
conn = psycopg2.connect(**database_config)
conn.autocommit = False
self_conn = True
with conn.cursor() as cur:
cur.execute(sql, values)
rows = cur.fetchone()
if rows and convert:
updated = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
updated = rows
if self_conn:
conn.commit()
conn.close()
return updated, conn
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)