From 8b265bb4f0fff9640ceda8260b88a00179d2ceb2 Mon Sep 17 00:00:00 2001 From: Jadowyne Ulve Date: Sat, 9 Aug 2025 14:18:27 -0500 Subject: [PATCH] updated receipts linking to be barcode based --- .../__pycache__/receipts_api.cpython-313.pyc | Bin 19144 -> 19871 bytes .../receipts_processes.cpython-313.pyc | Bin 8017 -> 9480 bytes application/receipts/receipts_api.py | 13 ++ application/receipts/receipts_processes.py | 49 ++++- .../receipts/static/js/receiptHandler.js | 175 +++++++++++++++++- application/receipts/templates/receipt.html | 32 ++++ 6 files changed, 267 insertions(+), 2 deletions(-) diff --git a/application/receipts/__pycache__/receipts_api.cpython-313.pyc b/application/receipts/__pycache__/receipts_api.cpython-313.pyc index 6970a5625e42704fd65c47c50e95d5e44d2d3969..e57363d897b8644bb7fdcc0750c73e699e2a65bc 100644 GIT binary patch delta 806 zcmZ9KUr19?9LMjucXzvUZPwDQ&C&%)n@y&&<%*e3R1}OD{vqojhF)~|XSd&`Q4f|+ z`5=)T{6jv77@_tD^qa`k~$Tjb91gq4UV79NnR!_Xe>kQ*a?-R+rthFaDL?A^7{q2eOaMVB02tB+&` z9o$7Jqd2aK7ipH$PY4YbIeDKze-_s3z{ZB5g@!%3*Co(kr;H&bDiG<5LpK_@0~pag z(8G5BeURp8LtO3!9rIm0oW@KGLyTu|IN%6tQrZ6<9Bwmr9aF$?gZrlCr0ko6LxYo+ zEnQ7PS~8AwCQbPXQ~s98u`L}<=j2VE+sttf>(gf2q-)cBY*?3;>`BR;klb@^FRjU7 zC=m>81)H{|X13UVD=jT9RF_MZiAdQF@62`F9jYUZZXigN{@DpiG75AsC;~4FK_;v z_b4C_MC2oY84Y6US(TWeSA z@d5x#16U5g5&)hQ))2T5;1cs3RHELyMJdo5?db23&p?8C_-Dmt)Ydwq;C3z6E&4Zz kd4mMr6GM{NH;Mf#uO}DCuE6nmh>9Hz_IE7m`38mj0;4Z*=%mA!NfRma)P-A>tvwlmCe28rCG?#I~WPN9OZjizvP7twca-_2i z>wX}UZF7~gFEi^gAd_eE8Mh~lI+HiLn{uxMsoDr4W>5a;zSkKP97Q0X7lC|R1aedn y$etpQ8ATx7D;bLHL2Owdaf`zyH$SB`C)KX#Jdn!>#Kl>gzj^R7Z?^JDWdr~&0CTqh diff --git a/application/receipts/__pycache__/receipts_processes.cpython-313.pyc b/application/receipts/__pycache__/receipts_processes.cpython-313.pyc index 63536cd9c192c2d4cf2cebe60065fdbbbcd2d2c4..159121e1820ad414f97c64a4ccc1074fd6dc73c6 100644 GIT binary patch delta 2124 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 diff --git a/application/receipts/receipts_api.py b/application/receipts/receipts_api.py index 2d8ccee..f51f2cf 100644 --- a/application/receipts/receipts_api.py +++ b/application/receipts/receipts_api.py @@ -197,6 +197,19 @@ def postLinkedItem(): return jsonify({'error': False, "message": "Line Saved Succesfully"}) return jsonify({'error': True, "message": "Something went wrong while saving line!"}) +@receipt_api.route('/api/saveBarcodeLink', methods=["POST"]) +@access_api.login_required +def saveBarcodeLink(): + if request.method == "POST": + print(request.get_json()) + site_name = session['selected_site'] + user_id = session['user_id'] + receipts_processes.linkBarcodeToItem(site_name, user_id, request.get_json()) + #receipts_processes.linkItem(site_name, user_id, payload) + + return jsonify({'error': False, "message": "Line Saved Succesfully"}) + return jsonify({'error': True, "message": "Something went wrong while saving line!"}) + @receipt_api.route('/api/resolveLine', methods=["POST"]) @access_api.login_required def resolveLine(): diff --git a/application/receipts/receipts_processes.py b/application/receipts/receipts_processes.py index 4132e5c..f49ae11 100644 --- a/application/receipts/receipts_processes.py +++ b/application/receipts/receipts_processes.py @@ -5,7 +5,7 @@ import PIL import openfoodfacts import psycopg2 import datetime - +import pprint # APPLICATION IMPORTS from application.receipts import receipts_database from application import database_payloads @@ -23,6 +23,52 @@ def create_pdf_preview(pdf_path, output_path, size=(600, 400)): img.save(output_path) return file_name + '.jpg' +def linkBarcodeToItem(site, user_id, data, conn=None): + self_conn = False + if not conn: + database_config = config.config() + conn = psycopg2.connect(**database_config) + conn.autocommit = False + self_conn = True + + receipt_item_id = data['receipt_item_id'] + payload = data['payload'] + item_uuid = payload['item_uuid'] + + receipt_item = receipts_database.selectReceiptItemsTuple(site, (receipt_item_id,)) + item = receipts_database.getItemAllByUUID(site, (item_uuid,)) + + barcode_tuple = database_payloads.BarcodesPayload( + barcode=receipt_item['barcode'], + item_uuid=item_uuid, + in_exchange=payload['in_exchange'], + out_exchange=payload['out_exchange'], + descriptor=payload['descriptor'] + ) + + receipts_database.insertBarcodesTuple(site, barcode_tuple.payload(), conn=conn) + + new_data = receipt_item['data'] + new_quantity = float(receipt_item['qty'] * payload['in_exchange']) + new_data['expires'] = item['food_info']['expires'] + receipts_item_update = {'id': receipt_item_id, 'update': { + 'type': 'sku', + 'name': item['item_name'], + 'uom': item['item_info']['uom']['id'], + 'item_uuid': item['item_uuid'], + 'data': new_data, + 'qty': new_quantity + }} + + receipts_database.updateReceiptItemsTuple(site, receipts_item_update, conn=conn) + + if self_conn: + conn.commit() + conn.close() + return False + + return conn + def linkItem(site, user_id, data, conn=None): """ this is a higher level function used to process a new item into the system, link it to another item, and update the receipt_item to the new linked item data. @@ -119,6 +165,7 @@ def postLine(site, user_id, data, conn=None): expiration = None #if receipt_item['type'] == 'sku': + # receipts_database.get # linked_item = receipts_database.getLinkedItemByBarcode(site, (receipt_item['barcode'], ), conn=conn) # if len(linked_item) > 1: # conv_factor = linked_item['conv_factor'] diff --git a/application/receipts/static/js/receiptHandler.js b/application/receipts/static/js/receiptHandler.js index 988f4dc..9358f71 100644 --- a/application/receipts/static/js/receiptHandler.js +++ b/application/receipts/static/js/receiptHandler.js @@ -118,7 +118,7 @@ async function replenishLinesTable(receipt_items) { linkOp.setAttribute('class', 'uk-button uk-button-small uk-button-default') linkOp.setAttribute('uk-icon', 'icon: link') linkOp.onclick = async function () { - await openLinksSelectModal(receipt_items[i].id) + await openItemBarcodeSelectModal(receipt_items[i].id) } let editOp = document.createElement('a') @@ -870,4 +870,177 @@ async function updateLinksPaginationElement() { console.log(nextElement.innerHTML) } paginationElement.append(nextElement) +} + +// Select Barcode Link Functions +var ItemBarcodeSelectModal_limit = 50 +var ItemBarcodeSelectModal_page = 1 +var ItemBarcodeSelectModal_page_end = 1 +var selectedReceiptItemID = 0 + +async function openItemBarcodeSelectModal(receipt_item_id) { + selectedReceiptItemID = receipt_item_id + await setupItemsBarcodeSelect() + UIkit.modal(document.getElementById("ItemBarcodeSelectModal")).show(); +} + +async function setupItemsBarcodeSelect() { + let items = await getItemsForModal() + await generateItemsBarcodeSelectTable(items) + await updateItemsBarcodeSelectPagination() +} + +async function generateItemsBarcodeSelectTable(items) { + let ItemBarcodeSelectTable = document.getElementById('ItemBarcodeSelectTable') + ItemBarcodeSelectTable.innerHTML = "" + + for(let i = 0; i < items.length; i++){ + let tableRow = document.createElement('tr') + + let nameCell = document.createElement('td') + nameCell.innerHTML = items[i].item_name + + let inCell = document.createElement('td') + inCell.innerHTML = `` + + let outCell = document.createElement('td') + outCell.innerHTML = `` + + let descriptorCell = document.createElement('td') + descriptorCell.innerHTML = `` + + + let opCell = document.createElement('td') + + let selectButton = document.createElement('button') + selectButton.setAttribute('class', 'uk-button uk-button-small uk-button-primary') + selectButton.innerHTML = "Select" + selectButton.onclick = async function() { + let payload = { + item_uuid: items[i].item_uuid, + in_exchange: parseFloat(document.getElementById(`${items[i].item_uuid}_in`).value), + out_exchange: parseFloat(document.getElementById(`${items[i].item_uuid}_out`).value), + descriptor: document.getElementById(`${items[i].item_uuid}_descriptor`).value + } + await updateReceiptItemBarcode(payload) + } + + opCell.append(selectButton) + + tableRow.append(nameCell, inCell, outCell, descriptorCell, opCell) + + ItemBarcodeSelectTable.append(tableRow) + } +} + + +async function getItemsForModal() { + const url = new URL('/receipts/api/getItems', window.location.origin); + url.searchParams.append('page', ItemBarcodeSelectModal_page); + url.searchParams.append('limit', ItemBarcodeSelectModal_limit); + const response = await fetch(url); + data = await response.json(); + ItemBarcodeSelectModal_page_end = data.end + let items = data.items; + return items; +} + +async function updateItemsBarcodeSelectPagination() { + let paginationElement = document.getElementById("ItemBarcodeSelectModalPage"); + paginationElement.innerHTML = ""; + // previous + let previousElement = document.createElement('li') + if(pagination_current<=1){ + previousElement.innerHTML = ``; + previousElement.classList.add('uk-disabled'); + }else { + previousElement.innerHTML = ``; + } + paginationElement.append(previousElement) + + //first + let firstElement = document.createElement('li') + if(pagination_current<=1){ + firstElement.innerHTML = `1`; + firstElement.classList.add('uk-disabled'); + }else { + firstElement.innerHTML = `1`; + } + paginationElement.append(firstElement) + + // ... + if(pagination_current-2>1){ + let firstDotElement = document.createElement('li') + firstDotElement.classList.add('uk-disabled') + firstDotElement.innerHTML = ``; + paginationElement.append(firstDotElement) + } + // last + if(ItemBarcodeSelectModal_page-2>0){ + let lastElement = document.createElement('li') + lastElement.innerHTML = `${ItemBarcodeSelectModal_page-1}` + paginationElement.append(lastElement) + } + // current + if(ItemBarcodeSelectModal_page!=1 && ItemBarcodeSelectModal_page != ItemBarcodeSelectModal_page_end){ + let currentElement = document.createElement('li') + currentElement.innerHTML = `
  • ${ItemBarcodeSelectModal_page}
  • ` + paginationElement.append(currentElement) + } + // next + if(ItemBarcodeSelectModal_page+2${ItemBarcodeSelectModal_page+1}` + paginationElement.append(nextElement) + } + // ... + if(ItemBarcodeSelectModal_page+2<=ItemBarcodeSelectModal_page_end){ + let secondDotElement = document.createElement('li') + secondDotElement.classList.add('uk-disabled') + secondDotElement.innerHTML = ``; + paginationElement.append(secondDotElement) + } + //end + let endElement = document.createElement('li') + if(pagination_current>=ItemBarcodeSelectModal_page_end){ + endElement.innerHTML = `${ItemBarcodeSelectModal_page_end}`; + endElement.classList.add('uk-disabled'); + }else { + endElement.innerHTML = `${ItemBarcodeSelectModal_page_end}`; + } + paginationElement.append(endElement) + //next button + let nextElement = document.createElement('li') + if(pagination_current>=ItemBarcodeSelectModal_page_end){ + nextElement.innerHTML = ``; + nextElement.classList.add('uk-disabled'); + }else { + nextElement.innerHTML = ``; + console.log(nextElement.innerHTML) + } + paginationElement.append(nextElement) +} + +async function ItemBarcodeSelectModalPage(pageNumber){ + ItemBarcodeSelectModal_page = pageNumber; + await setupItemsBarcodeSelect() +} + +async function updateReceiptItemBarcode(payload) { + + UIkit.modal(document.getElementById("ItemBarcodeSelectModal")).hide(); + + const response = await fetch(`/receipts/api/saveBarcodeLink`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + receipt_item_id: selectedReceiptItemID, + payload: payload + }), + }); + await refreshReceipt() + + } \ No newline at end of file diff --git a/application/receipts/templates/receipt.html b/application/receipts/templates/receipt.html index 955f5b8..c38d062 100644 --- a/application/receipts/templates/receipt.html +++ b/application/receipts/templates/receipt.html @@ -296,6 +296,38 @@ + +
    +
    +

    Select Item

    +

    Select an Item from the system...

    + + + + + + + + + + + + + +
    NameIn ExchangeOut ExchangeDescriptorOperations
    +
    +