Implemeted SKU creation in recipe module - edit
This commit is contained in:
parent
5bd6d0b552
commit
78d79f9a57
Binary file not shown.
@ -5,5 +5,6 @@ CREATE TABLE IF NOT EXISTS %%site_name%%_food_info (
|
|||||||
ingrediants TEXT [],
|
ingrediants TEXT [],
|
||||||
nutrients JSONB,
|
nutrients JSONB,
|
||||||
expires BOOLEAN,
|
expires BOOLEAN,
|
||||||
default_expiration FLOAT8
|
default_expiration FLOAT8,
|
||||||
|
UNIQUE(food_info_uuid)
|
||||||
);
|
);
|
||||||
@ -9,6 +9,6 @@ CREATE TABLE IF NOt EXISTS %%site_name%%_item_info (
|
|||||||
safety_stock FLOAT8,
|
safety_stock FLOAT8,
|
||||||
lead_time_days FLOAT8,
|
lead_time_days FLOAT8,
|
||||||
ai_pick BOOLEAN,
|
ai_pick BOOLEAN,
|
||||||
prefixes INTEGER [],
|
prefixes INTEGER []
|
||||||
UNIQUE(barcode)
|
UNIQUE(item_info_uuid)
|
||||||
);
|
);
|
||||||
@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS %%site_name%%_logistics_info(
|
|||||||
primary_zone INTEGER NOT NULL,
|
primary_zone INTEGER NOT NULL,
|
||||||
auto_issue_location INTEGER NOT NULL,
|
auto_issue_location INTEGER NOT NULL,
|
||||||
auto_issue_zone INTEGER NOT NULL,
|
auto_issue_zone INTEGER NOT NULL,
|
||||||
UNIQUE(barcode),
|
UNIQUE(logistics_info_uuid),
|
||||||
CONSTRAINT fk_primary_location
|
CONSTRAINT fk_primary_location
|
||||||
FOREIGN KEY(primary_location)
|
FOREIGN KEY(primary_location)
|
||||||
REFERENCES %%site_name%%_locations(id),
|
REFERENCES %%site_name%%_locations(id),
|
||||||
|
|||||||
@ -2,7 +2,7 @@ CREATE TABLE IF NOT EXISTS %%site_name%%_Transactions (
|
|||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
timestamp TIMESTAMP,
|
timestamp TIMESTAMP,
|
||||||
logistics_info_id INTEGER NOT NULL,
|
logistics_info_id INTEGER NOT NULL,
|
||||||
barcode VARCHAR(255) NOT NULL,
|
barcode VARCHAR(255),
|
||||||
name VARCHAR(255),
|
name VARCHAR(255),
|
||||||
transaction_type VARCHAR(255) NOT NULL,
|
transaction_type VARCHAR(255) NOT NULL,
|
||||||
quantity FLOAT8 NOT NULL,
|
quantity FLOAT8 NOT NULL,
|
||||||
|
|||||||
@ -46,10 +46,6 @@ class ItemInfoPayload:
|
|||||||
ai_pick: bool = False
|
ai_pick: bool = False
|
||||||
prefixes: list = field(default_factory=list)
|
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):
|
def payload(self):
|
||||||
return (
|
return (
|
||||||
self.barcode,
|
self.barcode,
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -126,6 +126,59 @@ def getPicturePath(site:str, payload:tuple):
|
|||||||
rows = cur.fetchone()[0]
|
rows = cur.fetchone()[0]
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
def selectSiteTuple(payload, convert=True):
|
||||||
|
""" payload (tuple): (site_name,) """
|
||||||
|
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 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 getLocation(site:str, payload:tuple, convert:bool=True):
|
||||||
|
selected = ()
|
||||||
|
database_config = config.config()
|
||||||
|
sql = f"SELECT * FROM {site}_locations WHERE id=%s;"
|
||||||
|
try:
|
||||||
|
with psycopg2.connect(**database_config) as conn:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql, payload)
|
||||||
|
rows = cur.fetchone()
|
||||||
|
if rows and convert:
|
||||||
|
selected = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
selected = rows
|
||||||
|
return selected
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
|
||||||
def selectItemLocationsTuple(site_name, payload, convert=True, conn=None):
|
def selectItemLocationsTuple(site_name, payload, convert=True, conn=None):
|
||||||
item_locations = ()
|
item_locations = ()
|
||||||
self_conn = False
|
self_conn = False
|
||||||
@ -312,6 +365,158 @@ def insertTransactionsTuple(site, payload, convert=True, conn=None):
|
|||||||
raise postsqldb.DatabaseError(error, payload, sql)
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
return transaction
|
return transaction
|
||||||
|
|
||||||
|
def insertLogisticsInfoTuple(site, payload, convert=True, conn=None):
|
||||||
|
""" payload (tuple): (barcode[str], primary_location[str], auto_issue_location[str], dynamic_locations[jsonb],
|
||||||
|
location_data[jsonb], quantity_on_hand[float]) """
|
||||||
|
logistics_info = ()
|
||||||
|
self_conn = False
|
||||||
|
|
||||||
|
with open(f"application/recipes/sql/insertLogisticsInfoTuple.sql", "r+") as file:
|
||||||
|
sql = file.read().replace("%%site_name%%", site)
|
||||||
|
try:
|
||||||
|
if not conn:
|
||||||
|
database_config = config.config()
|
||||||
|
conn = psycopg2.connect(**database_config)
|
||||||
|
conn.autocommit = True
|
||||||
|
self_conn = True
|
||||||
|
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql, payload)
|
||||||
|
rows = cur.fetchone()
|
||||||
|
if rows and convert:
|
||||||
|
logistics_info = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
logistics_info = rows
|
||||||
|
|
||||||
|
if self_conn:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return logistics_info
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
|
||||||
|
def insertItemInfoTuple(site, payload, convert=True, conn=None):
|
||||||
|
""" 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]) """
|
||||||
|
item_info = ()
|
||||||
|
self_conn = False
|
||||||
|
with open(f"application/recipes/sql/insertItemInfoTuple.sql", "r+") as file:
|
||||||
|
sql = file.read().replace("%%site_name%%", site)
|
||||||
|
try:
|
||||||
|
if not conn:
|
||||||
|
database_config = config.config()
|
||||||
|
conn = psycopg2.connect(**database_config)
|
||||||
|
conn.autocommit = True
|
||||||
|
self_conn = True
|
||||||
|
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql, payload)
|
||||||
|
rows = cur.fetchone()
|
||||||
|
if rows and convert:
|
||||||
|
item_info = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
item_info = rows
|
||||||
|
if self_conn:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return item_info
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
|
||||||
|
def insertFoodInfoTuple(site, payload, convert=True, conn=None):
|
||||||
|
""" payload (_type_): (ingrediants[lst2pgarr], food_groups[lst2pgarr], nutrients[jsonstr], expires[bool]) """
|
||||||
|
food_info = ()
|
||||||
|
self_conn = False
|
||||||
|
with open(f"application/recipes/sql/insertFoodInfoTuple.sql", "r+") as file:
|
||||||
|
sql = file.read().replace("%%site_name%%", site)
|
||||||
|
try:
|
||||||
|
if not conn:
|
||||||
|
database_config = config.config()
|
||||||
|
conn = psycopg2.connect(**database_config)
|
||||||
|
conn.autocommit = True
|
||||||
|
self_conn = True
|
||||||
|
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql, payload)
|
||||||
|
rows = cur.fetchone()
|
||||||
|
if rows and convert:
|
||||||
|
food_info = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
food_info = rows
|
||||||
|
|
||||||
|
if self_conn:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return food_info
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
|
||||||
|
def insertItemTuple(site, payload, convert=True, conn=None):
|
||||||
|
""" 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]) """
|
||||||
|
item = ()
|
||||||
|
self_conn = False
|
||||||
|
with open(f"application/recipes/sql/insertItemTuple.sql", "r+") as file:
|
||||||
|
sql = file.read().replace("%%site_name%%", site)
|
||||||
|
try:
|
||||||
|
if not conn:
|
||||||
|
database_config = config.config()
|
||||||
|
conn = psycopg2.connect(**database_config)
|
||||||
|
conn.autocommit = True
|
||||||
|
self_conn = True
|
||||||
|
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql, payload)
|
||||||
|
rows = cur.fetchone()
|
||||||
|
if rows and convert:
|
||||||
|
item = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
item = rows
|
||||||
|
|
||||||
|
if self_conn:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return item
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
|
||||||
|
|
||||||
|
def insertItemLocationsTuple(site, payload, convert=True, conn=None):
|
||||||
|
""" payload (tuple): (part_id[int], location_id[int], quantity_on_hand[float], cost_layers[lst2pgarr]) """
|
||||||
|
location = ()
|
||||||
|
self_conn = False
|
||||||
|
database_config = config.config()
|
||||||
|
with open(f"application/recipes/sql/insertItemLocationsTuple.sql", "r+") as file:
|
||||||
|
sql = file.read().replace("%%site_name%%", site)
|
||||||
|
try:
|
||||||
|
if not conn:
|
||||||
|
database_config = config.config()
|
||||||
|
conn = psycopg2.connect(**database_config)
|
||||||
|
conn.autocommit = True
|
||||||
|
self_conn = True
|
||||||
|
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql, payload)
|
||||||
|
rows = cur.fetchone()
|
||||||
|
if rows and convert:
|
||||||
|
location = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||||
|
elif rows and not convert:
|
||||||
|
location = rows
|
||||||
|
|
||||||
|
if self_conn:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return location
|
||||||
|
except Exception as error:
|
||||||
|
raise postsqldb.DatabaseError(error, payload, sql)
|
||||||
|
|
||||||
def postAddRecipe(site:str, payload:tuple, convert:bool=True):
|
def postAddRecipe(site:str, payload:tuple, convert:bool=True):
|
||||||
database_config = config.config()
|
database_config = config.config()
|
||||||
record = ()
|
record = ()
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import psycopg2
|
import psycopg2
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
|
|
||||||
from application import database_payloads, postsqldb
|
from application import database_payloads, postsqldb
|
||||||
from application.recipes import database_recipes
|
from application.recipes import database_recipes
|
||||||
|
from application.items import database_items
|
||||||
import config
|
import config
|
||||||
|
|
||||||
def postTransaction(site_name, user_id, data: dict, conn=None):
|
def postTransaction(site_name, user_id, data: dict, conn=None):
|
||||||
@ -137,3 +139,95 @@ def process_recipe_receipt(site_name, user_id, data:dict, conn=None):
|
|||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
return True, ""
|
return True, ""
|
||||||
|
|
||||||
|
def postNewSkuFromRecipe(site_name: str, user_id: int, data: dict, conn=None):
|
||||||
|
""" data = {'name', 'subtype', 'qty', 'uom_id', 'main_link', 'cost'}"""
|
||||||
|
self_conn = False
|
||||||
|
if not conn:
|
||||||
|
database_config = config.config()
|
||||||
|
conn = psycopg2.connect(**database_config)
|
||||||
|
conn.autocommit = False
|
||||||
|
self_conn = True
|
||||||
|
|
||||||
|
site = database_recipes.selectSiteTuple((site_name,))
|
||||||
|
default_zone = database_recipes.getZone(site_name,(site['default_zone'], ))
|
||||||
|
default_location = database_recipes.getLocation(site_name, (site['default_primary_location'],))
|
||||||
|
uuid = f"{default_zone['name']}@{default_location['name']}"
|
||||||
|
|
||||||
|
# create logistics info
|
||||||
|
logistics_info = database_payloads.LogisticsInfoPayload(
|
||||||
|
barcode=None,
|
||||||
|
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 = database_payloads.ItemInfoPayload(barcode=None)
|
||||||
|
|
||||||
|
# create Food Info
|
||||||
|
food_info = database_payloads.FoodInfoPayload()
|
||||||
|
|
||||||
|
logistics_info_id = 0
|
||||||
|
item_info_id = 0
|
||||||
|
food_info_id = 0
|
||||||
|
brand_id = 1
|
||||||
|
|
||||||
|
|
||||||
|
logistics_info = database_recipes.insertLogisticsInfoTuple(site_name, logistics_info.payload(), conn=conn)
|
||||||
|
item_info = database_recipes.insertItemInfoTuple(site_name, item_info.payload(), conn=conn)
|
||||||
|
food_info = database_recipes.insertFoodInfoTuple(site_name, food_info.payload(), conn=conn)
|
||||||
|
|
||||||
|
name = data['name']
|
||||||
|
name = name.replace("'", "@&apostraphe&")
|
||||||
|
links = {'main': data['main_link']}
|
||||||
|
search_string = f"&&{name}&&"
|
||||||
|
|
||||||
|
|
||||||
|
item = database_payloads.ItemsPayload(
|
||||||
|
barcode=None,
|
||||||
|
item_name=data['name'],
|
||||||
|
item_info_id=item_info['id'],
|
||||||
|
logistics_info_id=logistics_info['id'],
|
||||||
|
food_info_id=food_info['id'],
|
||||||
|
links=links,
|
||||||
|
brand=brand_id,
|
||||||
|
row_type="single",
|
||||||
|
item_type=data['subtype'],
|
||||||
|
search_string=search_string
|
||||||
|
)
|
||||||
|
|
||||||
|
item = database_recipes.insertItemTuple(site_name, item.payload(), conn=conn)
|
||||||
|
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(f"SELECT id FROM {site_name}_locations WHERE uuid=%s;", (uuid, ))
|
||||||
|
location_id = cur.fetchone()[0]
|
||||||
|
|
||||||
|
database_payloads.ItemLocationPayload
|
||||||
|
item_location = database_payloads.ItemLocationPayload(item['id'], location_id)
|
||||||
|
database_recipes.insertItemLocationsTuple(site_name, item_location.payload(), conn=conn)
|
||||||
|
|
||||||
|
|
||||||
|
creation_tuple = database_payloads.TransactionPayload(
|
||||||
|
datetime.datetime.now(),
|
||||||
|
logistics_info['id'],
|
||||||
|
None,
|
||||||
|
item['item_name'],
|
||||||
|
"SYSTEM",
|
||||||
|
0.0,
|
||||||
|
"Item added to the System!",
|
||||||
|
user_id,
|
||||||
|
{'location': uuid}
|
||||||
|
)
|
||||||
|
|
||||||
|
database_recipes.insertTransactionsTuple(site_name, creation_tuple.payload(), conn=conn)
|
||||||
|
|
||||||
|
item_uuid = item['item_uuid']
|
||||||
|
|
||||||
|
if self_conn:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return False, item_uuid
|
||||||
|
|
||||||
|
return conn, item_uuid
|
||||||
|
|||||||
@ -157,6 +157,34 @@ def postSKUItem():
|
|||||||
return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe Item was added successful!'})
|
return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe Item was added successful!'})
|
||||||
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} is not allowed!'})
|
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} is not allowed!'})
|
||||||
|
|
||||||
|
@recipes_api.route('/api/postNewSKUItem', methods=["POST"])
|
||||||
|
@access_api.login_required
|
||||||
|
def postNewSKUItem():
|
||||||
|
recipe = {}
|
||||||
|
if request.method == "POST":
|
||||||
|
recipe_id = int(request.get_json()['recipe_id'])
|
||||||
|
site_name = session['selected_site']
|
||||||
|
user_id = session['user_id']
|
||||||
|
|
||||||
|
_, item_uuid= recipe_processes.postNewSkuFromRecipe(site_name, user_id, request.get_json())
|
||||||
|
|
||||||
|
item = database_recipes.selectItemTupleByUUID(site_name, (item_uuid,))
|
||||||
|
|
||||||
|
recipe_item = db.RecipesTable.ItemPayload(
|
||||||
|
item_uuid=item_uuid,
|
||||||
|
rp_id=recipe_id,
|
||||||
|
item_type='sku',
|
||||||
|
item_name=request.get_json()['name'],
|
||||||
|
uom=request.get_json()['uom_id'],
|
||||||
|
qty=float(request.get_json()['qty']),
|
||||||
|
item_id=item['item_id'],
|
||||||
|
links={'main': request.get_json()['main_link']}
|
||||||
|
)
|
||||||
|
database_recipes.postAddRecipeItem(site_name, recipe_item.payload())
|
||||||
|
recipe = database_recipes.getRecipe(site_name, (recipe_id, ))
|
||||||
|
return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe Item was added successful!'})
|
||||||
|
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} is not allowed!'})
|
||||||
|
|
||||||
@recipes_api.route('/postImage/<recipe_id>', methods=["POST"])
|
@recipes_api.route('/postImage/<recipe_id>', methods=["POST"])
|
||||||
@access_api.login_required
|
@access_api.login_required
|
||||||
def uploadImage(recipe_id):
|
def uploadImage(recipe_id):
|
||||||
|
|||||||
4
application/recipes/sql/insertFoodInfoTuple.sql
Normal file
4
application/recipes/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/recipes/sql/insertItemInfoTuple.sql
Normal file
4
application/recipes/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/recipes/sql/insertItemLocationsTuple.sql
Normal file
4
application/recipes/sql/insertItemLocationsTuple.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/recipes/sql/insertItemTuple.sql
Normal file
5
application/recipes/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/recipes/sql/insertLogisticsInfoTuple.sql
Normal file
4
application/recipes/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 *;
|
||||||
@ -254,6 +254,47 @@ async function addSKUItem(item_id) {
|
|||||||
UIkit.modal(document.getElementById('itemsModal')).hide();
|
UIkit.modal(document.getElementById('itemsModal')).hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function addNewSKUItem() {
|
||||||
|
let newSKUName = document.getElementById('newSKUName').value
|
||||||
|
let newSKUSubtype = document.getElementById('newSKUSubtype').value
|
||||||
|
let newSKUQty = parseFloat(document.getElementById('newSKUQty').value)
|
||||||
|
let newSKUUOM = parseInt(document.getElementById('newSKUUOM').value)
|
||||||
|
let newWeblink = document.getElementById('newWeblink').value
|
||||||
|
let newSKUCost = parseFloat(document.getElementById('newSKUCost').value)
|
||||||
|
|
||||||
|
|
||||||
|
const response = await fetch(`/recipes/api/postNewSKUItem`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
recipe_id: recipe.id,
|
||||||
|
name: newSKUName,
|
||||||
|
subtype: newSKUSubtype,
|
||||||
|
qty: newSKUQty,
|
||||||
|
uom_id: newSKUUOM,
|
||||||
|
main_link: newWeblink,
|
||||||
|
cost: newSKUCost
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
data = await response.json()
|
||||||
|
message_type = "primary"
|
||||||
|
if(data.error){
|
||||||
|
message_type = "danger"
|
||||||
|
}
|
||||||
|
UIkit.notification({
|
||||||
|
message: data.message,
|
||||||
|
status: message_type,
|
||||||
|
pos: 'top-right',
|
||||||
|
timeout: 5000
|
||||||
|
});
|
||||||
|
recipe = data.recipe
|
||||||
|
await replenishRecipe()
|
||||||
|
UIkit.modal(document.getElementById('addNewSKUItem')).hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let updated = {}
|
let updated = {}
|
||||||
async function postUpdate() {
|
async function postUpdate() {
|
||||||
let description = document.getElementById('recipeDescription').value
|
let description = document.getElementById('recipeDescription').value
|
||||||
@ -326,6 +367,18 @@ async function deleteInstruction(index){
|
|||||||
await replenishInstructions()
|
await replenishInstructions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function openNewSKUModal() {
|
||||||
|
let itemsModal = document.getElementById('addNewSKUItem')
|
||||||
|
document.getElementById('newSKUName').value = ""
|
||||||
|
document.getElementById('newSKUSubtype').value = "FOOD"
|
||||||
|
document.getElementById('newSKUQty').value = 1
|
||||||
|
document.getElementById('newSKUUOM').value = "1"
|
||||||
|
document.getElementById('newWeblink').value = ""
|
||||||
|
document.getElementById('newSKUCost').value = 0.00
|
||||||
|
UIkit.modal(itemsModal).show();
|
||||||
|
}
|
||||||
|
|
||||||
let pagination_current = 1;
|
let pagination_current = 1;
|
||||||
let pagination_end = 10;
|
let pagination_end = 10;
|
||||||
let search_string = "";
|
let search_string = "";
|
||||||
|
|||||||
@ -174,6 +174,8 @@
|
|||||||
<div class="uk-button-group class="uk-width-expand" ">
|
<div class="uk-button-group class="uk-width-expand" ">
|
||||||
<button uk-toggle="target: #addCustomItem" type="button" id="addCustom" class="uk-button uk-button-default">Add Custom</button>
|
<button uk-toggle="target: #addCustomItem" type="button" id="addCustom" class="uk-button uk-button-default">Add Custom</button>
|
||||||
<button id="addSku" onclick="openSKUModal()" class="uk-button uk-button-default">Add SKU</button>
|
<button id="addSku" onclick="openSKUModal()" class="uk-button uk-button-default">Add SKU</button>
|
||||||
|
<button id="addSku" onclick="openNewSKUModal()" class="uk-button uk-button-default">Create SKU</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="uk-width-1-1 uk-margin-small-top">
|
<div class="uk-width-1-1 uk-margin-small-top">
|
||||||
@ -318,6 +320,69 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- add New SKU Line Modal-->
|
||||||
|
<div id="addNewSKUItem" uk-modal>
|
||||||
|
<div class="uk-modal-dialog">
|
||||||
|
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||||
|
<div class="uk-modal-header">
|
||||||
|
<h2 id="lineHeader" class="uk-modal-title">Add New Item...</h2>
|
||||||
|
</div>
|
||||||
|
<div class="uk-modal-body">
|
||||||
|
<div class="uk-margin-small">
|
||||||
|
<p class="uk-text-meta">Adding a new sku with both create a new item in the system with the information you provide and also add it to the recipe.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="uk-margin-small">
|
||||||
|
<label class="uk-form-label" for="newSKUType">Line Type</label>
|
||||||
|
<div class="uk-form-controls">
|
||||||
|
<input class="uk-input uk-disabled" id="newSKUType" type="text" placeholder="" value="new sku">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-margin-small">
|
||||||
|
<label class="uk-form-label" for="newSKUName">Item Name</label>
|
||||||
|
<div class="uk-form-controls">
|
||||||
|
<input class="uk-input" id="newSKUName" type="text" placeholder="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-margin-small">
|
||||||
|
<label class="uk-form-label" for="newSKUSubtype">Item Type</label>
|
||||||
|
<select id="newSKUSubtype" class="uk-select" aria-label="Select">
|
||||||
|
<option value="FOOD">Food</option>
|
||||||
|
<option value="FOOD_PLU">Food (PLU)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="uk-margin-small">
|
||||||
|
<label class="uk-form-label" for="newSKUQty">Quantity</label>
|
||||||
|
<div class="uk-form-controls">
|
||||||
|
<input class="uk-input" id="newSKUQty" type="number">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-margin-small">
|
||||||
|
<label class="uk-form-label" for="newSKUUOM">Unit of Measure</label>
|
||||||
|
<select id="newSKUUOM" class="uk-select" aria-label="Select">
|
||||||
|
{% for unit in units %}
|
||||||
|
<option value="{{unit['id']}}">{{unit['fullname']}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="uk-margin-small">
|
||||||
|
<label class="uk-form-label" for="newSKUCost">Cost</label>
|
||||||
|
<div class="uk-form-controls">
|
||||||
|
<input class="uk-input" id="newSKUCost" type="number">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-margin-small">
|
||||||
|
<label class="uk-form-label" for="newWeblink">Weblink</label>
|
||||||
|
<div class="uk-form-controls">
|
||||||
|
<input class="uk-input" id="newWeblink" type="text" placeholder="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-modal-footer uk-text-right">
|
||||||
|
<button onclick="addNewSKUItem()" class="uk-button uk-button-primary" type="button">Add</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- Items modal lookup -->
|
<!-- Items modal lookup -->
|
||||||
<div id="itemsModal" uk-modal>
|
<div id="itemsModal" uk-modal>
|
||||||
<div id="itemsModalInner" class="uk-modal-dialog uk-modal-body " uk-overflow-auto>
|
<div id="itemsModalInner" class="uk-modal-dialog uk-modal-body " uk-overflow-auto>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user