Transferred posting new item to new api
This commit is contained in:
parent
5933cc7338
commit
aec8f85a4d
461
application/database_payloads.py
Normal file
461
application/database_payloads.py
Normal file
@ -0,0 +1,461 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
import json, datetime
|
||||||
|
from database import lst2pgarr
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LogisticsInfoPayload:
|
||||||
|
barcode: str
|
||||||
|
primary_location: int
|
||||||
|
primary_zone: int
|
||||||
|
auto_issue_location: int
|
||||||
|
auto_issue_zone: int
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (self.barcode,
|
||||||
|
self.primary_location,
|
||||||
|
self.primary_zone,
|
||||||
|
self.auto_issue_location,
|
||||||
|
self.auto_issue_zone)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ItemInfoPayload:
|
||||||
|
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 __post_init__(self):
|
||||||
|
if not isinstance(self.barcode, str):
|
||||||
|
raise TypeError(f"barcode must be of type str; not {type(self.barcode)}")
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.barcode,
|
||||||
|
self.packaging,
|
||||||
|
self.uom_quantity,
|
||||||
|
self.uom,
|
||||||
|
self.cost,
|
||||||
|
self.safety_stock,
|
||||||
|
self.lead_time_days,
|
||||||
|
self.ai_pick,
|
||||||
|
lst2pgarr(self.prefixes)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FoodInfoPayload:
|
||||||
|
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(self):
|
||||||
|
return (
|
||||||
|
lst2pgarr(self.food_groups),
|
||||||
|
lst2pgarr(self.ingrediants),
|
||||||
|
json.dumps(self.nutrients),
|
||||||
|
self.expires,
|
||||||
|
self.default_expiration
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ItemsPayload:
|
||||||
|
barcode: str
|
||||||
|
item_name: str
|
||||||
|
item_info_id: int
|
||||||
|
logistics_info_id: int
|
||||||
|
food_info_id: int
|
||||||
|
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(self):
|
||||||
|
return (
|
||||||
|
self.barcode,
|
||||||
|
self.item_name,
|
||||||
|
self.brand,
|
||||||
|
self.description,
|
||||||
|
lst2pgarr(self.tags),
|
||||||
|
json.dumps(self.links),
|
||||||
|
self.item_info_id,
|
||||||
|
self.logistics_info_id,
|
||||||
|
self.food_info_id,
|
||||||
|
self.row_type,
|
||||||
|
self.item_type,
|
||||||
|
self.search_string
|
||||||
|
)
|
||||||
|
|
||||||
|
# done
|
||||||
|
@dataclass
|
||||||
|
class TransactionPayload:
|
||||||
|
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(self):
|
||||||
|
return (
|
||||||
|
self.timestamp,
|
||||||
|
self.logistics_info_id,
|
||||||
|
self.barcode,
|
||||||
|
self.name,
|
||||||
|
self.transaction_type,
|
||||||
|
self.quantity,
|
||||||
|
self.description,
|
||||||
|
self.user_id,
|
||||||
|
json.dumps(self.data)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CostLayerPayload:
|
||||||
|
aquisition_date: datetime.datetime
|
||||||
|
quantity: float
|
||||||
|
cost: float
|
||||||
|
currency_type: str
|
||||||
|
vendor: int = 0
|
||||||
|
expires: datetime.datetime = None
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.aquisition_date,
|
||||||
|
self.quantity,
|
||||||
|
self.cost,
|
||||||
|
self.currency_type,
|
||||||
|
self.expires,
|
||||||
|
self.vendor
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ItemLinkPayload:
|
||||||
|
barcode: str
|
||||||
|
link: int
|
||||||
|
data: dict = field(default_factory=dict)
|
||||||
|
conv_factor: float = 1
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if not isinstance(self.barcode, str):
|
||||||
|
raise TypeError(f"barcode must be of type str; not {type(self.barocde)}")
|
||||||
|
if not isinstance(self.link, int):
|
||||||
|
raise TypeError(f"link must be of type str; not {type(self.link)}")
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.barcode,
|
||||||
|
self.link,
|
||||||
|
json.dumps(self.data),
|
||||||
|
self.conv_factor
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class GroupPayload:
|
||||||
|
name: str
|
||||||
|
description: str
|
||||||
|
group_type: str = "plain"
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.name,
|
||||||
|
self.description,
|
||||||
|
self.group_type
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class GroupItemPayload:
|
||||||
|
uuid: str
|
||||||
|
gr_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(self):
|
||||||
|
return (
|
||||||
|
self.uuid,
|
||||||
|
self.gr_id,
|
||||||
|
self.item_type,
|
||||||
|
self.item_name,
|
||||||
|
self.uom,
|
||||||
|
self.qty,
|
||||||
|
self.item_id,
|
||||||
|
json.dumps(self.links)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RecipeItemPayload:
|
||||||
|
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(self):
|
||||||
|
return (
|
||||||
|
self.uuid,
|
||||||
|
self.rp_id,
|
||||||
|
self.item_type,
|
||||||
|
self.item_name,
|
||||||
|
self.uom,
|
||||||
|
self.qty,
|
||||||
|
self.item_id,
|
||||||
|
json.dumps(self.links)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RecipePayload:
|
||||||
|
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(self):
|
||||||
|
return (
|
||||||
|
self.name,
|
||||||
|
self.author,
|
||||||
|
self.description,
|
||||||
|
self.creation_date,
|
||||||
|
lst2pgarr(self.instructions),
|
||||||
|
self.picture_path
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ReceiptItemPayload:
|
||||||
|
type: str
|
||||||
|
receipt_id: int
|
||||||
|
barcode: str
|
||||||
|
name: str
|
||||||
|
qty: float = 1.0
|
||||||
|
uom: str = "each"
|
||||||
|
data: dict = field(default_factory=dict)
|
||||||
|
status: str = "Unresolved"
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.type,
|
||||||
|
self.receipt_id,
|
||||||
|
self.barcode,
|
||||||
|
self.name,
|
||||||
|
self.qty,
|
||||||
|
self.uom,
|
||||||
|
json.dumps(self.data),
|
||||||
|
self.status
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ReceiptPayload:
|
||||||
|
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(self):
|
||||||
|
return (
|
||||||
|
self.receipt_id,
|
||||||
|
self.receipt_status,
|
||||||
|
self.date_submitted,
|
||||||
|
self.submitted_by,
|
||||||
|
self.vendor_id,
|
||||||
|
json.dumps(self.files)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ShoppingListItemPayload:
|
||||||
|
uuid: str
|
||||||
|
sl_id: int
|
||||||
|
item_type: str
|
||||||
|
item_name: str
|
||||||
|
uom: str
|
||||||
|
qty: float
|
||||||
|
item_id: int = None
|
||||||
|
links: dict = field(default_factory=dict)
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.uuid,
|
||||||
|
self.sl_id,
|
||||||
|
self.item_type,
|
||||||
|
self.item_name,
|
||||||
|
self.uom,
|
||||||
|
self.qty,
|
||||||
|
self.item_id,
|
||||||
|
json.dumps(self.links)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ShoppingListPayload:
|
||||||
|
name: str
|
||||||
|
description: str
|
||||||
|
author: int
|
||||||
|
type: str = "plain"
|
||||||
|
creation_date: datetime.datetime = field(init=False)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
self.creation_date = datetime.datetime.now()
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.name,
|
||||||
|
self.description,
|
||||||
|
self.author,
|
||||||
|
self.creation_date,
|
||||||
|
self.type
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# DONE
|
||||||
|
@dataclass
|
||||||
|
class SitePayload:
|
||||||
|
site_name: str
|
||||||
|
site_description: str
|
||||||
|
site_owner_id: int
|
||||||
|
default_zone: str = None
|
||||||
|
default_auto_issue_location: str = None
|
||||||
|
default_primary_location: str = None
|
||||||
|
creation_date: datetime.datetime = field(init=False)
|
||||||
|
flags: dict = field(default_factory=dict)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
self.creation_date = datetime.datetime.now()
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.site_name,
|
||||||
|
self.site_description,
|
||||||
|
self.creation_date,
|
||||||
|
self.site_owner_id,
|
||||||
|
json.dumps(self.flags),
|
||||||
|
self.default_zone,
|
||||||
|
self.default_auto_issue_location,
|
||||||
|
self.default_primary_location
|
||||||
|
)
|
||||||
|
|
||||||
|
#DONE
|
||||||
|
@dataclass
|
||||||
|
class RolePayload:
|
||||||
|
role_name:str
|
||||||
|
role_description:str
|
||||||
|
site_id: int
|
||||||
|
flags: dict = field(default_factory=dict)
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.role_name,
|
||||||
|
self.role_description,
|
||||||
|
self.site_id,
|
||||||
|
json.dumps(self.flags)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ItemLocationPayload:
|
||||||
|
part_id: int
|
||||||
|
location_id: int
|
||||||
|
quantity_on_hand: float = 0.0
|
||||||
|
cost_layers: list = field(default_factory=list)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if not isinstance(self.part_id, int):
|
||||||
|
raise TypeError(f"part_id must be of type int; not {type(self.part_id)}")
|
||||||
|
if not isinstance(self.location_id, int):
|
||||||
|
raise TypeError(f"part_id must be of type int; not {type(self.part_id)}")
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.part_id,
|
||||||
|
self.location_id,
|
||||||
|
self.quantity_on_hand,
|
||||||
|
lst2pgarr(self.cost_layers)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SiteManager:
|
||||||
|
site_name: str
|
||||||
|
admin_user: tuple
|
||||||
|
default_zone: int
|
||||||
|
default_location: int
|
||||||
|
description: str
|
||||||
|
create_order: list = field(init=False)
|
||||||
|
drop_order: list = field(init=False)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
self.create_order = [
|
||||||
|
"logins",
|
||||||
|
"sites",
|
||||||
|
"roles",
|
||||||
|
"units",
|
||||||
|
"cost_layers",
|
||||||
|
"linked_items",
|
||||||
|
"brands",
|
||||||
|
"food_info",
|
||||||
|
"item_info",
|
||||||
|
"zones",
|
||||||
|
"locations",
|
||||||
|
"logistics_info",
|
||||||
|
"transactions",
|
||||||
|
"item",
|
||||||
|
"vendors",
|
||||||
|
"groups",
|
||||||
|
"group_items",
|
||||||
|
"receipts",
|
||||||
|
"receipt_items",
|
||||||
|
"recipes",
|
||||||
|
"recipe_items",
|
||||||
|
"shopping_lists",
|
||||||
|
"shopping_list_items",
|
||||||
|
"item_locations",
|
||||||
|
"conversions",
|
||||||
|
"sku_prefix"
|
||||||
|
]
|
||||||
|
self.drop_order = [
|
||||||
|
"item_info",
|
||||||
|
"items",
|
||||||
|
"cost_layers",
|
||||||
|
"linked_items",
|
||||||
|
"transactions",
|
||||||
|
"brands",
|
||||||
|
"food_info",
|
||||||
|
"logistics_info",
|
||||||
|
"zones",
|
||||||
|
"locations",
|
||||||
|
"vendors",
|
||||||
|
"group_items",
|
||||||
|
"groups",
|
||||||
|
"receipt_items",
|
||||||
|
"receipts",
|
||||||
|
"recipe_items",
|
||||||
|
"recipes",
|
||||||
|
"shopping_list_items",
|
||||||
|
"shopping_lists",
|
||||||
|
"item_locations",
|
||||||
|
"conversions",
|
||||||
|
"sku_prefix"
|
||||||
|
]
|
||||||
@ -3,7 +3,6 @@ import config
|
|||||||
import psycopg2
|
import psycopg2
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
def getTransactions(site:str, payload: tuple, convert:bool=True):
|
def getTransactions(site:str, payload: tuple, convert:bool=True):
|
||||||
database_config = config.config()
|
database_config = config.config()
|
||||||
sql = f"SELECT * FROM {site}_transactions WHERE logistics_info_id=%s LIMIT %s OFFSET %s;"
|
sql = f"SELECT * FROM {site}_transactions WHERE logistics_info_id=%s LIMIT %s OFFSET %s;"
|
||||||
@ -182,6 +181,23 @@ def getLocation(site:str, payload:tuple, convert:bool=True):
|
|||||||
except Exception as error:
|
except Exception as error:
|
||||||
raise postsqldb.DatabaseError(error, payload, sql)
|
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 paginateZonesBySku(site: str, payload: tuple, convert=True):
|
def paginateZonesBySku(site: str, payload: tuple, convert=True):
|
||||||
database_config = config.config()
|
database_config = config.config()
|
||||||
zones, count = (), 0
|
zones, count = (), 0
|
||||||
@ -513,6 +529,162 @@ def insertItemLocationsTuple(conn, site, payload, convert=True):
|
|||||||
except Exception as error:
|
except Exception as error:
|
||||||
raise postsqldb.DatabaseError(error, payload, sql)
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
|
||||||
|
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"application/items/sql/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 = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
logistics_info = rows
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.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"application/items/sql/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 = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
item_info = rows
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.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"application/items/sql/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 = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
food_info = rows
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
return food_info
|
||||||
|
|
||||||
|
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"application/items/sql/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 = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
item = rows
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.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"application/items/sql/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 = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
location = rows
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
return location
|
||||||
|
|
||||||
def selectItemLocationsTuple(site_name, payload, convert=True):
|
def selectItemLocationsTuple(site_name, payload, convert=True):
|
||||||
"""select a single tuple from ItemLocations table for site_name
|
"""select a single tuple from ItemLocations table for site_name
|
||||||
|
|
||||||
@ -570,6 +742,36 @@ def selectCostLayersTuple(site_name, payload, convert=True):
|
|||||||
except Exception as error:
|
except Exception as error:
|
||||||
return 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 postDeleteCostLayer(site_name, payload, convert=True, conn=None):
|
def postDeleteCostLayer(site_name, payload, convert=True, conn=None):
|
||||||
"""
|
"""
|
||||||
payload (tuple): (table_to_delete_from, tuple_id)
|
payload (tuple): (table_to_delete_from, tuple_id)
|
||||||
@ -660,7 +862,6 @@ def postAddTransaction(site, payload, convert=False, conn=None):
|
|||||||
except Exception as error:
|
except Exception as error:
|
||||||
raise postsqldb.DatabaseError(error, payload, sql)
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
|
||||||
|
|
||||||
def postInsertItemLink(site, payload, convert=True, conn=None):
|
def postInsertItemLink(site, payload, convert=True, conn=None):
|
||||||
"""insert payload into itemlinks table of site
|
"""insert payload into itemlinks table of site
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,22 @@
|
|||||||
from flask import Blueprint, request, render_template, redirect, session, url_for, send_file, jsonify, Response
|
# 3rd Party imports
|
||||||
import psycopg2, math, json, datetime, main, copy, requests, process, database, pprint, MyDataclasses
|
from flask import (
|
||||||
|
Blueprint, request, render_template, redirect, session, url_for, send_file, jsonify, Response
|
||||||
|
)
|
||||||
|
import psycopg2
|
||||||
|
import math
|
||||||
|
import json
|
||||||
|
import datetime
|
||||||
|
import copy
|
||||||
|
import requests
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
# applications imports
|
||||||
from config import config, sites_config
|
from config import config, sites_config
|
||||||
from main import unfoldCostLayers
|
from main import unfoldCostLayers
|
||||||
|
import process
|
||||||
|
import database
|
||||||
|
import main
|
||||||
|
import MyDataclasses
|
||||||
from user_api import login_required
|
from user_api import login_required
|
||||||
import application.postsqldb as db
|
import application.postsqldb as db
|
||||||
from application.items import database_items
|
from application.items import database_items
|
||||||
@ -25,14 +40,14 @@ def items():
|
|||||||
current_site=session['selected_site'],
|
current_site=session['selected_site'],
|
||||||
sites=sites)
|
sites=sites)
|
||||||
|
|
||||||
@items_api.route("/item/<id>")
|
@items_api.route("/<id>")
|
||||||
@login_required
|
@login_required
|
||||||
def item(id):
|
def item(id):
|
||||||
sites = [site[1] for site in main.get_sites(session['user']['sites'])]
|
sites = [site[1] for site in main.get_sites(session['user']['sites'])]
|
||||||
database_config = config()
|
database_config = config()
|
||||||
with psycopg2.connect(**database_config) as conn:
|
with psycopg2.connect(**database_config) as conn:
|
||||||
units = db.UnitsTable.getAll(conn)
|
units = db.UnitsTable.getAll(conn)
|
||||||
return render_template("items/item_new.html", id=id, units=units, current_site=session['selected_site'], sites=sites)
|
return render_template("item_new.html", id=id, units=units, current_site=session['selected_site'], sites=sites)
|
||||||
|
|
||||||
@items_api.route("/transaction")
|
@items_api.route("/transaction")
|
||||||
@login_required
|
@login_required
|
||||||
@ -43,14 +58,31 @@ def transaction():
|
|||||||
units = db.UnitsTable.getAll(conn)
|
units = db.UnitsTable.getAll(conn)
|
||||||
return render_template("transaction.html", units=units, current_site=session['selected_site'], sites=sites, proto={'referrer': request.referrer})
|
return render_template("transaction.html", units=units, current_site=session['selected_site'], sites=sites, proto={'referrer': request.referrer})
|
||||||
|
|
||||||
|
@items_api.route("/transactions/<id>")
|
||||||
|
@login_required
|
||||||
|
def transactions(id):
|
||||||
|
"""This is the main endpoint to reach the webpage for an items transaction history
|
||||||
|
---
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
type: integer
|
||||||
|
required: true
|
||||||
|
default: all
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Returns the transactions.html webpage for the item with passed ID
|
||||||
|
"""
|
||||||
|
sites = [site[1] for site in main.get_sites(session['user']['sites'])]
|
||||||
|
return render_template("transactions.html", id=id, current_site=session['selected_site'], sites=sites)
|
||||||
|
|
||||||
@items_api.route("/item/<parent_id>/itemLink/<id>")
|
@items_api.route("/<parent_id>/itemLink/<id>")
|
||||||
@login_required
|
@login_required
|
||||||
def itemLink(parent_id, id):
|
def itemLink(parent_id, id):
|
||||||
sites = [site[1] for site in main.get_sites(session['user']['sites'])]
|
sites = [site[1] for site in main.get_sites(session['user']['sites'])]
|
||||||
return render_template("itemlink.html", current_site=session['selected_site'], sites=sites, proto={'referrer': request.referrer}, id=id)
|
return render_template("itemlink.html", current_site=session['selected_site'], sites=sites, proto={'referrer': request.referrer}, id=id)
|
||||||
|
|
||||||
@items_api.route("/item/getTransactions", methods=["GET"])
|
@items_api.route("/getTransactions", methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
def getTransactions():
|
def getTransactions():
|
||||||
""" GET a subquery of transactions by passing a logistics_info_id, limit, and page
|
""" GET a subquery of transactions by passing a logistics_info_id, limit, and page
|
||||||
@ -71,7 +103,7 @@ def getTransactions():
|
|||||||
return jsonify({"transactions": recordset, "end": math.ceil(count/limit), "error": False, "message": ""})
|
return jsonify({"transactions": recordset, "end": math.ceil(count/limit), "error": False, "message": ""})
|
||||||
return jsonify({"transactions": recordset, "end": math.ceil(count/limit), "error": True, "message": f"method {request.method} is not allowed."})
|
return jsonify({"transactions": recordset, "end": math.ceil(count/limit), "error": True, "message": f"method {request.method} is not allowed."})
|
||||||
|
|
||||||
@items_api.route("/item/getTransaction", methods=["GET"])
|
@items_api.route("/getTransaction", methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
def getTransaction():
|
def getTransaction():
|
||||||
""" GET a transaction from the system by passing an ID
|
""" GET a transaction from the system by passing an ID
|
||||||
@ -97,7 +129,7 @@ def getTransaction():
|
|||||||
return jsonify({"transaction": transaction, "error": False, "message": ""})
|
return jsonify({"transaction": transaction, "error": False, "message": ""})
|
||||||
return jsonify({"transaction": transaction, "error": True, "message": f"method {request.method} is not allowed."})
|
return jsonify({"transaction": transaction, "error": True, "message": f"method {request.method} is not allowed."})
|
||||||
|
|
||||||
@items_api.route("/item/getItem", methods=["GET"])
|
@items_api.route("/getItem", methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
def get_item():
|
def get_item():
|
||||||
""" GET item from system by passing its ID
|
""" GET item from system by passing its ID
|
||||||
@ -183,7 +215,7 @@ def pagninate_items():
|
|||||||
return jsonify({'items': items, "end": math.ceil(count/limit), 'error':False, 'message': 'Items Loaded Successfully!'})
|
return jsonify({'items': items, "end": math.ceil(count/limit), 'error':False, 'message': 'Items Loaded Successfully!'})
|
||||||
return jsonify({'items': items, "end": math.ceil(count/limit), 'error':True, 'message': 'There was a problem loading the items!'})
|
return jsonify({'items': items, "end": math.ceil(count/limit), 'error':True, 'message': 'There was a problem loading the items!'})
|
||||||
|
|
||||||
@items_api.route('/item/getModalItems', methods=["GET"])
|
@items_api.route('/getModalItems', methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
def getModalItems():
|
def getModalItems():
|
||||||
""" GET items from the system by passing a page, limit, search_string. For select modals
|
""" GET items from the system by passing a page, limit, search_string. For select modals
|
||||||
@ -223,7 +255,7 @@ def getModalItems():
|
|||||||
return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"})
|
return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"})
|
||||||
return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":True, "message": f"method {request.method} is not allowed."})
|
return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":True, "message": f"method {request.method} is not allowed."})
|
||||||
|
|
||||||
@items_api.route('/item/getPrefixes', methods=["GET"])
|
@items_api.route('/getPrefixes', methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
def getModalPrefixes():
|
def getModalPrefixes():
|
||||||
""" GET prefixes from the system by passing page and limit.
|
""" GET prefixes from the system by passing page and limit.
|
||||||
@ -259,7 +291,7 @@ def getModalPrefixes():
|
|||||||
return jsonify({"prefixes":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"})
|
return jsonify({"prefixes":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"})
|
||||||
return jsonify({"prefixes":recordset, "end":math.ceil(count/limit), "error":True, "message":f"method {request.method} is not allowed!"})
|
return jsonify({"prefixes":recordset, "end":math.ceil(count/limit), "error":True, "message":f"method {request.method} is not allowed!"})
|
||||||
|
|
||||||
@items_api.route('/item/getZonesBySku', methods=["GET"])
|
@items_api.route('/getZonesBySku', methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
def getZonesbySku():
|
def getZonesbySku():
|
||||||
""" GET zones by sku by passing page, limit, item_id
|
""" GET zones by sku by passing page, limit, item_id
|
||||||
@ -301,7 +333,7 @@ def getZonesbySku():
|
|||||||
return jsonify({'zones': zones, 'endpage': math.ceil(count/limit), 'error':False, 'message': f''})
|
return jsonify({'zones': zones, 'endpage': math.ceil(count/limit), 'error':False, 'message': f''})
|
||||||
return jsonify({'zones': zones, 'endpage': math.ceil(count/limit), 'error':False, 'message': f'method {request.method} not allowed.'})
|
return jsonify({'zones': zones, 'endpage': math.ceil(count/limit), 'error':False, 'message': f'method {request.method} not allowed.'})
|
||||||
|
|
||||||
@items_api.route('/item/getLocationsBySkuZone', methods=['GET'])
|
@items_api.route('/getLocationsBySkuZone', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def getLocationsBySkuZone():
|
def getLocationsBySkuZone():
|
||||||
""" GET locations by sku by passing page, limit, item_id, zone_id
|
""" GET locations by sku by passing page, limit, item_id, zone_id
|
||||||
@ -351,7 +383,7 @@ def getLocationsBySkuZone():
|
|||||||
return jsonify({'locations': locations, 'endpage': math.ceil(count/limit), 'error': False, 'message': f''})
|
return jsonify({'locations': locations, 'endpage': math.ceil(count/limit), 'error': False, 'message': f''})
|
||||||
return jsonify({'locations': locations, 'endpage': math.ceil(count/limit), 'error': True, 'message': f'method {request.method} is not allowed.'})
|
return jsonify({'locations': locations, 'endpage': math.ceil(count/limit), 'error': True, 'message': f'method {request.method} is not allowed.'})
|
||||||
|
|
||||||
@items_api.route('/item/getBrands', methods=['GET'])
|
@items_api.route('/getBrands', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def getBrands():
|
def getBrands():
|
||||||
""" GET brands from the system by passing page, limit
|
""" GET brands from the system by passing page, limit
|
||||||
@ -386,7 +418,7 @@ def getBrands():
|
|||||||
return jsonify({'brands': brands, 'endpage': math.ceil(count/limit), 'error': True, 'message': f'method {request.method} is not allowed.'})
|
return jsonify({'brands': brands, 'endpage': math.ceil(count/limit), 'error': True, 'message': f'method {request.method} is not allowed.'})
|
||||||
|
|
||||||
|
|
||||||
@items_api.route('/item/updateItem', methods=['POST'])
|
@items_api.route('/updateItem', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def updateItem():
|
def updateItem():
|
||||||
""" POST update to item in the system by passing item_id, data
|
""" POST update to item in the system by passing item_id, data
|
||||||
@ -414,7 +446,7 @@ def updateItem():
|
|||||||
return jsonify({'error': False, 'message': f'Item was updated successfully!'})
|
return jsonify({'error': False, 'message': f'Item was updated successfully!'})
|
||||||
return jsonify({'error': True, 'message': f'method {request.method} is not allowed!'})
|
return jsonify({'error': True, 'message': f'method {request.method} is not allowed!'})
|
||||||
|
|
||||||
@items_api.route('/item/updateItemLink', methods=['POST'])
|
@items_api.route('/updateItemLink', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def updateItemLink():
|
def updateItemLink():
|
||||||
""" UPDATE item link by passing id, conv_factor, barcode, old_conv
|
""" UPDATE item link by passing id, conv_factor, barcode, old_conv
|
||||||
@ -462,7 +494,7 @@ def updateItemLink():
|
|||||||
return jsonify({'error': True, 'message': f"method {request.method} not allowed."})
|
return jsonify({'error': True, 'message': f"method {request.method} not allowed."})
|
||||||
|
|
||||||
|
|
||||||
@items_api.route('/item/getPossibleLocations', methods=["GET"])
|
@items_api.route('/getPossibleLocations', methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
def getPossibleLocations():
|
def getPossibleLocations():
|
||||||
""" GET locations with zones by passing a page and limit
|
""" GET locations with zones by passing a page and limit
|
||||||
@ -496,7 +528,7 @@ def getPossibleLocations():
|
|||||||
return jsonify({'locations': locations, 'end':math.ceil(count/limit), 'error':False, 'message': f'Locations received successfully!'})
|
return jsonify({'locations': locations, 'end':math.ceil(count/limit), 'error':False, 'message': f'Locations received successfully!'})
|
||||||
return jsonify({'locations': locations, 'end':math.ceil(count/limit), 'error':True, 'message': f'method {request.method} not allowed.'})
|
return jsonify({'locations': locations, 'end':math.ceil(count/limit), 'error':True, 'message': f'method {request.method} not allowed.'})
|
||||||
|
|
||||||
@items_api.route('/item/getLinkedItem', methods=["GET"])
|
@items_api.route('/getLinkedItem', methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
def getLinkedItem():
|
def getLinkedItem():
|
||||||
""" GET itemlink from system by passing an ID
|
""" GET itemlink from system by passing an ID
|
||||||
@ -521,7 +553,7 @@ def getLinkedItem():
|
|||||||
return jsonify({'linked_item': linked_item, 'error': False, 'message': 'Linked Item added!!'})
|
return jsonify({'linked_item': linked_item, 'error': False, 'message': 'Linked Item added!!'})
|
||||||
return jsonify({'linked_item': linked_item, 'error': True, 'message': f'method {request.method} not allowed'})
|
return jsonify({'linked_item': linked_item, 'error': True, 'message': f'method {request.method} not allowed'})
|
||||||
|
|
||||||
@items_api.route('/item/addLinkedItem', methods=["POST"])
|
@items_api.route('/addLinkedItem', methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def addLinkedItem():
|
def addLinkedItem():
|
||||||
""" POST a link between items by passing a parent_id, a child_id, conv_factor
|
""" POST a link between items by passing a parent_id, a child_id, conv_factor
|
||||||
@ -569,7 +601,7 @@ def addLinkedItem():
|
|||||||
return jsonify({'error': False, 'message': 'Linked Item added!!'})
|
return jsonify({'error': False, 'message': 'Linked Item added!!'})
|
||||||
return jsonify({'error': True, 'message': 'These was an error with adding to the linked list!'})
|
return jsonify({'error': True, 'message': 'These was an error with adding to the linked list!'})
|
||||||
|
|
||||||
@items_api.route('/items/addBlankItem', methods=["POST"])
|
@items_api.route('/addBlankItem', methods=["POST"])
|
||||||
def addBlankItem():
|
def addBlankItem():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = {
|
data = {
|
||||||
@ -577,20 +609,16 @@ def addBlankItem():
|
|||||||
'name': request.get_json()['name'],
|
'name': request.get_json()['name'],
|
||||||
'subtype': request.get_json()['subtype']
|
'subtype': request.get_json()['subtype']
|
||||||
}
|
}
|
||||||
pprint.pprint(data)
|
|
||||||
database_config = config()
|
database_config = config()
|
||||||
site_name = session['selected_site']
|
site_name = session['selected_site']
|
||||||
user_id = session['user_id']
|
user_id = session['user_id']
|
||||||
try:
|
|
||||||
with psycopg2.connect(**database_config) as conn:
|
items_processes.postNewBlankItem(site_name, user_id, data)
|
||||||
process.postNewBlankItem(conn, site_name, user_id, data)
|
|
||||||
except Exception as error:
|
|
||||||
conn.rollback()
|
|
||||||
return jsonify({'error': True, 'message': error})
|
|
||||||
return jsonify({'error': False, 'message': 'Item added!!'})
|
return jsonify({'error': False, 'message': 'Item added!!'})
|
||||||
return jsonify({'error': True, 'message': 'These was an error with adding Item!'})
|
return jsonify({'error': True, 'message': 'These was an error with adding Item!'})
|
||||||
|
|
||||||
@items_api.route('/items/addSKUPrefix', methods=["POST"])
|
@items_api.route('/addSKUPrefix', methods=["POST"])
|
||||||
def addSKUPrefix():
|
def addSKUPrefix():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
database_config = config()
|
database_config = config()
|
||||||
@ -609,7 +637,7 @@ def addSKUPrefix():
|
|||||||
return jsonify({'error': False, 'message': 'Prefix added!!'})
|
return jsonify({'error': False, 'message': 'Prefix added!!'})
|
||||||
return jsonify({'error': True, 'message': 'These was an error with adding this Prefix!'})
|
return jsonify({'error': True, 'message': 'These was an error with adding this Prefix!'})
|
||||||
|
|
||||||
@items_api.route('/item/addConversion', methods=['POST'])
|
@items_api.route('/addConversion', methods=['POST'])
|
||||||
def addConversion():
|
def addConversion():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
item_id = request.get_json()['parent_id']
|
item_id = request.get_json()['parent_id']
|
||||||
@ -627,7 +655,7 @@ def addConversion():
|
|||||||
return jsonify(error=False, message="Conversion was added successfully")
|
return jsonify(error=False, message="Conversion was added successfully")
|
||||||
return jsonify(error=True, message="Unable to save this conversion, ERROR!")
|
return jsonify(error=True, message="Unable to save this conversion, ERROR!")
|
||||||
|
|
||||||
@items_api.route('/item/deleteConversion', methods=['POST'])
|
@items_api.route('/deleteConversion', methods=['POST'])
|
||||||
def deleteConversion():
|
def deleteConversion():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
conversion_id = request.get_json()['conversion_id']
|
conversion_id = request.get_json()['conversion_id']
|
||||||
@ -640,7 +668,7 @@ def deleteConversion():
|
|||||||
return jsonify(error=False, message="Conversion was deleted successfully")
|
return jsonify(error=False, message="Conversion was deleted successfully")
|
||||||
return jsonify(error=True, message="Unable to delete this conversion, ERROR!")
|
return jsonify(error=True, message="Unable to delete this conversion, ERROR!")
|
||||||
|
|
||||||
@items_api.route('/item/updateConversion', methods=['POST'])
|
@items_api.route('/updateConversion', methods=['POST'])
|
||||||
def updateConversion():
|
def updateConversion():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
conversion_id = request.get_json()['conversion_id']
|
conversion_id = request.get_json()['conversion_id']
|
||||||
@ -653,7 +681,7 @@ def updateConversion():
|
|||||||
return jsonify(error=False, message="Conversion was updated successfully")
|
return jsonify(error=False, message="Conversion was updated successfully")
|
||||||
return jsonify(error=True, message="Unable to save this conversion, ERROR!")
|
return jsonify(error=True, message="Unable to save this conversion, ERROR!")
|
||||||
|
|
||||||
@items_api.route('/item/addPrefix', methods=['POST'])
|
@items_api.route('/addPrefix', methods=['POST'])
|
||||||
def addPrefix():
|
def addPrefix():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
item_info_id = request.get_json()['parent_id']
|
item_info_id = request.get_json()['parent_id']
|
||||||
@ -670,7 +698,7 @@ def addPrefix():
|
|||||||
return jsonify(error=False, message="Prefix was added successfully")
|
return jsonify(error=False, message="Prefix was added successfully")
|
||||||
return jsonify(error=True, message="Unable to save this prefix, ERROR!")
|
return jsonify(error=True, message="Unable to save this prefix, ERROR!")
|
||||||
|
|
||||||
@items_api.route('/item/deletePrefix', methods=['POST'])
|
@items_api.route('/deletePrefix', methods=['POST'])
|
||||||
def deletePrefix():
|
def deletePrefix():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
item_info_id = request.get_json()['item_info_id']
|
item_info_id = request.get_json()['item_info_id']
|
||||||
@ -685,7 +713,7 @@ def deletePrefix():
|
|||||||
return jsonify(error=False, message="Prefix was deleted successfully")
|
return jsonify(error=False, message="Prefix was deleted successfully")
|
||||||
return jsonify(error=True, message="Unable to delete this prefix, ERROR!")
|
return jsonify(error=True, message="Unable to delete this prefix, ERROR!")
|
||||||
|
|
||||||
@items_api.route('/item/refreshSearchString', methods=['POST'])
|
@items_api.route('/refreshSearchString', methods=['POST'])
|
||||||
def refreshSearchString():
|
def refreshSearchString():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
item_id = request.get_json()['item_id']
|
item_id = request.get_json()['item_id']
|
||||||
@ -706,7 +734,7 @@ def refreshSearchString():
|
|||||||
return jsonify(error=False, message="Search String was updated successfully")
|
return jsonify(error=False, message="Search String was updated successfully")
|
||||||
return jsonify(error=True, message="Unable to update this search string, ERROR!")
|
return jsonify(error=True, message="Unable to update this search string, ERROR!")
|
||||||
|
|
||||||
@items_api.route('/item/postNewItemLocation', methods=['POST'])
|
@items_api.route('/postNewItemLocation', methods=['POST'])
|
||||||
def postNewItemLocation():
|
def postNewItemLocation():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
item_id = request.get_json()['item_id']
|
item_id = request.get_json()['item_id']
|
||||||
|
|||||||
@ -1,9 +1,102 @@
|
|||||||
from application.items import database_items
|
from application.items import database_items
|
||||||
import application.postsqldb as db
|
import application.postsqldb as db
|
||||||
|
import application.database_payloads as dbPayloads
|
||||||
import config
|
import config
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import psycopg2
|
import psycopg2
|
||||||
|
import json
|
||||||
|
|
||||||
|
def postNewBlankItem(site_name: str, user_id: int, data: dict, conn=None):
|
||||||
|
""" data = {'barcode', 'name', 'subtype'}"""
|
||||||
|
self_conn = False
|
||||||
|
if not conn:
|
||||||
|
database_config = config.config()
|
||||||
|
conn = psycopg2.connect(**database_config)
|
||||||
|
conn.autocommit = False
|
||||||
|
self_conn = True
|
||||||
|
|
||||||
|
site = database_items.selectSiteTuple((site_name,))
|
||||||
|
default_zone = database_items.getZone(site_name,(site['default_zone'], ))
|
||||||
|
default_location = database_items.getLocation(site_name, (site['default_primary_location'],))
|
||||||
|
uuid = f"{default_zone['name']}@{default_location['name']}"
|
||||||
|
|
||||||
|
# create logistics info
|
||||||
|
logistics_info = dbPayloads.LogisticsInfoPayload(
|
||||||
|
barcode=data['barcode'],
|
||||||
|
primary_location=site['default_primary_location'],
|
||||||
|
primary_zone=site['default_zone'],
|
||||||
|
auto_issue_location=site['default_auto_issue_location'],
|
||||||
|
auto_issue_zone=site['default_zone']
|
||||||
|
)
|
||||||
|
|
||||||
|
# create item info
|
||||||
|
item_info = dbPayloads.ItemInfoPayload(data['barcode'])
|
||||||
|
|
||||||
|
# create Food Info
|
||||||
|
food_info = dbPayloads.FoodInfoPayload()
|
||||||
|
|
||||||
|
logistics_info_id = 0
|
||||||
|
item_info_id = 0
|
||||||
|
food_info_id = 0
|
||||||
|
brand_id = 1
|
||||||
|
|
||||||
|
|
||||||
|
logistics_info = database_items.insertLogisticsInfoTuple(conn, site_name, logistics_info.payload(), convert=True)
|
||||||
|
item_info = database_items.insertItemInfoTuple(conn, site_name, item_info.payload(), convert=True)
|
||||||
|
food_info = database_items.insertFoodInfoTuple(conn, site_name, food_info.payload(), convert=True)
|
||||||
|
|
||||||
|
name = data['name']
|
||||||
|
name = name.replace("'", "@&apostraphe&")
|
||||||
|
description = ""
|
||||||
|
tags = db.lst2pgarr([])
|
||||||
|
links = json.dumps({})
|
||||||
|
search_string = f"&&{data['barcode']}&&{name}&&"
|
||||||
|
|
||||||
|
|
||||||
|
item = dbPayloads.ItemsPayload(
|
||||||
|
data['barcode'],
|
||||||
|
data['name'],
|
||||||
|
item_info['id'],
|
||||||
|
logistics_info['id'],
|
||||||
|
food_info['id'],
|
||||||
|
brand=brand_id,
|
||||||
|
row_type="single",
|
||||||
|
item_type=data['subtype'],
|
||||||
|
search_string=search_string
|
||||||
|
)
|
||||||
|
|
||||||
|
item = database_items.insertItemTuple(conn, site_name, item.payload(), convert=True)
|
||||||
|
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(f"SELECT id FROM {site_name}_locations WHERE uuid=%s;", (uuid, ))
|
||||||
|
location_id = cur.fetchone()[0]
|
||||||
|
|
||||||
|
dbPayloads.ItemLocationPayload
|
||||||
|
item_location = dbPayloads.ItemLocationPayload(item['id'], location_id)
|
||||||
|
database_items.insertItemLocationsTuple(conn, site_name, item_location.payload())
|
||||||
|
|
||||||
|
|
||||||
|
creation_tuple = dbPayloads.TransactionPayload(
|
||||||
|
datetime.datetime.now(),
|
||||||
|
logistics_info['id'],
|
||||||
|
item['barcode'],
|
||||||
|
item['item_name'],
|
||||||
|
"SYSTEM",
|
||||||
|
0.0,
|
||||||
|
"Item added to the System!",
|
||||||
|
user_id,
|
||||||
|
{'location': uuid}
|
||||||
|
)
|
||||||
|
|
||||||
|
database_items.postAddTransaction(site_name, creation_tuple.payload(), conn=conn)
|
||||||
|
|
||||||
|
if self_conn:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return False
|
||||||
|
|
||||||
|
return conn
|
||||||
|
|
||||||
def postLinkedItem(site, payload):
|
def postLinkedItem(site, payload):
|
||||||
"""
|
"""
|
||||||
|
|||||||
4
application/items/sql/insertFoodInfoTuple.sql
Normal file
4
application/items/sql/insertFoodInfoTuple.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO %%site_name%%_food_info
|
||||||
|
(ingrediants, food_groups, nutrients, expires, default_expiration)
|
||||||
|
VALUES (%s, %s, %s, %s, %s)
|
||||||
|
RETURNING *;
|
||||||
4
application/items/sql/insertItemInfoTuple.sql
Normal file
4
application/items/sql/insertItemInfoTuple.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO %%site_name%%_item_info
|
||||||
|
(barcode, packaging, uom_quantity, uom, cost, safety_stock, lead_time_days, ai_pick, prefixes)
|
||||||
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
|
RETURNING *;
|
||||||
4
application/items/sql/insertItemLocationsTuple copy.sql
Normal file
4
application/items/sql/insertItemLocationsTuple copy.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO %%site_name%%_item_locations
|
||||||
|
(part_id, location_id, quantity_on_hand, cost_layers)
|
||||||
|
VALUES (%s, %s, %s, %s)
|
||||||
|
RETURNING *;
|
||||||
5
application/items/sql/insertItemTuple.sql
Normal file
5
application/items/sql/insertItemTuple.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
INSERT INTO %%site_name%%_items
|
||||||
|
(barcode, item_name, brand, description, tags, links, item_info_id, logistics_info_id,
|
||||||
|
food_info_id, row_type, item_type, search_string)
|
||||||
|
VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
|
RETURNING *;
|
||||||
4
application/items/sql/insertLogisticsInfoTuple.sql
Normal file
4
application/items/sql/insertLogisticsInfoTuple.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO %%site_name%%_logistics_info
|
||||||
|
(barcode, primary_location, primary_zone, auto_issue_location, auto_issue_zone)
|
||||||
|
VALUES (%s, %s, %s, %s, %s)
|
||||||
|
RETURNING *;
|
||||||
@ -214,12 +214,12 @@ async function updateTableElements(){
|
|||||||
let viewOp = document.createElement('a')
|
let viewOp = document.createElement('a')
|
||||||
viewOp.innerHTML = `edit <span uk-icon="icon: pencil"></span>`
|
viewOp.innerHTML = `edit <span uk-icon="icon: pencil"></span>`
|
||||||
viewOp.setAttribute('class', 'uk-button uk-button-default uk-button-small')
|
viewOp.setAttribute('class', 'uk-button uk-button-default uk-button-small')
|
||||||
viewOp.href = `/item/${items[i].id}`
|
viewOp.href = `/items/${items[i].id}`
|
||||||
|
|
||||||
let historyOp = document.createElement('a')
|
let historyOp = document.createElement('a')
|
||||||
historyOp.innerHTML = `history <span uk-icon="icon: history"></span>`
|
historyOp.innerHTML = `history <span uk-icon="icon: history"></span>`
|
||||||
historyOp.setAttribute('class', 'uk-button uk-button-default uk-button-small')
|
historyOp.setAttribute('class', 'uk-button uk-button-default uk-button-small')
|
||||||
historyOp.href = `/transactions/${items[i].id}`
|
historyOp.href = `/items/transactions/${items[i].id}`
|
||||||
|
|
||||||
buttonGroup.append(viewOp, historyOp)
|
buttonGroup.append(viewOp, historyOp)
|
||||||
opsCell.append(buttonGroup)
|
opsCell.append(buttonGroup)
|
||||||
@ -263,8 +263,8 @@ async function updateListElements(){
|
|||||||
|
|
||||||
let footer = document.createElement('div')
|
let footer = document.createElement('div')
|
||||||
footer.classList.add('uk-card-footer')
|
footer.classList.add('uk-card-footer')
|
||||||
footer.innerHTML = `<a style="margin-right: 5px; border-radius: 10px;" class="uk-button uk-button-default uk-button-small" uk-icon="icon: pencil" href="/item/${items[i].id}">edit</a>
|
footer.innerHTML = `<a style="margin-right: 5px; border-radius: 10px;" class="uk-button uk-button-default uk-button-small" uk-icon="icon: pencil" href="/items/${items[i].id}">edit</a>
|
||||||
<a style="border-radius: 10px;" class="uk-button uk-button-default uk-button-small" uk-icon="icon: history" href="/transactions/${items[i].id}">History</a>`
|
<a style="border-radius: 10px;" class="uk-button uk-button-default uk-button-small" uk-icon="icon: history" href="/items/transactions/${items[i].id}">History</a>`
|
||||||
|
|
||||||
listItem.append(header)
|
listItem.append(header)
|
||||||
if(!items[i].description == ""){
|
if(!items[i].description == ""){
|
||||||
|
|||||||
@ -581,7 +581,7 @@ async function updateLinkedItemsTable() {
|
|||||||
let editOp = document.createElement('a')
|
let editOp = document.createElement('a')
|
||||||
editOp.setAttribute('class', 'uk-button uk-button-default')
|
editOp.setAttribute('class', 'uk-button uk-button-default')
|
||||||
editOp.setAttribute('uk-icon', 'icon: pencil')
|
editOp.setAttribute('uk-icon', 'icon: pencil')
|
||||||
editOp.setAttribute('href', `/item/${item['id']}/itemLink/${linked_items[i].id}`)
|
editOp.setAttribute('href', `/items/${item['id']}/itemLink/${linked_items[i].id}`)
|
||||||
|
|
||||||
opCell.append(editOp)
|
opCell.append(editOp)
|
||||||
|
|
||||||
@ -755,7 +755,7 @@ async function openEditConversionsModal(conversion) {
|
|||||||
|
|
||||||
|
|
||||||
async function postConversion() {
|
async function postConversion() {
|
||||||
const response = await fetch(`/item/addConversion`, {
|
const response = await fetch(`/items/addConversion`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -786,7 +786,7 @@ async function postConversion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function postConversionUpdate(id, update) {
|
async function postConversionUpdate(id, update) {
|
||||||
const response = await fetch(`/item/updateConversion`, {
|
const response = await fetch(`/items/updateConversion`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -816,7 +816,7 @@ async function postConversionUpdate(id, update) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function deleteConversion(conversion_id) {
|
async function deleteConversion(conversion_id) {
|
||||||
const response = await fetch(`/item/deleteConversion`, {
|
const response = await fetch(`/items/deleteConversion`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -858,7 +858,7 @@ async function openAddPrefixesModal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function postPrefix(id) {
|
async function postPrefix(id) {
|
||||||
const response = await fetch(`/item/addPrefix`, {
|
const response = await fetch(`/items/addPrefix`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -887,7 +887,7 @@ async function postPrefix(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function deletePrefix(prefix_id) {
|
async function deletePrefix(prefix_id) {
|
||||||
const response = await fetch(`/item/deletePrefix`, {
|
const response = await fetch(`/items/deletePrefix`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -920,7 +920,7 @@ async function deletePrefix(prefix_id) {
|
|||||||
|
|
||||||
let prefix_limit = 2;
|
let prefix_limit = 2;
|
||||||
async function fetchPrefixes() {
|
async function fetchPrefixes() {
|
||||||
const url = new URL('/item/getPrefixes', window.location.origin);
|
const url = new URL('/items/getPrefixes', window.location.origin);
|
||||||
url.searchParams.append('page', current_page);
|
url.searchParams.append('page', current_page);
|
||||||
url.searchParams.append('limit', prefix_limit);
|
url.searchParams.append('limit', prefix_limit);
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
@ -930,7 +930,7 @@ async function fetchPrefixes() {
|
|||||||
|
|
||||||
let brands_limit = 25;
|
let brands_limit = 25;
|
||||||
async function fetchBrands() {
|
async function fetchBrands() {
|
||||||
const url = new URL('/item/getBrands', window.location.origin);
|
const url = new URL('/items/getBrands', window.location.origin);
|
||||||
url.searchParams.append('page', current_page);
|
url.searchParams.append('page', current_page);
|
||||||
url.searchParams.append('limit', brands_limit);
|
url.searchParams.append('limit', brands_limit);
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
@ -940,7 +940,7 @@ async function fetchBrands() {
|
|||||||
|
|
||||||
let items_limit = 25;
|
let items_limit = 25;
|
||||||
async function fetchItems() {
|
async function fetchItems() {
|
||||||
const url = new URL('/item/getModalItems', window.location.origin);
|
const url = new URL('/items/getModalItems', window.location.origin);
|
||||||
url.searchParams.append('page', current_page);
|
url.searchParams.append('page', current_page);
|
||||||
url.searchParams.append('limit', items_limit);
|
url.searchParams.append('limit', items_limit);
|
||||||
url.searchParams.append('search_string', search_string);
|
url.searchParams.append('search_string', search_string);
|
||||||
@ -951,7 +951,7 @@ async function fetchItems() {
|
|||||||
|
|
||||||
let zones_limit = 20;
|
let zones_limit = 20;
|
||||||
async function fetchZones(){
|
async function fetchZones(){
|
||||||
const url = new URL('/item/getZonesBySku', window.location.origin);
|
const url = new URL('/items/getZonesBySku', window.location.origin);
|
||||||
url.searchParams.append('page', current_page);
|
url.searchParams.append('page', current_page);
|
||||||
url.searchParams.append('limit', zones_limit);
|
url.searchParams.append('limit', zones_limit);
|
||||||
url.searchParams.append('item_id', item.id);
|
url.searchParams.append('item_id', item.id);
|
||||||
@ -962,7 +962,7 @@ async function fetchZones(){
|
|||||||
|
|
||||||
let locations_limit = 10;
|
let locations_limit = 10;
|
||||||
async function fetchLocations(logis) {
|
async function fetchLocations(logis) {
|
||||||
const url = new URL('/item/getLocationsBySkuZone', window.location.origin);
|
const url = new URL('/items/getLocationsBySkuZone', window.location.origin);
|
||||||
url.searchParams.append('page', current_page);
|
url.searchParams.append('page', current_page);
|
||||||
url.searchParams.append('limit', locations_limit);
|
url.searchParams.append('limit', locations_limit);
|
||||||
url.searchParams.append('part_id', item.id);
|
url.searchParams.append('part_id', item.id);
|
||||||
@ -977,7 +977,7 @@ async function fetchLocations(logis) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchItem() {
|
async function fetchItem() {
|
||||||
const url = new URL('/item/getItem', window.location.origin);
|
const url = new URL('/items/getItem', window.location.origin);
|
||||||
url.searchParams.append('id', item_id);
|
url.searchParams.append('id', item_id);
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
data = await response.json();
|
data = await response.json();
|
||||||
@ -1106,7 +1106,7 @@ async function addLinkedItem(parent_id, child_id) {
|
|||||||
|
|
||||||
if(Number.isInteger(conversion_factor)){
|
if(Number.isInteger(conversion_factor)){
|
||||||
document.getElementById('conversion_factor').classList.remove('uk-form-danger')
|
document.getElementById('conversion_factor').classList.remove('uk-form-danger')
|
||||||
const response = await fetch(`/item/addLinkedItem`, {
|
const response = await fetch(`/items/addLinkedItem`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -1145,7 +1145,7 @@ async function addLinkedItem(parent_id, child_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function saveUpdated() {
|
async function saveUpdated() {
|
||||||
const response = await fetch(`/item/updateItem`, {
|
const response = await fetch(`/items/updateItem`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -1175,7 +1175,7 @@ async function saveUpdated() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function refreshSearchString() {
|
async function refreshSearchString() {
|
||||||
const response = await fetch(`/item/refreshSearchString`, {
|
const response = await fetch(`/items/refreshSearchString`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -1370,7 +1370,7 @@ var new_locations_current_page = 1
|
|||||||
var new_locations_end_page = 1
|
var new_locations_end_page = 1
|
||||||
var new_locations_limit = 25
|
var new_locations_limit = 25
|
||||||
async function fetch_new_locations() {
|
async function fetch_new_locations() {
|
||||||
const url = new URL('/item/getPossibleLocations', window.location.origin);
|
const url = new URL('/items/getPossibleLocations', window.location.origin);
|
||||||
url.searchParams.append('page', new_locations_current_page);
|
url.searchParams.append('page', new_locations_current_page);
|
||||||
url.searchParams.append('limit', new_locations_limit);
|
url.searchParams.append('limit', new_locations_limit);
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
@ -1380,7 +1380,7 @@ async function fetch_new_locations() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function postNewItemLocation(location_id) {
|
async function postNewItemLocation(location_id) {
|
||||||
const response = await fetch(`/item/postNewItemLocation`, {
|
const response = await fetch(`/items/postNewItemLocation`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
|||||||
@ -105,7 +105,7 @@ async function getItem(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getTransaction(id) {
|
async function getTransaction(id) {
|
||||||
const url = new URL('/item/getTransaction', window.location.origin);
|
const url = new URL('/items/getTransaction', window.location.origin);
|
||||||
url.searchParams.append('id', id);
|
url.searchParams.append('id', id);
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
data = await response.json();
|
data = await response.json();
|
||||||
@ -114,7 +114,7 @@ async function getTransaction(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getTransactions(){
|
async function getTransactions(){
|
||||||
const url = new URL('/item/getTransactions', window.location.origin);
|
const url = new URL('/items/getTransactions', window.location.origin);
|
||||||
url.searchParams.append('page', pagination_current);
|
url.searchParams.append('page', pagination_current);
|
||||||
url.searchParams.append('limit', limit);
|
url.searchParams.append('limit', limit);
|
||||||
url.searchParams.append('logistics_info_id', item.logistics_info_id)
|
url.searchParams.append('logistics_info_id', item.logistics_info_id)
|
||||||
|
|||||||
@ -691,6 +691,6 @@
|
|||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
<script src="{{ url_for('static', filename='handlers/itemEditHandler.js') }}"></script>
|
<script src="{{ url_for('items_api.static', filename='itemEditHandler.js') }}"></script>
|
||||||
<script>const item_id = {{id|tojson}}</script>
|
<script>const item_id = {{id|tojson}}</script>
|
||||||
</html>
|
</html>
|
||||||
@ -115,6 +115,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script src="{{ url_for('static', filename='handlers/transactionsHandler.js') }}"></script>
|
<script src="{{ url_for('items_api.static', filename='transactionsHandler.js') }}"></script>
|
||||||
<script>const item_id = {{id|tojson}}</script>
|
<script>const item_id = {{id|tojson}}</script>
|
||||||
</html>
|
</html>
|
||||||
@ -2409,3 +2409,64 @@ class ItemLinkPayload:
|
|||||||
json.dumps(self.data),
|
json.dumps(self.data),
|
||||||
self.conv_factor
|
self.conv_factor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LogisticsInfoPayload:
|
||||||
|
barcode: str
|
||||||
|
primary_location: int
|
||||||
|
primary_zone: int
|
||||||
|
auto_issue_location: int
|
||||||
|
auto_issue_zone: int
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (self.barcode,
|
||||||
|
self.primary_location,
|
||||||
|
self.primary_zone,
|
||||||
|
self.auto_issue_location,
|
||||||
|
self.auto_issue_zone)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ItemInfoPayload:
|
||||||
|
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 __post_init__(self):
|
||||||
|
if not isinstance(self.barcode, str):
|
||||||
|
raise TypeError(f"barcode must be of type str; not {type(self.barcode)}")
|
||||||
|
|
||||||
|
def payload(self):
|
||||||
|
return (
|
||||||
|
self.barcode,
|
||||||
|
self.packaging,
|
||||||
|
self.uom_quantity,
|
||||||
|
self.uom,
|
||||||
|
self.cost,
|
||||||
|
self.safety_stock,
|
||||||
|
self.lead_time_days,
|
||||||
|
self.ai_pick,
|
||||||
|
lst2pgarr(self.prefixes)
|
||||||
|
)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FoodInfoPayload:
|
||||||
|
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(self):
|
||||||
|
return (
|
||||||
|
lst2pgarr(self.food_groups),
|
||||||
|
lst2pgarr(self.ingrediants),
|
||||||
|
json.dumps(self.nutrients),
|
||||||
|
self.expires,
|
||||||
|
self.default_expiration
|
||||||
|
)
|
||||||
19
webserver.py
19
webserver.py
@ -67,25 +67,6 @@ def inject_user():
|
|||||||
return dict(username="")
|
return dict(username="")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/transactions/<id>")
|
|
||||||
@login_required
|
|
||||||
def transactions(id):
|
|
||||||
"""This is the main endpoint to reach the webpage for an items transaction history
|
|
||||||
---
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
type: integer
|
|
||||||
required: true
|
|
||||||
default: all
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: Returns the transactions.html webpage for the item with passed ID
|
|
||||||
"""
|
|
||||||
sites = [site[1] for site in main.get_sites(session['user']['sites'])]
|
|
||||||
return render_template("items/transactions.html", id=id, current_site=session['selected_site'], sites=sites)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/push-subscriptions", methods=["POST"])
|
@app.route("/api/push-subscriptions", methods=["POST"])
|
||||||
def create_push_subscription():
|
def create_push_subscription():
|
||||||
json_data = request.get_json()
|
json_data = request.get_json()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user