from datetime import datetime import psycopg2, json import psycopg2.extras from dataclasses import dataclass, field import random import string class DatabaseError(Exception): def __init__(self, message, payload=[], sql=""): super().__init__(message) self.payload = payload self.message = str(message).replace("\n", "") self.sql = sql.replace("\n", "") self.log_error() def log_error(self): with open("database.log", "a+") as file: file.write("\n") file.write(f"{datetime.now()} --- ERROR --- DatabaseError(message='{self.message}',\n") file.write(f"{' '*41}payload={self.payload},\n") file.write(f"{' '*41}sql='{self.sql}')") def __str__(self): return f"DatabaseError(message='{self.message}', payload={self.payload}, sql='{self.sql}')" def tupleDictionaryFactory(columns, row): columns = [desc[0] for desc in columns] return dict(zip(columns, row)) def lst2pgarr(alist): return '{' + ','.join(alist) + '}' def updateStringFactory(updated_values: dict): set_clause = ', '.join([f"{key} = %s" for key in updated_values.keys()]) values = [] for value in updated_values.values(): if isinstance(value, dict): value = json.dumps(value) values.append(value) return set_clause, values def getUUID(n): random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=n)) return random_string # ------------------------- # Insert Database Functions # ------------------------- def insertShoppingListsTuple(conn, site, payload, convert=False): """insert payload into shopping_lists table of site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ shopping_list = () with open(f"sql/INSERT/insertShoppingListsTuple.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: shopping_list = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: shopping_list = rows except Exception as error: raise DatabaseError(error, payload, sql) return shopping_list def insertShoppingListItemsTuple(conn, site, payload, convert=False): """insert payload into shopping_list_items table of site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (uuid[str], sl_id[int], item_type[str], item_name[str], uom[str], qty[float], item_id[int], links[jsonb]) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ shopping_list_item = () with open(f"sql/INSERT/insertShoppingListItemsTuple.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: shopping_list_item = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: shopping_list_item = rows except Exception as error: raise DatabaseError(error, payload, sql) return shopping_list_item def insertReceiptsTuple(conn, site, payload, convert=False): """insert payload into receipt table of site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ receipt = () with open(f"sql/INSERT/insertReceiptsTuple.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: receipt = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: receipt = rows except Exception as error: raise DatabaseError(error, payload, sql) return receipt def insertReceiptItemsTuple(conn, site, payload, convert=False): """insert payload into receipt_items table of site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (type[str], receipt_id[int], barcode[str], name[str], qty[float], data[jsonb], status[str]) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ receipt_item = () with open(f"sql/INSERT/insertReceiptItemsTuple.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: receipt_item = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: receipt_item = rows except Exception as error: raise DatabaseError(error, payload, sql) return receipt_item def insertItemLinksTuple(conn, site, payload, convert=False): """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 = () with open(f"sql/INSERT/insertItemLinksTuple.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: link = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: link = rows except Exception as error: raise DatabaseError(error, payload, sql) return link def insertVendorsTuple(conn, site, payload, convert=False): """insert payload into vendors table of site Args: conn (_T_connector@connect): Postgresql Connector site (str): (vendor_name[str], vendor_address[str], creation_date[timestampe], created_by[int], phone_number[str]) payload (tuple): (vendor_name[str], vendor_address[str], creation_date[timestamp], created_by[int], phone_number[str]) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ vendor = () with open(f"sql/INSERT/insertVendorsTuple.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: vendor = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: vendor = rows except Exception as error: raise DatabaseError(error, payload, sql) return vendor def insertZonesTuple(conn, site, payload, convert=False): """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 """ zone = () with open(f"sql/INSERT/insertZonesTuple.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: zone = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: zone = rows except Exception as error: raise DatabaseError(error, payload, sql) return zone def insertLocationsTuple(conn, site, payload, convert=False): """insert payload into locations table of site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (uuid[str], name[str], zone_id[int], items[jsonb]) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ location = () with open(f"sql/INSERT/insertLocationsTuple.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: location = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: location = rows except Exception as error: raise DatabaseError(error, payload, sql) return location def insertLoginsTuple(conn, payload, convert=False): """Inserts payload into logins table Args: conn (_T_connector@connect): Postgresql Connector payload (tuple): (username[str], password[str], email[str]) convert (bool, optional): deteremines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted login """ login = () with open(f"sql/INSERT/insertLoginsTuple.sql", "r+") as file: sql = file.read() try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: login = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: login = rows except Exception as error: raise DatabaseError(error, payload, sql) return login def insertRecipeItemsTuple(conn, site, payload, convert=False): """insert into recipe_items table for site Args: conn (_T_connector@connect): Postgresql Connector site (stre): payload (tuple): (uuid[str], rp_id[int], item_type[str], item_name[str], uom[str], qty[float], item_id[int], links[jsonb]) convert (bool, optional): Determines if to return tuple as a dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ recipe_item = () with open(f"sql/INSERT/insertRecipeItemsTuple.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: recipe_item = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: recipe_item = rows except Exception as error: raise DatabaseError(error, payload, sql) return recipe_item def insertRecipesTuple(conn, site, payload, convert=False): """insert into recipes table for site Args: conn (_T_connector@connect): Postgresql Connector site (stre): payload (tuple): (name[str], author[int], description[str], creation_date[timestamp], instructions[list], picture_path[str]) convert (bool, optional): Determines if to return tuple as a dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ recipe = () with open(f"sql/INSERT/insertRecipesTuple.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: recipe = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: recipe = rows except Exception as error: raise DatabaseError(error, payload, sql) return recipe def insertGroupItemsTuple(conn, site, payload, convert=False): """insert into group_items table for site Args: conn (_T_connector@connect): Postgresql Connector site (stre): payload (tuple): (uuid[str], gr_id[int], item_type[str], item_name[str], uom[str], qty[float], item_id[int], links[jsonb]) convert (bool, optional): Determines if to return tuple as a dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ group_item = () with open(f"sql/INSERT/insertGroupItemsTuple.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: group_item = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: group_item = rows except Exception as error: raise DatabaseError(error, payload, sql) return group_item def insertGroupsTuple(conn, site, payload, convert=False): """insert into groups table for site Args: conn (_T_connector@connect): Postgresql Connector site (stre): payload (tuple): (name[str], description[str], included_items[lst2pgarr], group_type[str]) convert (bool, optional): Determines if to return tuple as a dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ group = () with open(f"sql/INSERT/insertGroupsTuple.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: group = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: group = rows except Exception as error: raise DatabaseError(error, payload, sql) return group def insertLogisticsInfoTuple(conn, site, payload, convert=False): """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 = () with open(f"sql/INSERT/insertLogisticsInfoTuple.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: logistics_info = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: logistics_info = rows except Exception as error: raise DatabaseError(error, payload, sql) return logistics_info def insertItemInfoTuple(conn, site, payload, convert=False): """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 = () with open(f"sql/INSERT/insertItemInfoTuple.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: item_info = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: item_info = rows except Exception as error: raise DatabaseError(error, payload, sql) return item_info def insertFoodInfoTuple(conn, site, payload, convert=False): """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 = () with open(f"sql/INSERT/insertFoodInfoTuple.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: food_info = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: food_info = rows except Exception as error: raise DatabaseError(error, payload, sql) return food_info def insertBrandsTuple(conn, site, payload, convert=False): """insert payload into brands table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (brand_name[str], ) convert (bool, optional): Determines if the tuple is returned as a dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ brand = () with open(f"sql/INSERT/insertBrandsTuple.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: brand = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: brand = rows except Exception as error: raise DatabaseError(error, payload, sql) return brand def insertItemTuple(conn, site, payload, convert=False): """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 = () with open(f"sql/INSERT/insertItemTuple.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: item = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: item = rows except Exception as error: raise DatabaseError(error, payload, sql) return item def insertItemLocationsTuple(conn, site, payload, convert=False): """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 = () with open(f"sql/INSERT/insertItemLocationsTuple.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: location = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: location = rows except Exception as error: raise DatabaseError(error, payload, sql) return location def insertCostLayersTuple(conn, site, payload, convert=False): """insert payload into cost_layers table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (aquisition_date[timestamp], quantity[float], cost[float], currency_type[str], expires[timestamp/None], vendor[int]) convert (bool, optional): Determines if tuple is returned as a dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ cost_layer = () with open(f"sql/INSERT/insertCostLayersTuple.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: cost_layer = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: cost_layer = rows except Exception as error: raise DatabaseError(error, payload, sql) return cost_layer def insertTransactionsTuple(conn, site, payload, convert=False): """insert payload into transactions table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (timestamp[timestamp], logistics_info_id[int], barcode[str], name[str], transaction_type[str], quantity[float], description[str], user_id[int], data[jsonb]) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ transaction = () with open(f"sql/INSERT/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 = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: transaction = rows except Exception as error: raise DatabaseError(error, payload, sql) return transaction def insertSitesTuple(conn, payload, convert=False): """inserts payload into sites table Args: conn (_T_connector@connect): Postgresql Connector payload (tuple): (site_name[str], site_description[str], creation_date[timestamp], site_owner_id[int], flags[dict], default_zone[str], default_auto_issue_location[str], default_primary_location[str]) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ site_tuple = () with open(f"sql/INSERT/insertSitesTuple.sql", "r+") as file: sql = file.read() try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: site_tuple = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: site_tuple = rows except Exception as error: raise DatabaseError(error, payload, sql) return site_tuple def insertRolesTuple(conn, payload, convert=False): """inserts payload into roles table Args: conn (_T_connector@connect): Postgresql Connector payload (tuple): (role_name[str], role_description[str], site_id[int], flags[jsonb]) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: inserted tuple """ role_tuple = () with open(f"sql/INSERT/insertRolesTuple.sql", "r+") as file: sql = file.read() try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: role_tuple = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: role_tuple = rows except Exception as error: raise DatabaseError(error, payload, sql) return role_tuple # ------------------------- # Update Database Functions # ------------------------- def updateItemLocation(conn, site, payload): item_location = () with open(f"sql/updateItemLocation.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: item_location = rows except Exception as error: return error return item_location def updateCostLayersTuple(conn, site, payload): """_summary_ Args: conn (_type_): _description_ site (_type_): _description_ payload (_type_): _description_ Returns: _type_: _description_ """ cost_layer = () with open(f"sql/updateCostLayersTuple.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: cost_layer = rows except Exception as error: return error return cost_layer # ------------------------- # Delete Database Functions # ------------------------- def __deleteTupleById(conn, site_name, payload, table, convert=False): """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): (table_to_delete_from, tuple_id) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: deleted tuple """ deleted = () sql = f"WITH deleted_rows AS (DELETE FROM {table} WHERE id IN ({','.join(['%s'] * len(payload))}) RETURNING *) SELECT * FROM deleted_rows;" try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchall() if rows and convert: deleted = [tupleDictionaryFactory(cur.description, r) for r in rows] elif rows and not convert: deleted = rows except Exception as error: raise DatabaseError(error, payload, sql) return deleted def deleteItemsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from items table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_items" return __deleteTupleById(conn, site, payload, table, convert) def deleteCostLayersTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from cost_layers table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_cost_layers" return __deleteTupleById(conn, site, payload, table, convert) def deleteLoginsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from cost_layers table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = "logins" return __deleteTupleById(conn, site, payload, table, convert) def deleteZonesTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from zones table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_zones" return __deleteTupleById(conn, site, payload, table, convert) def deleteRolesTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from roles table Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"roles" return __deleteTupleById(conn, site, payload, table, convert) def deleteBrandsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from brands table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_brands" return __deleteTupleById(conn, site, payload, table, convert) def deleteFoodInfoTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from food_info table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_food_info" return __deleteTupleById(conn, site, payload, table, convert) def deleteGroupsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from groups table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_groups" return __deleteTupleById(conn, site, payload, table, convert) def deleteGroupItemsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from group_items table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_group_items" return __deleteTupleById(conn, site, payload, table, convert) def deleteItemInfoTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from item_info table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_item_info" return __deleteTupleById(conn, site, payload, table, convert) def deleteItemLocationsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from item_locations table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_item_locations" return __deleteTupleById(conn, site, payload, table, convert) def deleteItemLinksTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from itemlinks table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_itemlinks" return __deleteTupleById(conn, site, payload, table, convert) def deleteLocationsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from locations table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_locations" return __deleteTupleById(conn, site, payload, table, convert) def deleteLogisticsInfoTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from logistics_info table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_logistics_info" return __deleteTupleById(conn, site, payload, table, convert) def deleteRecipesTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from recipes table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_recipes" return __deleteTupleById(conn, site, payload, table, convert) def deleteRecipeItemsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from recipe_items table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_recipe_items" return __deleteTupleById(conn, site, payload, table, convert) def deleteShoppingListsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from shopping_lists table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_shopping_lists" return __deleteTupleById(conn, site, payload, table, convert) def deleteShoppingListItemsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from shopping_list_items table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_shopping_list_items" return __deleteTupleById(conn, site, payload, table, convert) def deleteTransactionsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from transactions table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_transactions" return __deleteTupleById(conn, site, payload, table, convert) def deleteVendorsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from vendors table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_vendors" return __deleteTupleById(conn, site, payload, table, convert) def deleteReceiptsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from receipts table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_receipts" return __deleteTupleById(conn, site, payload, table, convert) def deleteReceiptItemsTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from receipt_items table for site Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"{site}_receipt_items" return __deleteTupleById(conn, site, payload, table, convert) def deleteSitesTuple(conn, site, payload, convert=False): """deletes tuple/s with ids from sites table Args: conn (_T_connector@connect): Postgresql Connector site (str): payload (tuple): (id1, id2, id3, ...) convert (bool, optional): Determines if to return tuple as dictionary. Defaults to False. Returns: tuple or dict: deleted tuple """ table = f"sites" return __deleteTupleById(conn, site, payload, table, convert) # ------------------------- # Update Database Functions # ------------------------- def __updateTuple(conn, site, table, payload, convert=False): """_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 = () set_clause, values = 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 = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: updated = rows except Exception as error: raise DatabaseError(error, payload, sql) return updated # ------------------------- # Select Database Functions # ------------------------- def __selectTuple(conn, site, table, payload, convert=False): selected = () sql = f"SELECT * FROM {table} WHERE id=%s;" try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: selected = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: selected = rows except Exception as error: raise DatabaseError(error, payload, sql) return selected def __selectTuples(conn, site, table, convert=False): selected = () sql = f"SELECT * FROM {table};" try: with conn.cursor() as cur: cur.execute(sql) rows = cur.fetchall() if rows and convert: selected = [tupleDictionaryFactory(cur.description, row) for row in rows] elif rows and not convert: selected = rows except Exception as error: raise DatabaseError(error, (), sql) return selected def _paginateTableTuples(conn, site, table, payload, convert=False): recordset = [] sql = f"SELECT * FROM {table} LIMIT {payload[0]} OFFSET {payload[1]};" try: if convert: with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur: cur.execute(sql, payload) recordset = cur.fetchall() recordset = [dict(record) for record in recordset] cur.execute(f"SELECT COUNT(*) FROM {table}") count = cur.fetchone() else: with conn.cursor() as cur: cur.execute(sql, payload) recordset = cur.fetchall() cur.execute(f"SELECT COUNT(*) FROM {table}") count = cur.fetchone() except Exception as error: raise DatabaseError(error, payload, sql) return recordset, count def selectItemLocationsTuple(conn, site_name, payload, convert=False): """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 = () select_item_location_sql = f"SELECT * FROM {site_name}_item_locations WHERE part_id = %s AND location_id = %s;" try: with conn.cursor() as cur: cur.execute(select_item_location_sql, payload) rows = cur.fetchone() if rows and convert: item_locations = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: item_locations = rows except Exception as error: return error return item_locations def selectCostLayersTuple(conn, site_name, payload, convert=False): """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 = () 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 conn.cursor() as cur: cur.execute(select_cost_layers_sql, payload) rows = cur.fetchall() if rows and convert: cost_layers = rows cost_layers = [tupleDictionaryFactory(cur.description, layer) for layer in rows] elif rows and not convert: cost_layers = rows except Exception as error: return error return cost_layers def selectSiteTuple(conn, payload, convert=False): """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 = () select_site_sql = f"SELECT * FROM sites WHERE site_name = %s;" try: with conn.cursor() as cur: cur.execute(select_site_sql, payload) rows = cur.fetchone() if rows and convert: site = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: site = rows except Exception as error: raise DatabaseError(error, payload, select_site_sql) return site def selectSitesTuple(conn, payload, convert=False): site = () select_sites_sql = f"SELECT * FROM sites WHERE id IN ({','.join(['%s'] * len(payload))}) RETURNING *;" try: with conn.cursor() as cur: cur.execute(select_sites_sql, payload) rows = cur.fetchall() if rows and convert: site = [tupleDictionaryFactory(cur.description, site) for site in rows] elif rows and not convert: site = rows except Exception as error: return error return site def selectRolesTuple(conn, payload, convert=False): """Select all Roles from roles table using site_id Args: conn (_T_connector@connect): Postgresql Connector payload (tuple): (site_id,) convert (bool, optional): determines if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: selected tuples """ roles = () select_roles_sql = f"SELECT * FROM roles WHERE site_id = %s;" try: with conn.cursor() as cur: cur.execute(select_roles_sql, payload) rows = cur.fetchall() if rows and convert: roles = [tupleDictionaryFactory(cur.description, role) for role in rows] elif rows and not convert: roles = rows except Exception as error: raise DatabaseError(error, payload, select_roles_sql) return roles # ------------------------- # Create Database Functions # ------------------------- def __createTable(conn, site, table): """creates table in site database Args: conn (_T_connector@connect): Postgresql Connector site (str): table (str): Raises: DatabaseError: """ with open(f"sql/CREATE/{table}.sql", 'r') as file: sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(sql) except Exception as error: raise DatabaseError(error, sql, table) # ----------------------- # Drop Database Functions # ----------------------- def __dropTable(conn, site, table): """drops table from site database Args: conn (_T_connector@connect): Postgresql Connector site (str): table (str): Raises: DatabaseError: """ with open(f"sql/DROP/{table}.sql", 'r') as file: sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(sql) except Exception as error: raise DatabaseError(error, sql, table) # ------------------------- # Custom Database Functions # ------------------------- def getItemLocation(conn, site_name, payload): """This functions returns the bundled ItemLocation of item_id and location_id, with the cost_layers pulled from the database as tuples. Args: conn (_T_connector@connect): site_name (str): payload (tuple): [item_id, location_id] Returns: list: list of the itemLocation with cost_layers selected """ item_location = list(selectItemLocationsTuple(conn, site_name, payload)) item_location[4] = selectCostLayersTuple(conn, site_name, (item_location[0], )) return item_location def getUser(conn, payload, convert=False): """_summary_ Args: conn (_type_): _description_ payload (tuple): (username, password) convert (bool, optional): _description_. Defaults to False. Raises: DatabaseError: _description_ Returns: _type_: _description_ """ user = () try: with conn.cursor() as cur: sql = f"SELECT * FROM logins WHERE username=%s;" cur.execute(sql, (payload[0],)) rows = cur.fetchone() if rows and rows[2] == payload[1] and convert: user = tupleDictionaryFactory(cur.description, rows) elif rows and rows[2] == payload[1] and not convert: user = rows except Exception as error: raise DatabaseError(error, payload, sql) return user def updateRemoveLoginSite(conn, payload, convert=False): sql = f"UPDATE logins SET sites = array_remove(sites, %s) WHERE id = %s RETURNING *;" login = () try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: login = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: login = rows except Exception as error: raise DatabaseError(error, payload, sql) return login def updateRemoveLoginRole(conn, payload, convert=False): sql = f"UPDATE logins SET site_roles = array_remove(site_roles, %s) WHERE id = %s RETURNING *;" login = () try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: login = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: login = rows except Exception as error: raise DatabaseError(error, payload, sql) return login def updateRemoveLoginSitesRoles(conn, payload, convert=False): """update logins table with payload Args: conn (_T_connector@connect): Postgresql Connector payload (tuple): (site_id, role_id, login_id) convert (bool, optional): determins if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: updated tuple """ sql = f"UPDATE logins SET sites = array_remove(sites, %s), site_roles = array_remove(site_roles, %s) WHERE id = %s RETURNING *;" login = () try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: login = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: login = rows except Exception as error: raise DatabaseError(error, payload, sql) return login def updateUsersSites(conn, site_id): try: select_sql = f"SELECT logins.id FROM logins WHERE sites @> ARRAY[%s];" with conn.cursor() as cur: cur.execute(select_sql, (site_id, )) user = tuple([row[0] for row in cur.fetchall()]) update_sql = f"UPDATE logins SET sites = array_remove(sites, %s) WHERE id = %s;" with conn.cursor() as cur: for user_id in user: cur.execute(update_sql, (site_id, user_id)) except Exception as error: raise error def updateUsersRoles(conn, role_id): try: select_sql = f"SELECT logins.id FROM logins WHERE site_roles @> ARRAY[%s];" with conn.cursor() as cur: cur.execute(select_sql, (role_id, )) users = tuple([row[0] for row in cur.fetchall()]) update_sql = f"UPDATE logins SET site_roles = array_remove(site_roles, %s) WHERE id = %s;" with conn.cursor() as cur: for user_id in users: cur.execute(update_sql, (role_id, user_id)) except Exception as error: raise error def updateAddLoginSitesRoles(conn, payload, convert=False): """update logins table with payload Args: conn (_T_connector@connect): Postgresql Connector payload (tuple): (site_id, role_id, login_id) convert (bool, optional): determins if to return tuple as dictionary. Defaults to False. Raises: DatabaseError: Returns: tuple or dict: updated tuple """ sql = f"UPDATE logins SET sites = sites || %s, site_roles = site_roles || %s WHERE id=%s RETURNING *;" login = () try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: login = tupleDictionaryFactory(cur.description, rows) elif rows and not convert: login = rows except Exception as error: raise DatabaseError(error, payload, sql) return login def getItemsWithQOH(conn, site, payload, convert=True): # used in items/index.html (getItems) recordset = [] count = 0 with open(f"sql/SELECT/getItemsWithQOH.sql", "r+") as file: sql = file.read().replace("%%site_name%%", site).replace("%%sort_order%%", payload[3]) payload = list(payload) payload.pop(3) try: if convert: with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur: cur.execute(sql, payload) recordset = cur.fetchall() recordset = [dict(record) for record in recordset] cur.execute(f"SELECT COUNT(*) FROM {site}_items WHERE search_string LIKE '%%' || %s || '%%';", (payload[0], )) count = cur.fetchone() else: with conn.cursor() as cur: cur.execute(sql, payload) recordset = cur.fetchall() cur.execute(f"SELECT COUNT(*) FROM {site}_items WHERE search_string LIKE '%%' || %s || '%%';", (payload[0], )) count = cur.fetchone() except Exception as error: raise DatabaseError(error, payload, sql) return recordset, count def getItemsForModal(conn, site, payload, convert=True): """ This database query returns all the items in the database specific for use with modals in the system. It returns all items that ARE NOT of the type link which is a linked item that we do not want anyone being able to interact with outside of editing info. Args: conn (_T_connector@connect): PostgreSQL connector site (str): payload (tuple): (search_string, limit, offset) convert (bool, optional): Determines if the items are returned as tuples or dictionaries. Defaults to True. Raises: DatabaseError: Returns: tuple: """ recordset = [] count = 0 with open(f"sql/SELECT/getItemsForModals.sql", "r+") as file: sql = file.read().replace("%%site_name%%", site) try: if convert: with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur: cur.execute(sql, payload) recordset = cur.fetchall() recordset = [dict(record) for record in recordset] cur.execute(f"SELECT COUNT(*) FROM {site}_items WHERE search_string LIKE '%%' || %s || '%%' AND {site}_items.row_type <> 'link';", (payload[0], )) count = cur.fetchone() else: with conn.cursor() as cur: cur.execute(sql, payload) recordset = cur.fetchall() cur.execute(f"SELECT COUNT(*) FROM {site}_items WHERE search_string LIKE '%%' || %s || '%%' AND {site}_items.row_type <> 'link';", (payload[0], )) count = cur.fetchone() except Exception as error: raise DatabaseError(error, payload, sql) return recordset, count def getItemAllByID(conn, site, payload, convert=False): item = () with open(f"sql/SELECT/getItemAllByID.sql", "r+") as file: getItemAllByID_sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(getItemAllByID_sql, payload) rows = cur.fetchone() if rows and convert: item = tupleDictionaryFactory(cur.description, rows) if rows and not convert: item = rows except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, getItemAllByID_sql) return item def getLinkedItemByBarcode(conn, site, payload, convert=True): item = () sql = f"SELECT * FROM {site}_itemlinks WHERE barcode=%s;" if convert: item = {} try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: item = tupleDictionaryFactory(cur.description, rows) if rows and not convert: item = rows except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return item def getItemAllByBarcode(conn, site, payload, convert=True): item = () if convert: item = {} linked_item = getLinkedItemByBarcode(conn, site, (payload[0],)) if len(linked_item) > 1: item = getItemAllByID(conn, site, payload=(linked_item['link'], ), convert=convert) item['item_info']['uom_quantity'] = linked_item['conv_factor'] else: with open(f"sql/SELECT/getItemAllByBarcode.sql", "r+") as file: getItemAllByBarcode_sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(getItemAllByBarcode_sql, payload) rows = cur.fetchone() if rows and convert: item = tupleDictionaryFactory(cur.description, rows) if rows and not convert: item = rows except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, getItemAllByBarcode_sql) return item def getZonesWithCount(conn, site, payload, convert=False): """_summary_ Args: conn (_type_): _description_ site (_type_): _description_ payload (_type_): (limit, offset) convert (bool, optional): _description_. Defaults to False. Raises: DatabaseError: _description_ Returns: _type_: _description_ """ zones = () count = 0 with open(f"sql/SELECT/getZonesWithCount.sql", "r+") as file: getZonesWithCount_sql = file.read().replace("%%site_name%%", site) with open(f"sql/SELECT/countZones.sql", "r+") as file: countZones_sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(getZonesWithCount_sql, payload) rows = cur.fetchall() if rows and convert: zones = [tupleDictionaryFactory(cur.description, row) for row in rows] if rows and not convert: zones = rows if rows: cur.execute(countZones_sql) count = cur.fetchone() except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, getZonesWithCount_sql) return zones, count def queryTuple(conn, sql, payload, convert=False): queryset = () try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchone() if rows and convert: queryset = tupleDictionaryFactory(cur.description, rows) if rows and not convert: queryset = rows except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return queryset def queryTuples(conn, sql, payload, convert=False): querysets = [] try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchall() if rows and convert: querysets = [tupleDictionaryFactory(cur.description, row) for row in rows] if rows and not convert: querysets = rows except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return querysets def getItemLocations(conn, site, payload, convert=False): locations = [] count = 0 with open(f"sql/SELECT/getItemLocations.sql", "r+") as file: sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchall() if rows and convert: locations = [tupleDictionaryFactory(cur.description, row) for row in rows] if rows and not convert: locations = rows cur.execute(f"SELECT COUNT(*) FROM {site}_item_locations WHERE part_id=%s;", (payload[0],)) count = cur.fetchone()[0] except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return locations, count def getReceipts(conn, site, payload, convert=False): receipts = [] count = 0 with open(f"sql/SELECT/getReceipts.sql", "r+") as file: sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchall() if rows and convert: receipts = [tupleDictionaryFactory(cur.description, row) for row in rows] if rows and not convert: receipts = rows cur.execute(f"SELECT COUNT(*) FROM {site}_receipts;") count = cur.fetchone()[0] except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return receipts, count def getReceiptByID(conn, site, payload, convert=False): receipt = [] with open(f"sql/SELECT/getReceiptByID.sql", "r+") as file: sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(sql, payload) row = cur.fetchone() if row and convert: receipt = tupleDictionaryFactory(cur.description, row) if row and not convert: receipt = row except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return receipt def request_receipt_id(conn, site_name): """gets the next id for receipts_id, currently returns a 8 digit number Args: site (str): site to get the next id for Returns: json: receipt_id, message, error keys """ next_receipt_id = None sql = f"SELECT receipt_id FROM {site_name}_receipts ORDER BY id DESC LIMIT 1;" try: with conn.cursor() as cur: cur.execute(sql) next_receipt_id = cur.fetchone() if next_receipt_id == None: next_receipt_id = "00000001" else: next_receipt_id = next_receipt_id[0] next_receipt_id = int(next_receipt_id.split("-")[1]) + 1 y = str(next_receipt_id) len_str = len(y) x = "".join(["0" for _ in range(8 - len_str)]) next_receipt_id = x + y except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload=(), sql=sql) return next_receipt_id def getShoppingLists(conn, site, payload, convert=True): """_summary_ Args: conn (_type_): _description_ site (_type_): _description_ payload (_type_): (limit, offset) convert (bool, optional): _description_. Defaults to True. Raises: DatabaseError: _description_ Returns: _type_: _description_ """ recordset = [] count = 0 with open(f"sql/SELECT/getShoppingLists.sql", "r+") as file: sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchall() if rows and convert: recordset = [tupleDictionaryFactory(cur.description, row) for row in rows] if rows and not convert: recordset = rows cur.execute(f"SELECT COUNT(*) FROM {site}_shopping_lists;") count = cur.fetchone()[0] except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return recordset, count def getShoppingList(conn, site, payload, convert=True): """_summary_ Args: conn (_type_): _description_ site (_type_): _description_ payload (_type_): (shopping_list_id, ) convert (bool, optional): _description_. Defaults to True. Raises: DatabaseError: _description_ Returns: _type_: _description_ """ recordset = [] if convert: recordset = {} with open(f"sql/SELECT/getShoppingListByID.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: recordset = tupleDictionaryFactory(cur.description, rows) if rows and not convert: recordset = rows except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return recordset def getGroups(conn, site, payload, convert=True): """_summary_ Args: conn (_type_): _description_ site (_type_): _description_ payload (_type_): (limit, offset) convert (bool, optional): _description_. Defaults to True. Raises: DatabaseError: _description_ Returns: _type_: _description_ """ recordset = [] count = 0 with open(f"sql/SELECT/getGroups.sql", "r+") as file: sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(sql, payload) rows = cur.fetchall() if rows and convert: recordset = [tupleDictionaryFactory(cur.description, row) for row in rows] if rows and not convert: recordset = rows cur.execute(f"SELECT COUNT(*) FROM {site}_groups;") count = cur.fetchone()[0] except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, payload, sql) return recordset, count def getItemsSafetyStock(conn, site, convert=True): """_summary_ Args: conn (_type_): _description_ site (_type_): _description_ payload (_type_): (limit, offset) convert (bool, optional): _description_. Defaults to True. Raises: DatabaseError: _description_ Returns: _type_: _description_ """ recordsets = [] with open(f"sql/SELECT/getItemsSafetyStock.sql", "r+") as file: sql = file.read().replace("%%site_name%%", site) try: with conn.cursor() as cur: cur.execute(sql) rows = cur.fetchall() if rows and convert: recordsets = [tupleDictionaryFactory(cur.description, row) for row in rows] if rows and not convert: recordsets = rows except (Exception, psycopg2.DatabaseError) as error: raise DatabaseError(error, None, sql) return recordsets