Began new database migration codebase

This commit is contained in:
Jadowyne Ulve 2025-08-23 11:31:51 -05:00
parent 39d866be70
commit a57b8a2044
125 changed files with 1145 additions and 5 deletions

View File

@ -0,0 +1,25 @@
CREATE TABLE IF NOT EXISTS logins(
id SERIAL PRIMARY KEY,
username VARCHAR(255),
password VARCHAR(255),
email VARCHAR(255) UNIQUE NOT NULL,
favorites JSONB DEFAULT '{}',
unseen_pantry_items INTEGER [] DEFAULT '{}',
unseen_groups INTEGER [] DEFAULT '{}',
unseen_shopping_lists INTEGER [] DEFAULT '{}',
unseen_recipes INTEGER [] DEFAULT '{}',
seen_pantry_items INTEGER [] DEFAULT '{}',
seen_groups INTEGER[] DEFAULT '{}',
seen_shopping_lists INTEGER [] DEFAULT '{}',
seen_recipes INTEGER [] DEFAULT '{}',
sites INTEGER [] DEFAULT '{}',
site_roles INTEGER [] DEFAULT '{}',
system_admin BOOLEAN DEFAULT FALSE,
flags JSONB DEFAULT '{}',
row_type VARCHAR(50),
profile_pic_url VARCHAR(255),
login_type VARCHAR(32),
UNIQUE(username),
CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')
);

View File

@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS roles(
id SERIAL PRIMARY KEY,
role_name VARCHAR(255) NOT NULL,
role_description TEXT,
site_id INTEGER NOT NULL,
flags JSONB DEFAULT '{}',
UNIQUE(role_name, site_id),
CONSTRAINT fk_site
FOREIGN KEY(site_id)
REFERENCES sites(id)
);

View File

@ -0,0 +1,12 @@
CREATE TABLE IF NOT EXISTS sites (
id SERIAL PRIMARY KEY,
site_name VARCHAR(120),
site_description TEXT,
creation_date TIMESTAMP,
site_owner_id INTEGER NOT NULL,
flags JSONB,
default_zone INTEGER DEFAULT NULL,
default_auto_issue_location INTEGER DEFAULT NULL,
default_primary_location INTEGER DEFAULT NULL,
UNIQUE(site_name)
);

View File

@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS units (
id SERIAL PRIMARY KEY,
plural VARCHAR(32),
single VARCHAR(32),
fullname VARCHAR(255),
description TEXT,
unique(plural),
unique(single),
unique(fullname)
);

View File

@ -619,8 +619,8 @@ class SiteManager:
"transactions", "transactions",
"item", "item",
"vendors", "vendors",
"groups", #"groups",
"group_items", #"group_items",
"receipts", "receipts",
"receipt_items", "receipt_items",
"recipes", "recipes",
@ -631,6 +631,7 @@ class SiteManager:
"conversions", "conversions",
"sku_prefix", "sku_prefix",
"barcodes", "barcodes",
"plans",
"plan_events" "plan_events"
] ]
self.drop_order = [ self.drop_order = [
@ -657,5 +658,6 @@ class SiteManager:
"conversions", "conversions",
"sku_prefix", "sku_prefix",
"barcodes", "barcodes",
"plans",
"plan_events" "plan_events"
] ]

View File

@ -0,0 +1,15 @@
from dataclasses import dataclass
from application.database_postgres.BaseModel import BasePayload, BaseModel
class BarcodesModel(BaseModel):
table_name = "barcodes"
primary_key = "barcode"
@dataclass
class Payload(BasePayload):
barcode: str
item_uuid: str
in_exchange: float
out_exchange: float
descriptor: str

View File

@ -0,0 +1,227 @@
from abc import ABC
import psycopg2
import datetime
import uuid
import json
import random
import string
from copy import deepcopy
import config
def validateUUID(uuid_string, version):
try:
u = uuid.UUID(uuid_string, version=version)
return u.version == version
except ValueError:
return False
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("logs/database.log", "a+") as file:
file.write("\n")
file.write(f"{datetime.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
class BasePayload(ABC):
"""BasePayloads holds the bare minimum methods required of a Payload. """
def payload_dictionary(self):
return deepcopy(self.__dict__)
class BaseModel(ABC):
"""Base Model holds the CRUD functionality for database management. Anything beyond what is built in this
model must be built into the specific models Class that extends this Class.
For each of these CRUD methods to work there must be a SQL file named {table_name}.sql inside of the
sql/INSERT, sql/CREATE, and sql/DROP that defines basic operations.
Inheritors MUST assign a 'table_name' and 'primary_key' class level variable. They must also define
a 'Payload' inner dataclass that returns a matching data scheme for INSERT basic funtions. You can
have any payloads inherit the BasePayload class in order to get basic payload functions intended to
be used in these basic operations.
"""
table_name: str = None # All extended class must assign a table name that CRUD uses to call upon
primary_key: str = 'id' # All extended class can assign a different primary key/cloumn which is used to call delete and update queries on.
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if not hasattr(cls, 'Payload'):
raise NotImplementedError(
f"{cls.__name__} must define an inner Payload class."
)
if not hasattr(cls, 'table_name') or cls.table_name is None:
raise NotImplementedError(f"{cls.__name__} must define 'table_name' class variable.")
if not hasattr(cls, 'primary_key') or cls.primary_key is None:
raise NotImplementedError(f"{cls.__name__} must define 'primary_key' class variable.")
if not isinstance(cls.table_name, str):
raise ValueError(f"{cls.__name__} must have table_name that is of type str")
if not isinstance(cls.primary_key, str):
raise ValueError(f"{cls.__name__} must have primary_key that is of type str")
@classmethod
def create_table(self, site, conn=None):
self_conn = False
with open(f"application/database_postgres/sql/CREATE/{self.table_name}.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)
if self_conn:
conn.commit()
conn.close()
except Exception as error:
raise DatabaseError(error, sql, self.table_name)
@classmethod
def drop_table(self, site, conn=None):
self_conn = False
with open(f"application/database_postgres/sql/DROP/{self.table_name}.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)
if self_conn:
conn.commit()
conn.close()
except Exception as error:
raise DatabaseError(error, sql, self.table_name)
@classmethod
def delete_tuples(self, site: str, payload: tuple, convert: bool = True, conn=None):
deleted = ()
self_conn = False
sql = f"WITH deleted_rows AS (DELETE FROM {site}_{self.table_name} WHERE {self.primary_key} 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 = True
self_conn = True
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
if self_conn:
conn.commit()
conn.close()
return deleted
except Exception as error:
raise DatabaseError(error, payload, sql)
@classmethod
def update_tuple(self, site: str, payload: dict, convert: bool = True, conn=None):
""" payload (dict): {'key': row_id, 'update': {... column_to_update: value_to_update_to...}} """
updated = ()
self_conn = False
set_clause, values = updateStringFactory(payload['update'])
values.append(payload['key'])
sql = f"UPDATE {site}_{self.table_name} SET {set_clause} WHERE {self.primary_key}=%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 = 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 DatabaseError(error, payload, sql)
@classmethod
def insert_tuple(self, site: str, payload: dict, convert: bool = True, conn=None):
record = ()
self_conn = False
with open(f"application/database_postgres/sql/INSERT/{self.table_name}.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 = 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 DatabaseError(error, payload, sql)

View File

@ -0,0 +1,11 @@
from dataclasses import dataclass
from application.database_postgres.BaseModel import BasePayload, BaseModel
class BrandsModel(BaseModel):
table_name = "brands"
@dataclass
class Payload(BasePayload):
name: str

View File

@ -0,0 +1,12 @@
from dataclasses import dataclass
from application.database_postgres.BaseModel import BasePayload, BaseModel
class ConversionsModel(BaseModel):
table_name = "conversions"
@dataclass
class Payload(BasePayload):
item_id: int
uom_id: int
conv_factor: float

View File

@ -0,0 +1,17 @@
from dataclasses import dataclass
import datetime
from application.database_postgres.BaseModel import BasePayload, BaseModel
class CostLayersModel(BaseModel):
table_name = "cost_layers"
@dataclass
class Payload(BasePayload):
aquisition_date: datetime.datetime
quantity: float
cost: float
currency_type: str
vendor: int = 0
expires: datetime.datetime = None

View File

@ -0,0 +1,24 @@
from dataclasses import dataclass, field
import json
from application.database_postgres.BaseModel import BasePayload, BaseModel, lst2pgarr
class FoodInfoModel(BaseModel):
table_name = "food_info"
@dataclass
class Payload(BasePayload):
food_groups: list = field(default_factory=list)
ingrediants: list = field(default_factory=list)
nutrients: dict = field(default_factory=dict)
expires: bool = False
default_expiration: float = 0.0
def payload_dictionary(self):
return {
'food_groups': lst2pgarr(self.food_groups),
'ingrediants': lst2pgarr(self.ingrediants),
'nutrients': json.dumps(self.nutrients),
'expires': self.expires,
'default_expiration': self.default_expiration
}

View File

@ -0,0 +1,24 @@
from dataclasses import dataclass, field
import json
from application.database_postgres.BaseModel import BasePayload, BaseModel, lst2pgarr
class ItemInfoModel(BaseModel):
table_name = "item_info"
@dataclass
class Payload(BasePayload):
barcode: str
packaging: str = ""
uom_quantity: float = 1.0
uom: int = 1
cost: float = 0.0
safety_stock: float = 0.0
lead_time_days: float = 0.0
ai_pick: bool = False
prefixes: list = field(default_factory=list)
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['prefixes'] = lst2pgarr(self.prefixes)
return payload

View File

@ -0,0 +1,18 @@
from dataclasses import dataclass, field
from application.database_postgres.BaseModel import BasePayload, BaseModel, lst2pgarr
class ItemLocationsModel(BaseModel):
table_name = "item_locations"
@dataclass
class Payload(BasePayload):
part_id: int
location_id: int
quantity_on_hand: float = 0.0
cost_layers: list = field(default_factory=list)
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['cost_layers'] = lst2pgarr(self.cost_layers)
return payload

View File

@ -0,0 +1,31 @@
from dataclasses import dataclass, field
import json
from application.database_postgres.BaseModel import BasePayload, BaseModel, lst2pgarr
class ItemsModel(BaseModel):
table_name = "items"
@dataclass
class Payload(BasePayload):
item_info_id: int
item_info_uuid: str
logistics_info_id: int
logistics_info_uuid: str
food_info_id: int
food_info_uuid: str
barcode: str = ""
item_name: str = ""
brand: int = 0
description: str = ""
tags: list = field(default_factory=list)
links: dict = field(default_factory=dict)
row_type: str = ""
item_type: str = ""
search_string: str =""
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['tags'] = lst2pgarr(self.tags)
payload['links'] = json.dumps(self.links)
return payload

View File

@ -0,0 +1,13 @@
from dataclasses import dataclass
from application.database_postgres.BaseModel import BasePayload, BaseModel
class LocationsModel(BaseModel):
table_name = "locations"
@dataclass
class Payload(BasePayload):
uuid: str
name: str
zone_id: int

View File

@ -0,0 +1,15 @@
from dataclasses import dataclass
from application.database_postgres.BaseModel import BasePayload, BaseModel
class LogisticsInfoModel(BaseModel):
table_name = "logistics_info"
@dataclass
class Payload(BasePayload):
barcode: str
primary_location: int
primary_zone: int
auto_issue_location: int
auto_issue_zone: int

View File

@ -0,0 +1,20 @@
from dataclasses import dataclass
import datetime
from application.database_postgres.BaseModel import BasePayload, BaseModel
class PlanEventsModel(BaseModel):
table_name = "plan_events"
@dataclass
class Payload(BasePayload):
plan_uuid: str
event_shortname: str
event_description: str
event_date_start: datetime.datetime
event_date_end: datetime.datetime
created_by: int
recipe_uuid: str
receipt_uuid: str
event_type: str

View File

@ -0,0 +1,12 @@
from dataclasses import dataclass
from application.database_postgres.BaseModel import BasePayload, BaseModel
class PlansModel(BaseModel):
table_name = "plans"
@dataclass
class Payload(BasePayload):
plan_shortname: str
plan_description: str
created_by: int

View File

@ -0,0 +1,24 @@
from dataclasses import dataclass, field
import json
from application.database_postgres.BaseModel import BasePayload, BaseModel
class ReceiptItemsModel(BaseModel):
table_name = "receipt_items"
@dataclass
class Payload(BasePayload):
type: str
receipt_id: int
barcode: str
item_uuid: str
name: str
qty: float = 1.0
uom: str = "each"
data: dict = field(default_factory=dict)
status: str = "Unresolved"
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['data'] = json.dumps(self.data)
return payload

View File

@ -0,0 +1,25 @@
from dataclasses import dataclass, field
import json
import datetime
from application.database_postgres.BaseModel import BasePayload, BaseModel
class ReceiptsModel(BaseModel):
table_name = "receipts"
@dataclass
class Payload(BasePayload):
receipt_id: str
receipt_status: str = "Unresolved"
date_submitted: datetime.datetime = field(init=False)
submitted_by: int = 0
vendor_id: int = 1
files: dict = field(default_factory=dict)
def __post_init__(self):
self.date_submitted = datetime.datetime.now()
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['files'] = json.dumps(self.files)
return payload

View File

@ -0,0 +1,23 @@
from dataclasses import dataclass, field
import json
from application.database_postgres.BaseModel import BasePayload, BaseModel
class RecipeItemsModel(BaseModel):
table_name = "recipe_items"
@dataclass
class Payload(BasePayload):
uuid: str
rp_id: int
item_type: str
item_name:str
uom: str
qty: float = 0.0
item_id: int = None
links: dict = field(default_factory=dict)
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['links'] = json.dumps(self.links)
return payload

View File

@ -0,0 +1,24 @@
from dataclasses import dataclass, field
import datetime
from application.database_postgres.BaseModel import BasePayload, BaseModel, lst2pgarr
class RecipesModel(BaseModel):
table_name = "recipes"
@dataclass
class Payload(BasePayload):
name: str
author: int
description: str
creation_date: datetime.datetime = field(init=False)
instructions: list = field(default_factory=list)
picture_path: str = ""
def __post_init__(self):
self.creation_date = datetime.datetime.now()
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['instructions'] = lst2pgarr(self.instructions)
return payload

View File

@ -0,0 +1,12 @@
from dataclasses import dataclass
from application.database_postgres.BaseModel import BasePayload, BaseModel
class SKUPrefixModel(BaseModel):
table_name = "sku_prefix"
@dataclass
class Payload(BasePayload):
uuid: str
name: str
description: str

View File

@ -0,0 +1,22 @@
from dataclasses import dataclass, field
import json
from application.database_postgres.BaseModel import BasePayload, BaseModel
class ShoppingListItemsModel(BaseModel):
table_name = "shopping_list_items"
@dataclass
class Payload(BasePayload):
list_uuid: str
item_type: str
item_name: str
uom: int
qty: float
item_uuid: str = None
links: dict = field(default_factory=dict)
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['links'] = json.dumps(self.links)
return payload

View File

@ -0,0 +1,18 @@
from dataclasses import dataclass, field
import datetime
from application.database_postgres.BaseModel import BasePayload, BaseModel
class ShoppingListsModel(BaseModel):
table_name = "shopping_lists"
@dataclass
class Payload(BasePayload):
name: str
description: str
author: int
sub_type: str = "plain"
creation_date: datetime.datetime = field(init=False)
list_type: str = "temporary"
def __post_init__(self):
self.creation_date = datetime.datetime.now()

View File

@ -0,0 +1,25 @@
from dataclasses import dataclass, field
import json
import datetime
from application.database_postgres.BaseModel import BasePayload, BaseModel
class TransactionsModel(BaseModel):
table_name = "transactions"
@dataclass
class Payload(BasePayload):
timestamp: datetime.datetime
logistics_info_id: int
barcode: str
name: str
transaction_type: str
quantity: float
description: str
user_id: int
data: dict = field(default_factory=dict)
def payload_dictionary(self):
payload = super().payload_dictionary()
payload['data'] = json.dumps(self.data)
return payload

View File

@ -0,0 +1,18 @@
from dataclasses import dataclass, field
import datetime
from application.database_postgres.BaseModel import BasePayload, BaseModel
class VendorsModel(BaseModel):
table_name = "vendors"
@dataclass
class Payload(BasePayload):
vendor_name: str
created_by: int
vendor_address: str = ""
creation_date: datetime.datetime = field(init=False)
phone_number: str = ""
def __post_init__(self):
self.creation_date = datetime.datetime.now()

View File

@ -0,0 +1,12 @@
from dataclasses import dataclass
from application.database_postgres.BaseModel import BasePayload, BaseModel
class ZonesModel(BaseModel):
table_name = "zones"
@dataclass
class Payload(BasePayload):
name: str
description: str = ""

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_barcodes (
barcode VARCHAR(32) PRIMARY KEY,
item_uuid UUID,
in_exchange FLOAT,
out_exchange FLOAT,
descriptor VARCHAR(255)
);

View File

@ -0,0 +1,4 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_brands (
id SERIAL PRIMARY KEY,
name VARCHAR(255)
);

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_conversions (
id SERIAL PRIMARY KEY,
item_id INTEGER NOT NULL,
uom_id INTEGER NOT NULL,
conv_factor FLOAT8 NOT NULL,
UNIQUE(item_id, uom_id)
);

View File

@ -0,0 +1,9 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_cost_layers (
id SERIAL PRIMARY KEY,
aquisition_date TIMESTAMP NOT NULL,
quantity FLOAT8 NOT NULL,
cost FLOAT8 NOT NULL,
currency_type VARCHAR(16) NOT NULL,
expires TIMESTAMP,
vendor INTEGER DEFAULT 0
);

View File

@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_food_info (
id SERIAL PRIMARY KEY,
food_info_uuid UUID DEFAULT uuid_generate_v4(),
food_groups TEXT [],
ingrediants TEXT [],
nutrients JSONB,
expires BOOLEAN,
default_expiration FLOAT8,
UNIQUE(food_info_uuid)
);

View File

@ -0,0 +1,14 @@
CREATE TABLE IF NOt EXISTS %%site_name%%_item_info (
id SERIAL PRIMARY KEY,
item_info_uuid UUID DEFAULT uuid_generate_v4(),
barcode VARCHAR(255),
packaging VARCHAR(255),
uom_quantity FLOAT8,
uom INTEGER,
cost FLOAT8,
safety_stock FLOAT8,
lead_time_days FLOAT8,
ai_pick BOOLEAN,
prefixes INTEGER [],
UNIQUE(item_info_uuid)
);

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_item_locations(
id SERIAL PRIMARY KEY,
part_id INTEGER NOT NULL,
location_id INTEGER NOT NULL,
quantity_on_hand FLOAT8 NOT NULL,
cost_layers INTEGER[] DEFAULT '{}',
UNIQUE(part_id, location_id),
CONSTRAINT fk_part_id
FOREIGN KEY(part_id)
REFERENCES %%site_name%%_items(id)
ON DELETE CASCADE,
CONSTRAINT fk_location_id
FOREIGN KEY(location_id)
REFERENCES %%site_name%%_locations(id)
ON DELETE CASCADE
);

View File

@ -0,0 +1,36 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_items(
id SERIAL PRIMARY KEY,
item_uuid UUID DEFAULT uuid_generate_v4(),
barcode VARCHAR(255),
item_name VARCHAR(255) NOT NULL,
brand INTEGER,
description TEXT,
tags TEXT [],
links JSONB,
item_info_id INTEGER NOT NULL,
item_info_uuid UUID NOT NULL,
logistics_info_id INTEGER NOT NULL,
logistics_info_uuid UUID NOT NULL,
food_info_id INTEGER,
food_info_uuid UUID NOT NULL,
row_type VARCHAR(255) NOT NULL,
item_type VARCHAR(255) NOT NULL,
search_string TEXT NOT NULL,
inactive BOOLEAN DEFAULT false NOT NULL,
UNIQUE(item_uuid),
CONSTRAINT fk_item_info
FOREIGN KEY(item_info_id)
REFERENCES %%site_name%%_item_info(id)
ON DELETE CASCADE,
CONSTRAINT fk_food_info
FOREIGN KEY(food_info_id)
REFERENCES %%site_name%%_food_info(id)
ON DELETE CASCADE,
CONSTRAINT fk_brand
FOREIGN KEY(brand)
REFERENCES %%site_name%%_brands(id),
CONSTRAINT fk_logistics_info
FOREIGN KEY(logistics_info_id)
REFERENCES %%site_name%%_logistics_info(id)
ON DELETE CASCADE
);

View File

@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_locations(
id SERIAL PRIMARY KEY,
uuid VARCHAR(255) NOT NULL,
name VARCHAR(32) NOT NULL,
zone_id INTEGER NOT NULL,
UNIQUE(uuid),
CONSTRAINT fk_zone
FOREIGN KEY(zone_id)
REFERENCES %%site_name%%_zones(id)
);

View File

@ -0,0 +1,22 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_logistics_info(
id SERIAL PRIMARY KEY,
logistics_info_uuid UUID DEFAULT uuid_generate_v4(),
barcode VARCHAR(255),
primary_location INTEGER NOT NULL,
primary_zone INTEGER NOT NULL,
auto_issue_location INTEGER NOT NULL,
auto_issue_zone INTEGER NOT NULL,
UNIQUE(logistics_info_uuid),
CONSTRAINT fk_primary_location
FOREIGN KEY(primary_location)
REFERENCES %%site_name%%_locations(id),
CONSTRAINT fk_primary_zone
FOREIGN KEY(primary_zone)
REFERENCES %%site_name%%_zones(id),
CONSTRAINT fk_auto_issue_location
FOREIGN KEY(auto_issue_location)
REFERENCES %%site_name%%_locations(id),
CONSTRAINT fk_auto_issue_zone
FOREIGN KEY(auto_issue_zone)
REFERENCES %%site_name%%_zones(id)
);

View File

@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_plan_events(
id SERIAL PRIMARY KEY,
event_uuid UUID DEFAULT gen_random_uuid(),
plan_uuid UUID,
recipe_uuid UUID,
receipt_uuid UUID DEFAULT NULL,
event_shortname VARCHAR(32) NOT NULL,
event_description TEXT,
event_date_start TIMESTAMP NOT NULL,
event_date_end TIMESTAMP NOT NULL,
created_by INTEGER NOT NULL,
event_type VARCHAR(32) NOT NULL,
UNIQUE(event_uuid)
)

View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_plans(
plan_uuid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
plan_shortname VARCHAR(32) NOT NULL,
plan_description TEXT,
created_by INTEGER NOT NULL
)

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_receipt_items (
id SERIAL PRIMARY KEY,
type VARCHAR(255) NOT NULL,
receipt_id INTEGER NOT NULL,
barcode VARCHAR(255),
item_uuid UUID,
name VARCHAR(255) NOT NULL,
qty FLOAT8 NOT NULL,
uom INTEGER NOT NULL,
data JSONB,
status VARCHAR (64),
CONSTRAINT fk_receipt
FOREIGN KEY(receipt_id)
REFERENCES %%site_name%%_receipts(id)
ON DELETE CASCADE
);

View File

@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_receipts (
id SERIAL PRIMARY KEY,
receipt_id VARCHAR (32) NOT NULL,
receipt_status VARCHAR (64) NOT NULL,
date_submitted TIMESTAMP NOT NULL,
submitted_by INTEGER NOT NULL,
vendor_id INTEGER,
files JSONB,
UNIQUE(receipt_id),
CONSTRAINT fk_vendor
FOREIGN KEY(vendor_id)
REFERENCES %%site_name%%_vendors(id)
);

View File

@ -0,0 +1,19 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_recipe_items (
id SERIAL PRIMARY KEY,
item_uuid UUID,
rp_id INTEGER NOT NULL,
item_type VARCHAR(32) NOT NULL,
item_name TEXT NOT NULL,
uom INTEGER NOT NULL,
qty FLOAT8 NOT NULL,
item_id INTEGER DEFAULT NULL,
links JSONB DEFAULT '{"main": ""}',
CONSTRAINT fk_rp_id
FOREIGN KEY(rp_id)
REFERENCES %%site_name%%_recipes(id)
ON DELETE CASCADE,
CONSTRAINT fk_item_id
FOREIGN KEY(item_id)
REFERENCES %%site_name%%_items(id)
ON DELETE CASCADE
);

View File

@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_recipes (
id SERIAL PRIMARY KEY,
recipe_uuid UUID DEFAULT gen_random_uuid() NOT NULL,
name VARCHAR,
author INTEGER,
description TEXT,
creation_date TIMESTAMP,
instructions TEXT [],
picture_path TEXT,
UNIQUE(recipe_uuid)
);

View File

@ -0,0 +1,12 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_shopping_list_items (
list_item_uuid UUID DEFAULT uuid_generate_v4() NOT NULL PRIMARY KEY,
list_uuid UUID NOT NULL,
item_type VARCHAR(32) NOT NULL,
item_name TEXT NOT NULL,
uom INTEGER NOT NULL,
qty FLOAT8 NOT NULL,
item_uuid UUID DEFAULT NULL,
links JSONB DEFAULT '{"main": ""}',
list_item_state BOOLEAN DEFAULT false,
UNIQUE(list_uuid, item_uuid)
);

View File

@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_shopping_lists (
id SERIAL PRIMARY KEY,
list_uuid UUID DEFAULT uuid_generate_v4() NOT NULL,
list_type VARCHAR(32),
name VARCHAR(255) NOT NULL,
description TEXT,
author INTEGER,
creation_date TIMESTAMP,
sub_type VARCHAR(64),
UNIQUE(list_uuid, name)
);

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_sku_prefix(
id SERIAL PRIMARY KEY,
uuid VARCHAR(16) NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
UNIQUE (name, uuid)
);

View File

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

View File

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_vendors (
id SERIAL PRIMARY KEY,
vendor_name VARCHAR(255) NOT NULL,
vendor_address VARCHAR(255),
creation_date TIMESTAMP NOT NULL,
created_by INTEGER NOT NULL,
phone_number VARCHAR(32)
);

View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS %%site_name%%_zones(
id SERIAL PRIMARY KEY,
name VARCHAR(32) NOT NULL,
description TEXT,
UNIQUE(name)
);

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_barcodes CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_brands CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_conversions CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_cost_layers CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_food_info CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_item_info CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_item_locations CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_items CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_locations CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_logistics_info CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_plan_events CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_plans CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_receipt_items CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_receipts CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_recipe_items CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_recipes CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_shopping_list_items CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_shopping_lists CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_sku_prefix CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_transactions CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_vendors CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %%site_name%%_zones CASCADE;

View File

@ -0,0 +1,4 @@
INSERT INTO %%site_name%%_barcodes
(barcode, item_uuid, in_exchange, out_exchange, descriptor)
VALUES (%(barcode)s, %(item_uuid)s, %(in_exchange)s, %(out_exchange)s, %(descriptor)s)
RETURNING *;

Some files were not shown because too many files have changed in this diff Show More