migrated more receipts module api

This commit is contained in:
Jadowyne Ulve 2025-08-02 08:09:14 -05:00
parent ee2bdda226
commit cb240f7e97
7 changed files with 209 additions and 40 deletions

View File

@ -104,18 +104,17 @@ def getReceipt():
return jsonify({'receipt': record, 'error': False, "message": "Get Receipts Successful!"})
return jsonify({'receipt': record, 'error': True, "message": "Something went wrong while getting receipts!"})
# added to database
@receipt_api.route('/api/addReceipt', methods=["POST", "GET"])
def addReceipt():
if request.method == "GET":
user_id = session['user_id']
site_name = session['selected_site']
database_config = config()
with psycopg2.connect(**database_config) as conn:
receipt = MyDataclasses.ReceiptPayload(
receipt_id=f"PR-{database.request_receipt_id(conn, site_name)}",
receipt = database_payloads.ReceiptPayload(
receipt_id=f"PR-{receipts_database.requestNextReceiptID(site_name)}",
submitted_by=user_id
)
database.insertReceiptsTuple(conn, site_name, receipt.payload())
receipts_database.insertReceiptsTuple(site_name, receipt.payload())
return jsonify({'error': False, "message": "Receipt Added Successful!"})
return jsonify({'error': True, "message": "Something went wrong while adding receipt!"})
@ -145,41 +144,37 @@ def addSKULine():
return jsonify({'error': False, "message": "Line added Succesfully"})
return jsonify({'error': True, "message": "Something went wrong while add SKU line!"})
# Added to Database
@receipt_api.route('/api/deleteLine', methods=["POST"])
def deleteLine():
if request.method == "POST":
line_id = int(request.get_json()['line_id'])
site_name = session['selected_site']
database_config = config()
with psycopg2.connect(**database_config) as conn:
database.deleteReceiptItemsTuple(conn, site_name, (line_id, ))
receipts_database.deleteReceiptItemsTuple(site_name, (line_id, ))
return jsonify({'error': False, "message": "Line Deleted Succesfully"})
return jsonify({'error': True, "message": "Something went wrong while deleting line!"})
# Added to Database
@receipt_api.route('/api/denyLine', methods=["POST"])
def denyLine():
if request.method == "POST":
line_id = int(request.get_json()['line_id'])
site_name = session['selected_site']
database_config = config()
with psycopg2.connect(**database_config) as conn:
database.__updateTuple(conn, site_name, f"{site_name}_receipt_items", {'id': line_id, 'update': {'status': 'Denied'}})
receipts_database.updateReceiptItemsTuple(site_name, {'id': line_id, 'update': {'status': 'Denied'}})
return jsonify({'error': False, "message": "Line Denied Succesfully"})
return jsonify({'error': True, "message": "Something went wrong while denying line!"})
# Added to database
@receipt_api.route('/api/saveLine', methods=["POST"])
def saveLine():
if request.method == "POST":
line_id = int(request.get_json()['line_id'])
payload = request.get_json()['payload']
site_name = session['selected_site']
database_config = config()
with psycopg2.connect(**database_config) as conn:
receipt_item = database.__selectTuple(conn, site_name, f"{site_name}_receipt_items", (line_id, ), convert=True)
receipt_item = receipts_database.selectReceiptItemsTuple(site_name, (line_id, ))
if 'api_data' in receipt_item['data'].keys():
payload['data']['api_data'] = receipt_item['data']['api_data']
database.__updateTuple(conn, site_name, f"{site_name}_receipt_items", {'id': line_id, 'update': payload})
receipts_database.updateReceiptItemsTuple(site_name, {'id': line_id, 'update': payload})
return jsonify({'error': False, "message": "Line Saved Succesfully"})
return jsonify({'error': True, "message": "Something went wrong while saving line!"})
@ -377,9 +372,12 @@ def uploadFile(receipt_id):
return jsonify({})
# Does not need to be added to Database
@receipt_api.route('/api/getFile/<file_name>')
def getFile(file_name):
return send_from_directory('static/files/receipts', file_name)
path_ = current_app.config['FILES_FOLDER'] + "/receipts"
print(path_)
return send_from_directory(path_, file_name)
@receipt_api.route('/api/checkAPI', methods=["POST"])
def checkAPI():
@ -390,7 +388,7 @@ def checkAPI():
database_config = config()
with psycopg2.connect(**database_config) as conn:
print(barcode, line_id)
api_response, api_data = get_open_facts(barcode)
api_response, api_data = receipts_processes.get_open_facts(barcode)
if api_response:
receipt_item = database.__selectTuple(conn, site_name, f"{site_name}_receipt_items", (line_id, ), convert=True)
item_data = receipt_item['data']
@ -406,15 +404,3 @@ def checkAPI():
return jsonify({'error': True, "message": "Item not in WorldFoodFacts!"})
return jsonify({'error': False, "message": "Line Saved Succesfully"})
return jsonify({'error': True, "message": "Something went wrong while saving line!"})
open_food_api = openfoodfacts.API(user_agent="MyAwesomeApp/1.0")
open_food_enabled = True
def get_open_facts(barcode):
if open_food_enabled:
barcode: str = barcode.replace('%', "")
data = open_food_api.product.get(barcode)
if data != None:
return True, data
return False, {}

View File

@ -1,9 +1,48 @@
import psycopg2
import config
from application import postsqldb
def requestNextReceiptID(site_name, conn=None):
"""gets the next id for receipts_id, currently returns a 8 digit number
Args:
site (str): site to get the next id for
Returns:
json: receipt_id, message, error keys
"""
next_receipt_id = None
self_conn = False
sql = f"SELECT receipt_id FROM {site_name}_receipts ORDER BY id DESC LIMIT 1;"
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)
next_receipt_id = cur.fetchone()
if next_receipt_id == None:
next_receipt_id = "00000001"
else:
next_receipt_id = next_receipt_id[0]
next_receipt_id = int(next_receipt_id.split("-")[1]) + 1
y = str(next_receipt_id)
len_str = len(y)
x = "".join(["0" for _ in range(8 - len_str)])
next_receipt_id = x + y
if self_conn:
conn.commit()
conn.close()
return next_receipt_id
except (Exception, psycopg2.DatabaseError) as error:
raise postsqldb.DatabaseError(error, payload=(), sql=sql)
def getItemsWithQOH(site, payload, convert=True, conn=None):
recordset = []
count = 0
@ -69,7 +108,59 @@ def getItemAllByID(site, payload, convert=True, conn=None):
except (Exception, psycopg2.DatabaseError) as error:
raise postsqldb.DatabaseError(error, payload, getItemAllByID_sql)
def selectReceiptItemsTuple(site, payload, convert=True, conn=None):
selected = ()
self_conn = False
sql = f"SELECT * FROM {site}_receipt_items 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)
if rows and not convert:
selected = rows
if self_conn:
conn.close()
return selected
except (Exception, psycopg2.DatabaseError) as error:
raise postsqldb.DatabaseError(error, payload, sql)
def deleteReceiptItemsTuple(site, payload, convert=True, conn=None):
deleted = ()
self_conn = False
sql = f"WITH deleted_rows AS (DELETE FROM {site}_receipt_items 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 insertReceiptItemsTuple(site, payload, convert=True, conn=None):
receipt_item = ()
@ -98,3 +189,77 @@ def insertReceiptItemsTuple(site, payload, convert=True, conn=None):
return receipt_item
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def insertReceiptsTuple(site, payload, convert=True, conn=None):
receipt = ()
self_conn = False
with open(f"application/receipts/sql/insertReceiptsTuple.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:
receipt = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
receipt = rows
if self_conn:
conn.commit()
conn.close()
return receipt
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)
def updateReceiptItemsTuple(site, payload, convert=True, conn=None):
"""_summary_
Args:
conn (_T_connector@connect): Postgresql Connector
site (str):
payload (dict): {'id': row_id, 'update': {... column_to_update: value_to_update_to...}}
convert (bool, optional): determines if to return tuple as dictionary. Defaults to True.
Raises:
DatabaseError:
Returns:
tuple or dict: updated tuple
"""
updated = ()
self_conn = False
set_clause, values = postsqldb.updateStringFactory(payload['update'])
values.append(payload['id'])
sql = f"UPDATE {site}_receipt_items 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:
updated = postsqldb.tupleDictionaryFactory(cur.description, rows)
elif rows and not convert:
updated = rows
if self_conn:
conn.commit()
conn.close()
return updated
except Exception as error:
raise postsqldb.DatabaseError(error, payload, sql)

View File

@ -1,6 +1,7 @@
import pymupdf
import os
import PIL
import openfoodfacts
def create_pdf_preview(pdf_path, output_path, size=(600, 400)):
pdf = pymupdf.open(pdf_path)
@ -12,3 +13,16 @@ def create_pdf_preview(pdf_path, output_path, size=(600, 400)):
img.thumbnail(size)
img.save(output_path)
return file_name + '.jpg'
# OPEN FOOD FACTS API INTEGRATION
open_food_api = openfoodfacts.API(user_agent="MyAwesomeApp/1.0")
open_food_enabled = True
def get_open_facts(barcode):
if open_food_enabled:
barcode: str = barcode.replace('%', "")
data = open_food_api.product.get(barcode)
if data != None:
return True, data
return False, {}

View File

@ -0,0 +1,4 @@
INSERT INTO %%site_name%%_receipts
(receipt_id, receipt_status, date_submitted, submitted_by, vendor_id, files)
VALUES (%s, %s, %s, %s, %s, %s)
RETURNING *;

View File

@ -250,7 +250,7 @@ async function viewFile(source) {
document.getElementById('filenameiframemodal').innerHTML = source
let iframe = document.createElement('iframe')
iframe.src = `/receipt/getFile/${source}`
iframe.src = `/receipts/api/getFile/${source}`
iframe.width = "100%"
iframe.style.height = "100%"

View File

@ -91,12 +91,12 @@
<div class="uk-container">
<div class="uk-section">
<div uk-grid>
<div class="uk-width-1-2@m">
<!-- div class="uk-width-1-2@m">
<ul class="uk-iconnav uk-flex-center uk-flex-left@m">
<li><a href="#" uk-icon="icon: plus">Open Receipt</a></li>
<li><a href="#" uk-icon="icon: cloud-download">download</a></li>
</ul>
</div>
</div -->
<div class="uk-width-1-2@m">
<nav aria-label="Pagination">
<ul id="paginationElement" class="uk-pagination uk-flex-center uk-flex-right@m" uk-margin>

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB