From 94f7bad2e6631088bafe46ac08ead3fd00c6aade Mon Sep 17 00:00:00 2001 From: Jadowyne Ulve Date: Sun, 10 Aug 2025 10:33:00 -0500 Subject: [PATCH] Implemented conv_factors into recipe receipts --- .../database_recipes.cpython-313.pyc | Bin 27326 -> 28461 bytes .../recipe_processes.cpython-313.pyc | Bin 6196 -> 6308 bytes application/recipes/database_recipes.py | 28 ++++++++++++++++++ application/recipes/recipe_processes.py | 20 +++++-------- .../recipes/static/js/recipeEditHandler.js | 2 +- .../recipes/static/js/recipeViewHandler.js | 4 ++- logs/database.log | 8 ++++- 7 files changed, 47 insertions(+), 15 deletions(-) diff --git a/application/recipes/__pycache__/database_recipes.cpython-313.pyc b/application/recipes/__pycache__/database_recipes.cpython-313.pyc index 6d5ab8f9c6fb03b42061860d2ee230580091cf4f..f51235da8ddc229fa5df225f2ad80305cb1e3e42 100644 GIT binary patch delta 1212 zcmZXSUrbwd6vywcz4vyzw9x;hm$ki&8P+fI*MAgSk&`#yIi8#Hf4Fq)&qv|2%4Z&<7Jdzf0p5xi|OQ&pF@o z`<-)tw_p53?mi-|e_AXOhnMaC?fLgE)mz)iR=vAF?o)Z0TOib=`cxr(L>1FVRa06D zi|P@~^XRmo!!ic-XftDeTpQ+9shPE?{`$vVIlpSrH?(3=t4=o6ueRxAN3!bVK(guN zM6&DTLUQQje%zorj1%*07?0|M^Td1O|HHbQzW2~dPt%bPIqglS1N(ZB2|b1+>*Pb~ z(8+&j-7%Sy^kD);5)5eHknq#+>jgXf5D~x;Qpto?41LCvE6^EE5mj3aFB0vy)bF^Bjl&igrvxVI3 zN`)$8$t!VX{cQFL|H)eAg^Q!fQRQIsj=U04o~kOtiIHX(JswOYf)+TJIqf)$Eom>4 z5R(K7Jg~SS6E+P-{~I7xTV9-_&!hP>KGg=w2DjH{+ql@Ux;8E~%zfL=ZSmn5`cSHF zM1MCpp&oi0HUlQX^G@4e9_TvP6MhC4y*u0z?cpAHhL1;O<5vR;20OA8J!#rGVPf1P zjo6Gk&w578#;?u7hz)jSkM==d!vOdChe#4$&&c2yNQ*PL7a>}0z)tuSGVICjgSxfI z`DWdZk*ttL&#(0lSp?xK;vnqD0$M4W<;4t!Gz;IyP6@M!acw`w6F!HijVBrgZTE73 z2o(&our)cQO~=18igOsQ_rboo9kydU#3p5H0aLWdWS+?@@aklrKoOUrnWod z6ofYrKhgfq{KJdaSV05}JYdV85#GY^TWvfaHTZNk#{(>Xi zwX7ipNh)Z-KY;=t%@;0Auu_!?`^1!;E@ekYuQFlhL)lSK_F|O13uPlwHVkEb=}kzK Ve9|pMf=_h}YNa~yf??tFe*xKaHhTa7 delta 859 zcmZXQ%WD%+6vpRHXC_TzYF?&EnluZQ5PYPCAVo+qeb7ys+T0{kOhQQdh;3q(-Bs$a)jJzny#6&{)lP{l7T5@wbQ(Xt4G2e0zTgY>vgP9(cdE+mIeZX~BpCl1FNE4a`XD|n7% z+(xFiGXulKy3zR*k5TRGtfsw2#*bTgkqPTV^63;n^6L~l(${D7^)HY}|2J{hRD|rA zSC*Tr%?AHMPMsqWFh#GCDc*>_QAi5T#4;q!H)A!zpAYQH5Q-0zX|Tt9a3fyOaya2Y z;(Ku?Q7AGWy!c&){lq1sW@x0O&Y&;zMEg*(?d*Y6wT}5PhNJM>*OuEz(%0XyP zgy3%SKq;c)+v#1Ik6jKCwT5yOthp?IJN=l!+9M3S0MC2-{2uu?PgPc!9zBiSsB7e=*tF=PRrl*914 z5VdE8jEk@+!V)+tL2wk$t2a?L`B>4ds<#pE^FrmfqOFReI2QH7di8?3iL%YNtCL-% z0e_al8WZ^@oUNU*ITf5edjOlbIURS diff --git a/application/recipes/__pycache__/recipe_processes.cpython-313.pyc b/application/recipes/__pycache__/recipe_processes.cpython-313.pyc index 05e07d39b460da0ac9dd931e055119989abd8b59..bdd998f3e96e64aa72ac4e69415c277be8d1a949 100644 GIT binary patch delta 1327 zcmYjQO>7%Q6rSt#~xY*s!Cj#v6CuKns2^&@7p(T z=gs^OzdC5!w%IIzSl>^}=e}IB)#0(FKd(S(y$pYWc#`RZUAWAMFoXx)0sPQtG-@W* znhxU|OcnOv2s;9Mi9o`}+5nlY!J@95DwRjz+WnSBuel}Qhga=KxHV3#RE91$Rg){k}k&al^j9K>mU z6+`QH(2Z|eZ~L3B3d(AFHdmQ1X_-p3ypY%3B%g#Y*ksEI!c1i7i|f~H5JDfmZa<74 z+wZ`}`uC1;IA{d^@XGXBZ#^_b1GXqw@~*L zYpn1G4!Hsn@3@#kog{CLC9rEYLKrf(AK|mEv(S$>TuZ{|0BB~_te7|wQOp!I3!d!^ z2Q8EjLzPk35k})@Xq_!f+vzEN$}2oosFq@+<6 z7b%;S!1QGRcpw3lecnZ>)kU$@ML&May)W$34HD1|T1Nqdz>H@n3FrXX5mK6i^n6!+ z)7||_a5t_xc7JZzpc}e@B5ICt2hA1P;RRR#uQA=A0ObJg@Vq&~R7*wFLlQL2^Obxt zQ?1U=AyN=PZ%`+nD`^)p1#(+T2>Gc8Ai5p0;g38YicvykI~t�~F#E2C+$aDcuzG z{6aognIIYRNGG@LB)x1XMkVx~Av=XJ3gZ;^6Of(gb;`Rb7%7A)Oi)PT4}{*Ac~s7{ zD=ih9mKM`1)j|QCq8eH>>LbwP@(7iX?j&52B>bZgwd4ptLx#SH9|<2j8s5NiV(I)! zr0(sz#6Q4gZ}1&&@0NG;o_F-t+qILk_2ci>&YZ7JE^K;>L|}JcNiGXZsZG0dHL)68 zo2|T>FfX*?|UAB?hh28_ul z`)k6Ij2rI8Ek}pAyN6;&2e^%1NchG8M^J_*WWL>pgZL{k@ha_0lbxH-RoVwm4*=1g zwca9f(6DK=SemOY7%Q6rNe{uJ_l@CbriP8U}oK-3ZAszeDmhbdvD%* z`{npIWAYTFeh+=w9&$t^Eu4jIrU4Xl3_%TzK@Xkb zQhjKb4KrL?N)4bbM-2`k7d?fpGd}bd{W=^#(@a15kzTRcDB5REpf%T+xhLK3}k`Vyzt3sTNZ(&1JLYT*9i{V&Q9`cOy~U zVVN6dsZvF^#a-Bm^3r#V)rmu*X;~MpV8Y?g`h0I$h7kJDitD`dkmlEhKfH`?x$eND zy%l#H8XO4pZ6|jJ8~syt^`+I>1KRU|_S~l<_vpyZ-2KVf#^mfzlgawk%sqPUH)lta zlWvOZ;)YC!ur6#!O?TItc;pS%hc7h5c%6&ddg7|vTnS!<@pY#1%oGccooQMh?q$>lheH6vY9(g84ki+;0$GS z7>WV0Ri}N{6%{MubG}799qn1s0M19TBVx$F%pOjJ)<80kv@R8fNT*obL`O;`bWj6} zUW?LzMOBsaZcS^zfZ4z^%e3@tI43BJ>H&tQBE==*wf`wE z!Xh~5=mABjtH|ZK(#w~sg{8M^wbFvAVK*l6)dFUSaG5|7ed>8nJ&mdEGRKH!oIs4g z88qlUHDkU^IGG32g`vfn%jNQXE`Qxj5Zx$&OBi(7oFSal$7Big5qOorYv>E_U{J7= zv8uIV(HtV`5eybd1I6Vor1<;_?li~~?E?M{SHUrhHsu&9`x4G$3i1YgfWGyGPIL0w zI|p3gNDXi64K>mXkJKX<8sS%(YM_ayakdc{Yig0Ezk4hFnTRG--FO@XylZW7!*xtE z{J^0U+InNxc_3YSI0BU5lNSJ|{C_Tw#IC=7k3*p3;Gd79pd;`IIQW64)NwPpp4_;M zzEX!{41FicCK&n$w~!F1yMizyGj~0a8IIWp5c7SG!KlMGb+KL8iBJ4zCrO=K^g=0L zZP%5&+9W+N$yAtRmRsEP((*#BTsUtQ@D^7CSmS8PAJFC?ya;y|{s1<4_%0QJp54R~ IfEWAvKZ4a7tpET3 diff --git a/application/recipes/database_recipes.py b/application/recipes/database_recipes.py index 18251a4..6d29857 100644 --- a/application/recipes/database_recipes.py +++ b/application/recipes/database_recipes.py @@ -225,6 +225,34 @@ def selectItemTupleByUUID(site, payload, convert=True, conn=None): return selected except Exception as error: raise postsqldb.DatabaseError(error, payload, sql) + +def selectConversionTuple(site, payload, convert=True, conn=None): + """payload=(item_id, uom_id)""" + selected = () + self_conn = False + sql = f"SELECT conversions.conv_factor FROM {site}_conversions conversions WHERE item_id = %s AND uom_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.close() + + return selected + except Exception as error: + raise postsqldb.DatabaseError(error, payload, sql) + def insertCostLayersTuple(site, payload, convert=True, conn=None): cost_layer = () diff --git a/application/recipes/recipe_processes.py b/application/recipes/recipe_processes.py index 0894b20..5bd19a1 100644 --- a/application/recipes/recipe_processes.py +++ b/application/recipes/recipe_processes.py @@ -46,9 +46,9 @@ def postTransaction(site_name, user_id, data: dict, conn=None): 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) @@ -58,7 +58,6 @@ def postTransaction(site_name, user_id, data: dict, conn=None): 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: @@ -82,19 +81,17 @@ def postTransaction(site_name, user_id, data: dict, conn=None): 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) - + transaction_tuple = 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!"} + return conn def process_recipe_receipt(site_name, user_id, data:dict, conn=None): """data={'recipe_id': recipe_id}""" @@ -110,29 +107,28 @@ def process_recipe_receipt(site_name, user_id, data:dict, conn=None): 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'])""" + rp_item_uom = item['uom']['id'] item_stuff = database_recipes.selectItemTupleByUUID(site_name, (item['item_uuid'],), conn=conn) - print(item_stuff) + conv_factor = database_recipes.selectConversionTuple(site_name, (item_stuff['item_id'], rp_item_uom)) + qty = float(item['qty']) / float(conv_factor['conv_factor']) 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'], + 'quantity': 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.commit() conn.close() return False, str(error) diff --git a/application/recipes/static/js/recipeEditHandler.js b/application/recipes/static/js/recipeEditHandler.js index cae1efb..0213a97 100644 --- a/application/recipes/static/js/recipeEditHandler.js +++ b/application/recipes/static/js/recipeEditHandler.js @@ -115,7 +115,7 @@ async function openLineItemModal(item){ } async function deleteLineItem(index){ - const response = await fetch(`/recipe/deleteRecipeItem`, { + const response = await fetch(`/recipes/deleteRecipeItem`, { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/application/recipes/static/js/recipeViewHandler.js b/application/recipes/static/js/recipeViewHandler.js index 6ad1f26..00512f0 100644 --- a/application/recipes/static/js/recipeViewHandler.js +++ b/application/recipes/static/js/recipeViewHandler.js @@ -45,7 +45,7 @@ async function replenishIngrediantsTable() { } else if (qty_needed > quantity_on_hand && item_type === "sku") { markerCell.innerHTML = `Missing` } else { - markerCell.innerHTML = "" + markerCell.innerHTML = `Untracked` } let nameCell = document.createElement('td') @@ -140,4 +140,6 @@ async function receiptRecipe(){ pos: 'top-right', timeout: 5000 }); + UIkit.modal(document.getElementById('receiptRecipeModal')).hide(); + } \ No newline at end of file diff --git a/logs/database.log b/logs/database.log index 944cc53..5f2d138 100644 --- a/logs/database.log +++ b/logs/database.log @@ -139,4 +139,10 @@ 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;') \ No newline at end of file + 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;') +2025-08-10 10:17:09.169270 --- ERROR --- DatabaseError(message='syntax error at or near ","LINE 1: ... test_conversions conversions WHERE part_id = 2016, uom_id =... ^', + payload=(2016, 6), + sql='SELECT conversions.conv_factor FROM test_conversions conversions WHERE part_id = %s, uom_id = %s;') +2025-08-10 10:18:03.658146 --- ERROR --- DatabaseError(message='column "part_id" does not existLINE 1: ...nv_factor FROM test_conversions conversions WHERE part_id = ... ^', + payload=(2016, 6), + sql='SELECT conversions.conv_factor FROM test_conversions conversions WHERE part_id = %s AND uom_id = %s;') \ No newline at end of file