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 [],
|
||||
nutrients JSONB,
|
||||
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,
|
||||
lead_time_days FLOAT8,
|
||||
ai_pick BOOLEAN,
|
||||
prefixes INTEGER [],
|
||||
UNIQUE(barcode)
|
||||
prefixes INTEGER []
|
||||
UNIQUE(item_info_uuid)
|
||||
);
|
||||
@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS %%site_name%%_logistics_info(
|
||||
primary_zone INTEGER NOT NULL,
|
||||
auto_issue_location INTEGER NOT NULL,
|
||||
auto_issue_zone INTEGER NOT NULL,
|
||||
UNIQUE(barcode),
|
||||
UNIQUE(logistics_info_uuid),
|
||||
CONSTRAINT fk_primary_location
|
||||
FOREIGN KEY(primary_location)
|
||||
REFERENCES %%site_name%%_locations(id),
|
||||
|
||||
@ -2,7 +2,7 @@ CREATE TABLE IF NOT EXISTS %%site_name%%_Transactions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
timestamp TIMESTAMP,
|
||||
logistics_info_id INTEGER NOT NULL,
|
||||
barcode VARCHAR(255) NOT NULL,
|
||||
barcode VARCHAR(255),
|
||||
name VARCHAR(255),
|
||||
transaction_type VARCHAR(255) NOT NULL,
|
||||
quantity FLOAT8 NOT NULL,
|
||||
|
||||
@ -45,10 +45,6 @@ class ItemInfoPayload:
|
||||
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 (
|
||||
|
||||
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]
|
||||
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):
|
||||
item_locations = ()
|
||||
self_conn = False
|
||||
@ -312,6 +365,158 @@ def insertTransactionsTuple(site, payload, convert=True, conn=None):
|
||||
raise postsqldb.DatabaseError(error, payload, sql)
|
||||
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):
|
||||
database_config = config.config()
|
||||
record = ()
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import psycopg2
|
||||
import datetime
|
||||
import json
|
||||
|
||||
from application import database_payloads, postsqldb
|
||||
from application.recipes import database_recipes
|
||||
from application.items import database_items
|
||||
import config
|
||||
|
||||
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()
|
||||
|
||||
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': 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"])
|
||||
@access_api.login_required
|
||||
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();
|
||||
}
|
||||
|
||||
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 = {}
|
||||
async function postUpdate() {
|
||||
let description = document.getElementById('recipeDescription').value
|
||||
@ -326,6 +367,18 @@ async function deleteInstruction(index){
|
||||
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_end = 10;
|
||||
let search_string = "";
|
||||
|
||||
@ -174,6 +174,8 @@
|
||||
<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 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 class="uk-width-1-1 uk-margin-small-top">
|
||||
@ -318,6 +320,69 @@
|
||||
</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 -->
|
||||
<div id="itemsModal" uk-modal>
|
||||
<div id="itemsModalInner" class="uk-modal-dialog uk-modal-body " uk-overflow-auto>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user