Implemeted first attempt at Recipe Receipting
This commit is contained in:
parent
da0c67b7f7
commit
1212473c48
Binary file not shown.
Binary file not shown.
BIN
application/recipes/__pycache__/recipe_processes.cpython-313.pyc
Normal file
BIN
application/recipes/__pycache__/recipe_processes.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
@ -91,12 +91,18 @@ def getRecipes(site:str, payload:tuple, convert=True):
|
||||
raise postsqldb.DatabaseError(error, payload, sql)
|
||||
return recordset, count
|
||||
|
||||
def getRecipe(site, payload:tuple, convert=True):
|
||||
database_config = config.config()
|
||||
def getRecipe(site, payload:tuple, convert=True, conn=None):
|
||||
self_conn = False
|
||||
record = ()
|
||||
with open(f"application/recipes/sql/getRecipeByID.sql", "r+") as file:
|
||||
sql = file.read().replace("%%site_name%%", site)
|
||||
try:
|
||||
with psycopg2.connect(**database_config) as conn:
|
||||
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()
|
||||
@ -104,6 +110,10 @@ def getRecipe(site, payload:tuple, convert=True):
|
||||
record = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||
if rows and not convert:
|
||||
record = rows
|
||||
|
||||
if self_conn:
|
||||
conn.close()
|
||||
|
||||
return record
|
||||
except (Exception, psycopg2.DatabaseError) as error:
|
||||
raise postsqldb.DatabaseError(error, payload, sql)
|
||||
@ -116,6 +126,164 @@ def getPicturePath(site:str, payload:tuple):
|
||||
rows = cur.fetchone()[0]
|
||||
return rows
|
||||
|
||||
def selectItemLocationsTuple(site_name, payload, convert=True, conn=None):
|
||||
item_locations = ()
|
||||
self_conn = False
|
||||
select_item_location_sql = f"SELECT * FROM {site_name}_item_locations WHERE part_id = %s AND location_id = %s;"
|
||||
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(select_item_location_sql, payload)
|
||||
rows = cur.fetchone()
|
||||
if rows and convert:
|
||||
item_locations = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||
elif rows and not convert:
|
||||
item_locations = rows
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return item_locations
|
||||
except Exception as error:
|
||||
return error
|
||||
|
||||
def selectCostLayersTuple(site_name, payload, convert=True):
|
||||
cost_layers = ()
|
||||
database_config = config.config()
|
||||
select_cost_layers_sql = f"SELECT cl.* FROM {site_name}_item_locations il JOIN {site_name}_cost_layers cl ON cl.id = ANY(il.cost_layers) where il.id=%s;"
|
||||
try:
|
||||
with psycopg2.connect(**database_config) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(select_cost_layers_sql, payload)
|
||||
rows = cur.fetchall()
|
||||
if rows and convert:
|
||||
cost_layers = rows
|
||||
cost_layers = [postsqldb.tupleDictionaryFactory(cur.description, layer) for layer in rows]
|
||||
elif rows and not convert:
|
||||
cost_layers = rows
|
||||
return cost_layers
|
||||
except Exception as error:
|
||||
return error
|
||||
|
||||
def selectLocationsTuple(site, payload, convert=True, conn=None):
|
||||
selected = ()
|
||||
self_conn = False
|
||||
sql = f"SELECT * FROM {site}_locations WHERE id=%s;"
|
||||
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:
|
||||
selected = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||
elif rows and not convert:
|
||||
selected = rows
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return selected
|
||||
except Exception as error:
|
||||
raise postsqldb.DatabaseError(error, payload, sql)
|
||||
|
||||
def selectItemTupleByUUID(site, payload, convert=True, conn=None):
|
||||
selected = ()
|
||||
self_conn = False
|
||||
with open(f"application/recipes/sql/getItemTupleByUUID.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:
|
||||
selected = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||
elif rows and not convert:
|
||||
selected = rows
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return selected
|
||||
except Exception as error:
|
||||
raise postsqldb.DatabaseError(error, payload, sql)
|
||||
|
||||
def insertCostLayersTuple(site, payload, convert=True, conn=None):
|
||||
cost_layer = ()
|
||||
self_conn = False
|
||||
|
||||
with open(f"application/recipes/sql/insertCostLayersTuple.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:
|
||||
cost_layer = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||
elif rows and not convert:
|
||||
cost_layer = rows
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return cost_layer
|
||||
except Exception as error:
|
||||
raise postsqldb.DatabaseError(error, payload, sql)
|
||||
|
||||
def insertTransactionsTuple(site, payload, convert=True, conn=None):
|
||||
# payload (tuple): (timestamp[timestamp], logistics_info_id[int], barcode[str], name[str],
|
||||
transaction = ()
|
||||
self_conn = False
|
||||
with open(f"application/recipes/sql/insertTransactionsTuple.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:
|
||||
transaction = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||
elif rows and not convert:
|
||||
transaction = rows
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
except Exception as error:
|
||||
raise postsqldb.DatabaseError(error, payload, sql)
|
||||
return transaction
|
||||
|
||||
def postAddRecipe(site:str, payload:tuple, convert:bool=True):
|
||||
database_config = config.config()
|
||||
record = ()
|
||||
@ -200,6 +368,93 @@ def postDeleteRecipeItem(site:str, payload:tuple, convert:bool=True):
|
||||
deleted = rows
|
||||
return deleted
|
||||
|
||||
def updateCostLayersTuple(site, payload, convert=True, conn=None):
|
||||
cost_layer = ()
|
||||
self_conn = False
|
||||
|
||||
set_clause, values = postsqldb.updateStringFactory(payload['update'])
|
||||
values.append(payload['id'])
|
||||
sql = f"UPDATE {site}_cost_layers SET {set_clause} WHERE id=%s RETURNING *;"
|
||||
|
||||
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, values)
|
||||
rows = cur.fetchone()
|
||||
if rows and convert:
|
||||
cost_layer = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||
elif rows and not convert:
|
||||
cost_layer = rows
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return cost_layer
|
||||
except Exception as error:
|
||||
return error
|
||||
|
||||
def updateItemLocation(site, payload, convert=True, conn=None):
|
||||
item_location = ()
|
||||
self_conn = False
|
||||
|
||||
with open(f"application/recipes/sql/updateItemLocation.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_location = postsqldb.tupleDictionaryFactory(cur.description, rows)
|
||||
elif rows and not convert:
|
||||
item_location = rows
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return item_location
|
||||
except Exception as error:
|
||||
return error
|
||||
|
||||
def deleteCostLayersTuple(site, payload, convert=True, conn=None):
|
||||
deleted = ()
|
||||
self_conn = False
|
||||
sql = f"WITH deleted_rows AS (DELETE FROM {site}_cost_layers WHERE id IN ({','.join(['%s'] * len(payload))}) RETURNING *) SELECT * FROM deleted_rows;"
|
||||
try:
|
||||
if not conn:
|
||||
database_config = config.config()
|
||||
conn = psycopg2.connect(**database_config)
|
||||
conn.autocommit = True
|
||||
self_conn = True
|
||||
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(sql, payload)
|
||||
rows = cur.fetchall()
|
||||
if rows and convert:
|
||||
deleted = [postsqldb.tupleDictionaryFactory(cur.description, r) for r in rows]
|
||||
elif rows and not convert:
|
||||
deleted = rows
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return deleted
|
||||
except Exception as error:
|
||||
raise postsqldb.DatabaseError(error, payload, sql)
|
||||
|
||||
def deleteRecipe(site:str, payload:tuple, convert:bool=True):
|
||||
database_config = config.config()
|
||||
deleted = ()
|
||||
|
||||
143
application/recipes/recipe_processes.py
Normal file
143
application/recipes/recipe_processes.py
Normal file
@ -0,0 +1,143 @@
|
||||
import psycopg2
|
||||
import datetime
|
||||
|
||||
from application import database_payloads, postsqldb
|
||||
from application.recipes import database_recipes
|
||||
import config
|
||||
|
||||
def postTransaction(site_name, user_id, data: dict, conn=None):
|
||||
""" dict_keys(['item_id', 'logistics_info_id', 'barcode', 'item_name', 'transaction_type',
|
||||
'quantity', 'description', 'cost', 'vendor', 'expires', 'location_id'])"""
|
||||
def quantityFactory(quantity_on_hand:float, quantity:float, transaction_type:str):
|
||||
if transaction_type == "Adjust In":
|
||||
quantity_on_hand += quantity
|
||||
return quantity_on_hand
|
||||
if transaction_type == "Adjust Out":
|
||||
quantity_on_hand -= quantity
|
||||
return quantity_on_hand
|
||||
raise Exception("The transaction type is wrong!")
|
||||
|
||||
self_conn = False
|
||||
if not conn:
|
||||
database_config = config.config()
|
||||
conn = psycopg2.connect(**database_config)
|
||||
conn.autocommit = False
|
||||
self_conn = True
|
||||
|
||||
|
||||
transaction_time = datetime.datetime.now()
|
||||
|
||||
cost_layer = postsqldb.CostLayerPayload(
|
||||
aquisition_date=transaction_time,
|
||||
quantity=float(data['quantity']),
|
||||
cost=float(data['cost']),
|
||||
currency_type="USD",
|
||||
vendor=int(data['vendor']),
|
||||
expires=data['expires']
|
||||
)
|
||||
transaction = postsqldb.TransactionPayload(
|
||||
timestamp=transaction_time,
|
||||
logistics_info_id=int(data['logistics_info_id']),
|
||||
barcode=data['barcode'],
|
||||
name=data['item_name'],
|
||||
transaction_type=data['transaction_type'],
|
||||
quantity=float(data['quantity']),
|
||||
description=data['description'],
|
||||
user_id=user_id,
|
||||
)
|
||||
|
||||
location = database_recipes.selectItemLocationsTuple(site_name, (data['item_id'], data['location_id']), conn=conn)
|
||||
site_location = database_recipes.selectLocationsTuple(site_name, (location['location_id'], ), conn=conn)
|
||||
print(location)
|
||||
cost_layers: list = location['cost_layers']
|
||||
if data['transaction_type'] == "Adjust In":
|
||||
cost_layer = database_recipes.insertCostLayersTuple(site_name, cost_layer.payload(), conn=conn)
|
||||
cost_layers.append(cost_layer['id'])
|
||||
|
||||
if data['transaction_type'] == "Adjust Out":
|
||||
if float(location['quantity_on_hand']) < float(data['quantity']):
|
||||
raise Exception(f"The quantity on hand for {data['item_name']} in {site_location['uuid']} is not enough to satisfy your transaction!")
|
||||
cost_layers = database_recipes.selectCostLayersTuple(site_name, payload=(location['id'], ))
|
||||
|
||||
new_cost_layers = []
|
||||
qty = float(data['quantity'])
|
||||
for layer in cost_layers:
|
||||
if qty == 0.0:
|
||||
new_cost_layers.append(layer['id'])
|
||||
elif qty >= float(layer['quantity']):
|
||||
qty -= float(layer['quantity'])
|
||||
layer['quantity'] = 0.0
|
||||
else:
|
||||
layer['quantity'] -= qty
|
||||
new_cost_layers.append(layer['id'])
|
||||
database_recipes.updateCostLayersTuple(site_name, {'id': layer['id'], 'update': {'quantity': layer['quantity']}}, conn=conn)
|
||||
qty = 0.0
|
||||
|
||||
if layer['quantity'] == 0.0:
|
||||
database_recipes.deleteCostLayersTuple(site_name, (layer['id'],), conn=conn)
|
||||
|
||||
cost_layers = new_cost_layers
|
||||
|
||||
quantity_on_hand = quantityFactory(float(location['quantity_on_hand']), data['quantity'], data['transaction_type'])
|
||||
|
||||
updated_item_location_payload = (cost_layers, quantity_on_hand, data['item_id'], data['location_id'])
|
||||
database_recipes.updateItemLocation(site_name, updated_item_location_payload, conn=conn)
|
||||
|
||||
#site_location = database_recipes.selectLocationsTuple(site_name, (location['location_id'], ), conn=conn)
|
||||
|
||||
transaction.data = {'location': site_location['uuid']}
|
||||
|
||||
database_recipes.insertTransactionsTuple(site_name, transaction.payload(), conn=conn)
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return conn
|
||||
|
||||
return {"error": False, "message":f"Transaction Successful!"}
|
||||
|
||||
def process_recipe_receipt(site_name, user_id, data:dict, conn=None):
|
||||
"""data={'recipe_id': recipe_id}"""
|
||||
|
||||
self_conn = False
|
||||
if not conn:
|
||||
database_config = config.config()
|
||||
conn = psycopg2.connect(**database_config)
|
||||
conn.autocommit = False
|
||||
self_conn = True
|
||||
|
||||
recipe = database_recipes.getRecipe(site_name, (data['recipe_id'],), conn=conn)
|
||||
|
||||
sku_items = [rp_item for rp_item in recipe['recipe_items'] if rp_item['item_type'] == "sku"]
|
||||
for item in sku_items:
|
||||
""" dict_keys(['item_id', 'logistics_info_id', 'barcode', 'item_name', 'transaction_type',
|
||||
'quantity', 'description', 'cost', 'vendor', 'expires', 'location_id'])"""
|
||||
item_stuff = database_recipes.selectItemTupleByUUID(site_name, (item['item_uuid'],), conn=conn)
|
||||
print(item_stuff)
|
||||
payload = {
|
||||
'item_id': item_stuff['item_id'],
|
||||
'logistics_info_id': item_stuff['logistics_info_id'],
|
||||
'barcode': "",
|
||||
'item_name': item_stuff['item_name'],
|
||||
'transaction_type': "Adjust Out",
|
||||
'quantity': item['qty'],
|
||||
'description': f"Recipe Receipt - {data['recipe_id']}",
|
||||
'cost': 0.00,
|
||||
'vendor': 0,
|
||||
'expires': False,
|
||||
'location_id': item_stuff['auto_issue_location']
|
||||
}
|
||||
print(payload)
|
||||
|
||||
try:
|
||||
postTransaction(site_name, user_id, payload, conn=conn)
|
||||
except Exception as error:
|
||||
conn.rollback()
|
||||
conn.close()
|
||||
return False, str(error)
|
||||
|
||||
if self_conn:
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return True, ""
|
||||
@ -8,7 +8,7 @@ import math
|
||||
import main
|
||||
import webpush
|
||||
from application.access_module import access_api
|
||||
from application.recipes import database_recipes
|
||||
from application.recipes import database_recipes, recipe_processes
|
||||
from application import postsqldb as db
|
||||
|
||||
recipes_api = Blueprint('recipes_api', __name__, template_folder="templates", static_folder="static")
|
||||
@ -199,3 +199,16 @@ def saveRecipeItem():
|
||||
recipe = database_recipes.getRecipe(site_name, (int(updated_line['rp_id']), ))
|
||||
return jsonify({'recipe': recipe, 'error': False, 'message': f'Recipe Item {updated_line['item_name']} was updated successful!'})
|
||||
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} not allowed!'})
|
||||
|
||||
|
||||
@recipes_api.route('/api/receiptRecipe', methods=["POST"])
|
||||
@access_api.login_required
|
||||
def receiptRecipe():
|
||||
if request.method == "POST":
|
||||
site_name = session['selected_site']
|
||||
user_id = session['user_id']
|
||||
status, message = recipe_processes.process_recipe_receipt(site_name, user_id, request.get_json())
|
||||
if not status:
|
||||
return jsonify(status=400, message=message)
|
||||
return jsonify(status=201, message="Recipe Transacted Successfully!")
|
||||
return jsonify(status=405, message=f"{request.method} is not an allowed method on this endpoint!")
|
||||
6
application/recipes/sql/getItemTupleByUUID.sql
Normal file
6
application/recipes/sql/getItemTupleByUUID.sql
Normal file
@ -0,0 +1,6 @@
|
||||
SELECT items.id AS item_id,
|
||||
items.item_name as item_name,
|
||||
items.logistics_info_id as logistics_info_id,
|
||||
lginf.auto_issue_location as auto_issue_location
|
||||
FROM %%site_name%%_items items
|
||||
LEFT JOIN %%site_name%%_logistics_info lginf ON lginf.id = items.logistics_info_id WHERE item_uuid=%s;
|
||||
4
application/recipes/sql/insertCostLayersTuple.sql
Normal file
4
application/recipes/sql/insertCostLayersTuple.sql
Normal file
@ -0,0 +1,4 @@
|
||||
INSERT INTO %%site_name%%_cost_layers
|
||||
(aquisition_date, quantity, cost, currency_type, expires, vendor)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
RETURNING *;
|
||||
5
application/recipes/sql/insertTransactionsTuple.sql
Normal file
5
application/recipes/sql/insertTransactionsTuple.sql
Normal file
@ -0,0 +1,5 @@
|
||||
INSERT INTO %%site_name%%_transactions
|
||||
(timestamp, logistics_info_id, barcode, name, transaction_type,
|
||||
quantity, description, user_id, data)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
RETURNING *;
|
||||
4
application/recipes/sql/updateItemLocation.sql
Normal file
4
application/recipes/sql/updateItemLocation.sql
Normal file
@ -0,0 +1,4 @@
|
||||
UPDATE %%site_name%%_item_locations
|
||||
SET cost_layers = %s, quantity_on_hand = %s
|
||||
WHERE part_id=%s AND location_id=%s
|
||||
RETURNING *;
|
||||
@ -21,6 +21,7 @@ async function replenishRecipe() {
|
||||
|
||||
await replenishIngrediantsTable()
|
||||
await replenishInstructions()
|
||||
await replenishTransactionsTable()
|
||||
|
||||
await getImage()
|
||||
|
||||
@ -32,16 +33,21 @@ async function replenishIngrediantsTable() {
|
||||
|
||||
|
||||
for(let i=0; i<recipe.recipe_items.length; i++){
|
||||
let qty_needed = recipe.recipe_items[i].qty
|
||||
let quantity_on_hand = recipe.recipe_items[i].quantity_on_hand
|
||||
let item_type = recipe.recipe_items[i].item_type
|
||||
|
||||
let tableRow = document.createElement('tr')
|
||||
|
||||
let markerCell = document.createElement('td')
|
||||
if (recipe.recipe_items[i].qty <= recipe.recipe_items[i].quantity_on_hand){
|
||||
markerCell.innerHTML = `<span class="uk-label uk-label-success">Have</span>`
|
||||
} else {
|
||||
if (qty_needed <= quantity_on_hand && item_type === "sku"){
|
||||
markerCell.innerHTML = `<span class="uk-label uk-label-success">On Hand</span>`
|
||||
} else if (qty_needed > quantity_on_hand && item_type === "sku") {
|
||||
markerCell.innerHTML = `<span class="uk-label uk-label-danger">Missing</span>`
|
||||
} else {
|
||||
markerCell.innerHTML = ""
|
||||
}
|
||||
|
||||
|
||||
let nameCell = document.createElement('td')
|
||||
nameCell.innerHTML = `${recipe.recipe_items[i].item_name}`
|
||||
|
||||
@ -54,6 +60,27 @@ async function replenishIngrediantsTable() {
|
||||
|
||||
}
|
||||
|
||||
async function replenishTransactionsTable() {
|
||||
let receiptRecipeTableBody = document.getElementById('receiptRecipeTableBody')
|
||||
receiptRecipeTableBody.innerHTML = ""
|
||||
|
||||
for(let i=0; i < recipe.recipe_items.length; i++){
|
||||
if (recipe.recipe_items[i].item_type === "sku"){
|
||||
let tableRow = document.createElement('tr')
|
||||
|
||||
let nameCell = document.createElement('td')
|
||||
nameCell.innerHTML = `${recipe.recipe_items[i].item_name}`
|
||||
|
||||
let qtyUOMCell = document.createElement('td')
|
||||
qtyUOMCell.innerHTML = `${recipe.recipe_items[i].qty}`
|
||||
|
||||
tableRow.append(nameCell, qtyUOMCell)
|
||||
receiptRecipeTableBody.append(tableRow)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function replenishInstructions() {
|
||||
let tileList = document.getElementById('tileList')
|
||||
tileList.innerHTML = ""
|
||||
@ -90,3 +117,27 @@ async function getImage(){
|
||||
document.getElementById('recipeImage').src = imageURL;
|
||||
});
|
||||
}
|
||||
|
||||
async function receiptRecipe(){
|
||||
let recipe_id = recipe.id
|
||||
const response = await fetch(`/recipes/api/receiptRecipe`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
recipe_id: recipe_id
|
||||
}),
|
||||
});
|
||||
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
|
||||
});
|
||||
}
|
||||
@ -140,9 +140,34 @@
|
||||
</table>
|
||||
</div>
|
||||
<div id="tileList" class="uk-width-1-2@l uk-child-width-1-1 uk-grid-collapse">
|
||||
</div>
|
||||
<div class="uk-width-1-1">
|
||||
<button class="uk-button uk-button-primary" type="button" uk-toggle="target: #receiptRecipeModal">Receipt Recipe</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- Receipt Recipe Modal -->
|
||||
<div id="receiptRecipeModal" uk-modal>
|
||||
<div class="uk-modal-dialog uk-modal-body">
|
||||
<h2 class="uk-modal-title">Recipe Receipt Transaction</h2>
|
||||
<p>You are about to receipt these items from the system, please confirm before completing these Transaction as once they have been completed
|
||||
this cannot be reversed.</p>
|
||||
<table class="uk-table uk-table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Item</th>
|
||||
<th>Qty</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="receiptRecipeTableBody">
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="uk-text-right">
|
||||
<button class="uk-button uk-button-default uk-modal-close" type="button">Cancel</button>
|
||||
<button onclick="receiptRecipe()" class="uk-button uk-button-primary" type="button">Complete</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@ -122,3 +122,21 @@
|
||||
2025-08-10 07:48:28.429239 --- ERROR --- DatabaseError(message='missing FROM-clause entry for table "item"LINE 24: LEFT JOIN sum_cte ON item.id = sum_cte.id ^',
|
||||
payload=(1,),
|
||||
sql='WITH passed_id AS (SELECT %s AS passed_id), sum_cte AS ( SELECT mi.id, SUM(mil.quantity_on_hand)::FLOAT8 AS total_sum FROM main_item_locations mil JOIN main_items mi ON mil.part_id = mi.id GROUP BY mi.id ), cte_recipe_items AS ( SELECT items.*, /*COALESCE(main_items.barcode, items.uuid) AS uuid,*/ (SELECT COALESCE(row_to_json(units.*), '{}') FROM units WHERE units.id=main_item_info.uom) AS item_uom, COALESCE(main_items.item_name, items.item_name) AS item_name, COALESCE(main_items.links, items.links) AS links, row_to_json(units.*) as uom, (SELECT COALESCE(array_agg(jsonb_build_object('conversion', conv, 'unit', units)), '{}') FROM main_conversions conv LEFT JOIN units ON conv.uom_id = units.id WHERE conv.item_id = main_items.id) AS conversions, COALESCE(sum_cte.total_sum, 0) AS quantity_on_hand FROM main_recipe_items items LEFT JOIN main_items ON items.item_id = main_items.id LEFT JOIN main_item_info ON main_items.item_info_id = main_item_info.id LEFT JOIN units ON units.id = items.uom LEFT JOIN sum_cte ON item.id = sum_cte.id WHERE items.rp_id = (SELECT passed_id FROM passed_id) ORDER BY items.item_name ASC ) SELECT (SELECT passed_id FROM passed_id) AS passed_id, main_recipes.*, logins.username as author, (SELECT COALESCE(array_agg(row_to_json(ris)), '{}') FROM cte_recipe_items ris) AS recipe_itemsFROM main_recipesJOIN logins ON main_recipes.author = logins.idWHERE main_recipes.id=(SELECT passed_id FROM passed_id)')
|
||||
2025-08-10 08:56:10.432791 --- ERROR --- DatabaseError(message=''int' object does not support indexing',
|
||||
payload=4,
|
||||
sql='WITH passed_id AS (SELECT %s AS passed_id), sum_cte AS ( SELECT mi.id, SUM(mil.quantity_on_hand)::FLOAT8 AS total_sum FROM test_item_locations mil JOIN test_items mi ON mil.part_id = mi.id GROUP BY mi.id ), cte_recipe_items AS ( SELECT items.*, /*COALESCE(test_items.barcode, items.uuid) AS uuid,*/ (SELECT COALESCE(row_to_json(units.*), '{}') FROM units WHERE units.id=test_item_info.uom) AS item_uom, COALESCE(test_items.item_name, items.item_name) AS item_name, COALESCE(test_items.links, items.links) AS links, row_to_json(units.*) as uom, (SELECT COALESCE(array_agg(jsonb_build_object('conversion', conv, 'unit', units)), '{}') FROM test_conversions conv LEFT JOIN units ON conv.uom_id = units.id WHERE conv.item_id = test_items.id) AS conversions, COALESCE(sum_cte.total_sum, 0.0) AS quantity_on_hand FROM test_recipe_items items LEFT JOIN test_items ON items.item_id = test_items.id LEFT JOIN test_item_info ON test_items.item_info_id = test_item_info.id LEFT JOIN units ON units.id = items.uom LEFT JOIN sum_cte ON test_items.id = sum_cte.id WHERE items.rp_id = (SELECT passed_id FROM passed_id) ORDER BY items.item_name ASC ) SELECT (SELECT passed_id FROM passed_id) AS passed_id, test_recipes.*, logins.username as author, (SELECT COALESCE(array_agg(row_to_json(ris)), '{}') FROM cte_recipe_items ris) AS recipe_itemsFROM test_recipesJOIN logins ON test_recipes.author = logins.idWHERE test_recipes.id=(SELECT passed_id FROM passed_id)')
|
||||
2025-08-10 08:57:07.377357 --- ERROR --- DatabaseError(message=''int' object does not support indexing',
|
||||
payload=4,
|
||||
sql='WITH passed_id AS (SELECT %s AS passed_id), sum_cte AS ( SELECT mi.id, SUM(mil.quantity_on_hand)::FLOAT8 AS total_sum FROM test_item_locations mil JOIN test_items mi ON mil.part_id = mi.id GROUP BY mi.id ), cte_recipe_items AS ( SELECT items.*, /*COALESCE(test_items.barcode, items.uuid) AS uuid,*/ (SELECT COALESCE(row_to_json(units.*), '{}') FROM units WHERE units.id=test_item_info.uom) AS item_uom, COALESCE(test_items.item_name, items.item_name) AS item_name, COALESCE(test_items.links, items.links) AS links, row_to_json(units.*) as uom, (SELECT COALESCE(array_agg(jsonb_build_object('conversion', conv, 'unit', units)), '{}') FROM test_conversions conv LEFT JOIN units ON conv.uom_id = units.id WHERE conv.item_id = test_items.id) AS conversions, COALESCE(sum_cte.total_sum, 0.0) AS quantity_on_hand FROM test_recipe_items items LEFT JOIN test_items ON items.item_id = test_items.id LEFT JOIN test_item_info ON test_items.item_info_id = test_item_info.id LEFT JOIN units ON units.id = items.uom LEFT JOIN sum_cte ON test_items.id = sum_cte.id WHERE items.rp_id = (SELECT passed_id FROM passed_id) ORDER BY items.item_name ASC ) SELECT (SELECT passed_id FROM passed_id) AS passed_id, test_recipes.*, logins.username as author, (SELECT COALESCE(array_agg(row_to_json(ris)), '{}') FROM cte_recipe_items ris) AS recipe_itemsFROM test_recipesJOIN logins ON test_recipes.author = logins.idWHERE test_recipes.id=(SELECT passed_id FROM passed_id)')
|
||||
2025-08-10 08:57:32.169483 --- ERROR --- DatabaseError(message=''int' object does not support indexing',
|
||||
payload=4,
|
||||
sql='WITH passed_id AS (SELECT %s AS passed_id), sum_cte AS ( SELECT mi.id, SUM(mil.quantity_on_hand)::FLOAT8 AS total_sum FROM test_item_locations mil JOIN test_items mi ON mil.part_id = mi.id GROUP BY mi.id ), cte_recipe_items AS ( SELECT items.*, /*COALESCE(test_items.barcode, items.uuid) AS uuid,*/ (SELECT COALESCE(row_to_json(units.*), '{}') FROM units WHERE units.id=test_item_info.uom) AS item_uom, COALESCE(test_items.item_name, items.item_name) AS item_name, COALESCE(test_items.links, items.links) AS links, row_to_json(units.*) as uom, (SELECT COALESCE(array_agg(jsonb_build_object('conversion', conv, 'unit', units)), '{}') FROM test_conversions conv LEFT JOIN units ON conv.uom_id = units.id WHERE conv.item_id = test_items.id) AS conversions, COALESCE(sum_cte.total_sum, 0.0) AS quantity_on_hand FROM test_recipe_items items LEFT JOIN test_items ON items.item_id = test_items.id LEFT JOIN test_item_info ON test_items.item_info_id = test_item_info.id LEFT JOIN units ON units.id = items.uom LEFT JOIN sum_cte ON test_items.id = sum_cte.id WHERE items.rp_id = (SELECT passed_id FROM passed_id) ORDER BY items.item_name ASC ) SELECT (SELECT passed_id FROM passed_id) AS passed_id, test_recipes.*, logins.username as author, (SELECT COALESCE(array_agg(row_to_json(ris)), '{}') FROM cte_recipe_items ris) AS recipe_itemsFROM test_recipesJOIN logins ON test_recipes.author = logins.idWHERE test_recipes.id=(SELECT passed_id FROM passed_id)')
|
||||
2025-08-10 09:12:15.585887 --- ERROR --- DatabaseError(message='syntax error at or near "%"LINE 1: SELECT * FROM test_items items LEFT JOIN %site_name%_logisti... ^',
|
||||
payload=('44c41878-e645-4e16-a402-e480936ac4aa',),
|
||||
sql='SELECT * FROM test_items items LEFT JOIN %%site_name%%_logistics_info lginf ON lginf.id = items.logistics_info_id WHERE item_uuid=%s;')
|
||||
2025-08-10 09:21:38.180067 --- ERROR --- DatabaseError(message='duplicate key value violates unique constraint "test_item_locations_part_id_location_id_key"DETAIL: Key (part_id, location_id)=(2016, 2) already exists.',
|
||||
payload=(2016, 2, 0.0, '{}'),
|
||||
sql='INSERT INTO test_item_locations(part_id, location_id, quantity_on_hand, cost_layers) VALUES (%s, %s, %s, %s)RETURNING *;')
|
||||
2025-08-10 09:26:25.470903 --- ERROR --- DatabaseError(message='syntax error at or near "{"LINE 1: SELECT items.*, lginf.* AS logistics_info FROM {site}_items ... ^',
|
||||
payload=('44c41878-e645-4e16-a402-e480936ac4aa',),
|
||||
sql='SELECT items.*, lginf.* AS logistics_info FROM {site}_items items LEFT JOIN {site}_logistics_info lginf ON lginf.id = items.logistics_info_id WHERE item_uuid=%s;')
|
||||
Loading…
x
Reference in New Issue
Block a user