diff --git a/data/WiredTiger b/data/WiredTiger new file mode 100644 index 0000000..1bc57ba --- /dev/null +++ b/data/WiredTiger @@ -0,0 +1,2 @@ +WiredTiger +WiredTiger 11.2.0: (November 10, 2022) diff --git a/data/WiredTiger.lock b/data/WiredTiger.lock new file mode 100644 index 0000000..3d84206 --- /dev/null +++ b/data/WiredTiger.lock @@ -0,0 +1 @@ +WiredTiger lock file diff --git a/data/WiredTiger.turtle b/data/WiredTiger.turtle new file mode 100644 index 0000000..10b0e40 --- /dev/null +++ b/data/WiredTiger.turtle @@ -0,0 +1,6 @@ +WiredTiger version string +WiredTiger 11.2.0: (November 10, 2022) +WiredTiger version +major=11,minor=2,patch=0 +file:WiredTiger.wt +access_pattern_hint=none,allocation_size=4KB,app_metadata=,assert=(commit_timestamp=none,durable_timestamp=none,read_timestamp=none,write_timestamp=off),block_allocation=best,block_compressor=,cache_resident=false,checksum=on,collator=,columns=,dictionary=0,encryption=(keyid=,name=),format=btree,huffman_key=,huffman_value=,id=0,ignore_in_memory_cache_size=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=S,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=0,log=(enabled=true),memory_page_image_max=0,memory_page_max=5MB,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,readonly=false,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,tiered_object=false,tiered_storage=(auth_token=,bucket=,bucket_prefix=,cache_directory=,local_retention=300,name=,object_target_size=0),value_format=S,verbose=[],version=(major=1,minor=1),write_timestamp_usage=none,checkpoint=(WiredTigerCheckpoint.308=(addr="018881e461e58ddb8981e4ee482c7d8a81e4687addcb808080e29fc0e22fc0",order=308,time=1714543150,size=24576,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=8,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=886,run_write_gen=870)),checkpoint_backup_info=,checkpoint_lsn=(38,8064) diff --git a/data/WiredTiger.wt b/data/WiredTiger.wt new file mode 100644 index 0000000..4c86e56 Binary files /dev/null and b/data/WiredTiger.wt differ diff --git a/data/WiredTigerHS.wt b/data/WiredTigerHS.wt new file mode 100644 index 0000000..3f019cb Binary files /dev/null and b/data/WiredTigerHS.wt differ diff --git a/data/_mdb_catalog.wt b/data/_mdb_catalog.wt new file mode 100644 index 0000000..c06acc5 Binary files /dev/null and b/data/_mdb_catalog.wt differ diff --git a/data/collection-0-2112355434297019392.wt b/data/collection-0-2112355434297019392.wt new file mode 100644 index 0000000..031275a Binary files /dev/null and b/data/collection-0-2112355434297019392.wt differ diff --git a/data/collection-2-2112355434297019392.wt b/data/collection-2-2112355434297019392.wt new file mode 100644 index 0000000..72cf4ce Binary files /dev/null and b/data/collection-2-2112355434297019392.wt differ diff --git a/data/collection-4-2112355434297019392.wt b/data/collection-4-2112355434297019392.wt new file mode 100644 index 0000000..3f019cb Binary files /dev/null and b/data/collection-4-2112355434297019392.wt differ diff --git a/data/diagnostic.data/metrics.2024-05-01T00-18-06Z-00000 b/data/diagnostic.data/metrics.2024-05-01T00-18-06Z-00000 new file mode 100644 index 0000000..437e28f Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T00-18-06Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T00-53-57Z-00000 b/data/diagnostic.data/metrics.2024-05-01T00-53-57Z-00000 new file mode 100644 index 0000000..1186b95 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T00-53-57Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T01-22-41Z-00000 b/data/diagnostic.data/metrics.2024-05-01T01-22-41Z-00000 new file mode 100644 index 0000000..9033c54 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T01-22-41Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T01-26-11Z-00000 b/data/diagnostic.data/metrics.2024-05-01T01-26-11Z-00000 new file mode 100644 index 0000000..ff68e63 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T01-26-11Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T01-26-47Z-00000 b/data/diagnostic.data/metrics.2024-05-01T01-26-47Z-00000 new file mode 100644 index 0000000..0484cb2 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T01-26-47Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T01-27-29Z-00000 b/data/diagnostic.data/metrics.2024-05-01T01-27-29Z-00000 new file mode 100644 index 0000000..2ca196d Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T01-27-29Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T01-28-50Z-00000 b/data/diagnostic.data/metrics.2024-05-01T01-28-50Z-00000 new file mode 100644 index 0000000..a5ec1cd Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T01-28-50Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T01-31-04Z-00000 b/data/diagnostic.data/metrics.2024-05-01T01-31-04Z-00000 new file mode 100644 index 0000000..11eba93 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T01-31-04Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T01-44-28Z-00000 b/data/diagnostic.data/metrics.2024-05-01T01-44-28Z-00000 new file mode 100644 index 0000000..f0845bb Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T01-44-28Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T01-50-20Z-00000 b/data/diagnostic.data/metrics.2024-05-01T01-50-20Z-00000 new file mode 100644 index 0000000..c13e01c Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T01-50-20Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T03-07-02Z-00000 b/data/diagnostic.data/metrics.2024-05-01T03-07-02Z-00000 new file mode 100644 index 0000000..b146251 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T03-07-02Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T03-32-12Z-00000 b/data/diagnostic.data/metrics.2024-05-01T03-32-12Z-00000 new file mode 100644 index 0000000..24b9903 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T03-32-12Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T03-38-34Z-00000 b/data/diagnostic.data/metrics.2024-05-01T03-38-34Z-00000 new file mode 100644 index 0000000..f54872a Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T03-38-34Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T03-42-00Z-00000 b/data/diagnostic.data/metrics.2024-05-01T03-42-00Z-00000 new file mode 100644 index 0000000..75bc99c Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T03-42-00Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T03-44-47Z-00000 b/data/diagnostic.data/metrics.2024-05-01T03-44-47Z-00000 new file mode 100644 index 0000000..89439f6 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T03-44-47Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T03-53-51Z-00000 b/data/diagnostic.data/metrics.2024-05-01T03-53-51Z-00000 new file mode 100644 index 0000000..add5200 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T03-53-51Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-02-23Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-02-23Z-00000 new file mode 100644 index 0000000..1da107b Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-02-23Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-07-23Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-07-23Z-00000 new file mode 100644 index 0000000..9c5ad5c Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-07-23Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-23-58Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-23-58Z-00000 new file mode 100644 index 0000000..039fc69 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-23-58Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-29-47Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-29-47Z-00000 new file mode 100644 index 0000000..8c77b32 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-29-47Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-33-56Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-33-56Z-00000 new file mode 100644 index 0000000..f4341e2 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-33-56Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-37-53Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-37-53Z-00000 new file mode 100644 index 0000000..89b5850 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-37-53Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-44-18Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-44-18Z-00000 new file mode 100644 index 0000000..f4a1db7 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-44-18Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-46-37Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-46-37Z-00000 new file mode 100644 index 0000000..ccca0db Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-46-37Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-50-47Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-50-47Z-00000 new file mode 100644 index 0000000..0ffda85 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-50-47Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T04-57-26Z-00000 b/data/diagnostic.data/metrics.2024-05-01T04-57-26Z-00000 new file mode 100644 index 0000000..0ff4303 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T04-57-26Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-05-49Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-05-49Z-00000 new file mode 100644 index 0000000..04c8dc5 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-05-49Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-13-29Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-13-29Z-00000 new file mode 100644 index 0000000..000dd56 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-13-29Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-15-29Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-15-29Z-00000 new file mode 100644 index 0000000..f2a70ba Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-15-29Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-19-06Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-19-06Z-00000 new file mode 100644 index 0000000..33e4329 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-19-06Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-23-45Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-23-45Z-00000 new file mode 100644 index 0000000..6766588 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-23-45Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-24-55Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-24-55Z-00000 new file mode 100644 index 0000000..c384e5e Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-24-55Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-29-33Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-29-33Z-00000 new file mode 100644 index 0000000..d11727f Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-29-33Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-31-27Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-31-27Z-00000 new file mode 100644 index 0000000..eab1a8b Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-31-27Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-38-19Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-38-19Z-00000 new file mode 100644 index 0000000..a3ad21e Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-38-19Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-41-49Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-41-49Z-00000 new file mode 100644 index 0000000..d3867ba Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-41-49Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-49-04Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-49-04Z-00000 new file mode 100644 index 0000000..ad6cfab Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-49-04Z-00000 differ diff --git a/data/diagnostic.data/metrics.2024-05-01T05-54-39Z-00000 b/data/diagnostic.data/metrics.2024-05-01T05-54-39Z-00000 new file mode 100644 index 0000000..c573c35 Binary files /dev/null and b/data/diagnostic.data/metrics.2024-05-01T05-54-39Z-00000 differ diff --git a/data/index-1-2112355434297019392.wt b/data/index-1-2112355434297019392.wt new file mode 100644 index 0000000..7760fb3 Binary files /dev/null and b/data/index-1-2112355434297019392.wt differ diff --git a/data/index-3-2112355434297019392.wt b/data/index-3-2112355434297019392.wt new file mode 100644 index 0000000..ccd37d0 Binary files /dev/null and b/data/index-3-2112355434297019392.wt differ diff --git a/data/index-5-2112355434297019392.wt b/data/index-5-2112355434297019392.wt new file mode 100644 index 0000000..3f019cb Binary files /dev/null and b/data/index-5-2112355434297019392.wt differ diff --git a/data/index-6-2112355434297019392.wt b/data/index-6-2112355434297019392.wt new file mode 100644 index 0000000..3f019cb Binary files /dev/null and b/data/index-6-2112355434297019392.wt differ diff --git a/data/journal/WiredTigerLog.0000000038 b/data/journal/WiredTigerLog.0000000038 new file mode 100644 index 0000000..8e63266 Binary files /dev/null and b/data/journal/WiredTigerLog.0000000038 differ diff --git a/data/journal/WiredTigerPreplog.0000000001 b/data/journal/WiredTigerPreplog.0000000001 new file mode 100644 index 0000000..aa52a21 Binary files /dev/null and b/data/journal/WiredTigerPreplog.0000000001 differ diff --git a/data/journal/WiredTigerPreplog.0000000002 b/data/journal/WiredTigerPreplog.0000000002 new file mode 100644 index 0000000..aa52a21 Binary files /dev/null and b/data/journal/WiredTigerPreplog.0000000002 differ diff --git a/data/mongod.lock b/data/mongod.lock new file mode 100644 index 0000000..e69de29 diff --git a/data/sizeStorer.wt b/data/sizeStorer.wt new file mode 100644 index 0000000..b96c85c Binary files /dev/null and b/data/sizeStorer.wt differ diff --git a/data/storage.bson b/data/storage.bson new file mode 100644 index 0000000..276b694 Binary files /dev/null and b/data/storage.bson differ diff --git a/machine-learning-client/main.py b/machine-learning-client/main.py index 0d47d16..ad684b5 100644 --- a/machine-learning-client/main.py +++ b/machine-learning-client/main.py @@ -50,6 +50,24 @@ cxn = pymongo.MongoClient(os.getenv("MONGO_URI")) db = cxn[os.getenv("MONGO_DBNAME")] # store a reference to the database +# Load response1.json +with open("response1.json", "r") as f: + data = json.load(f) + +print('Receipt Keys:', data['receipts'][0].keys()) +items = data['receipts'][0]['items'] +print() +print(f"Your purchase at {data['receipts'][0]['merchant_name']}") + +for item in items: + print(f"{item['description']} - {data['receipts'][0]['currency']} {item['amount']}") +print("-" * 20) +print(f"Subtotal: {data['receipts'][0]['currency']} {data['receipts'][0]['subtotal']}") +print(f"Tax: {data['receipts'][0]['currency']} {data['receipts'][0]['tax']}") +print("-" * 20) +print(f"Total: {data['receipts'][0]['currency']} {data['receipts'][0]['total']}") +# print(data['receipts']) + @app.route('/predict', methods=['POST']) def pretdict_endpoint(): # Get the image data from the request @@ -91,33 +109,43 @@ def pretdict_endpoint(): # Return the inserted_id as a JSON response return jsonify({'_id': str(inserted_id)}) -def perform_ocr(Object_ID): - logger.debug("starting perform_ocr function...") # debug - url = "https://ocr.asprise.com/api/v1/receipt" - image_data = db.receipts.find_one({"_id": Object_ID})['image'] - file_path = f"receipt_{Object_ID}.jpg" # Set the file path to save the image - logger.debug("file path: %s", file_path) # debug - with open(file_path, "wb") as f: - f.write(image_data) - file_path = file_path.replace('\x00', '') # Remove any null bytes from the file path - - - # Get response (can only do this a couple times with the test API key) - res = requests.post(url, - data = { - 'api_key': 'TEST', - 'recognizer': 'auto', - 'ref_no': 'ocr_python_123' - }, - - files = { - 'file': open(file_path, "rb") - }) - - with open("response.json", "w") as f: - f.write(res.text) - - return res.json() +def perform_ocr(): + try: + json_file_path = os.path.join(os.path.dirname(__file__), 'response1.json') + with open(json_file_path, "r") as file: + data = json.load(file) + if 'receipts' in data and len(data['receipts']) > 0: + # Access the first receipt since the JSON has an array of receipts + receipt_data = data['receipts'][0] + + # Prepare the receipt format as needed, you might need to adjust based on your MongoDB schema + formatted_receipt = { + 'merchant_name': receipt_data.get('merchant_name'), + 'merchant_address': receipt_data.get('merchant_address'), + 'merchant_phone': receipt_data.get('merchant_phone'), + 'total': receipt_data.get('total'), + 'tax': receipt_data.get('tax'), + 'subtotal': receipt_data.get('subtotal'), + 'currency': receipt_data.get('currency'), + 'items': receipt_data.get('items', []), + 'date': receipt_data.get('date') + } + return formatted_receipt + else: + logger.error("No 'receipts' key found in JSON file or 'receipts' array is empty.") + return None + except FileNotFoundError: + logger.error(f"The file {json_file_path} was not found.") + return None + except json.JSONDecodeError as e: + logger.error(f"JSON decode error in file {json_file_path}: {str(e)}") + return None + except Exception as e: + logger.error(f"An unexpected error occurred: {str(e)}") + return None + + + if __name__ == '__main__': app.run(host='0.0.0.0', port=5002) # Run the app \ No newline at end of file diff --git a/web-app/app.py b/web-app/app.py index 3bb3b46..be78179 100644 --- a/web-app/app.py +++ b/web-app/app.py @@ -7,6 +7,7 @@ from dotenv import load_dotenv from bson import ObjectId import json +import uuid import logging @@ -30,16 +31,43 @@ cxn = pymongo.MongoClient(os.getenv("MONGO_URI")) db = cxn[os.getenv("MONGO_DBNAME")] # store a reference to the database +def perform_ocr(): + try: + json_file_path = os.path.join(os.path.dirname(__file__), 'response1.json') + with open(json_file_path, "r") as file: + data = json.load(file) + if 'receipts' in data and len(data['receipts']) > 0: + # Access the first receipt since the JSON has an array of receipts + receipt_data = data['receipts'][0] + + # Prepare the receipt format as needed, you might need to adjust based on your MongoDB schema + formatted_receipt = { + 'merchant_name': receipt_data.get('merchant_name'), + 'merchant_address': receipt_data.get('merchant_address'), + 'merchant_phone': receipt_data.get('merchant_phone'), + 'total': receipt_data.get('total'), + 'tax': receipt_data.get('tax'), + 'subtotal': receipt_data.get('subtotal'), + 'currency': receipt_data.get('currency'), + 'items': receipt_data.get('items', []), + 'date': receipt_data.get('date') + } + for item in receipt_data.get('items', []): + item['_id'] = str(uuid.uuid4()) # Assign a unique ID + return formatted_receipt + else: + logger.error("No 'receipts' key found in JSON file or 'receipts' array is empty.") + return None + except FileNotFoundError: + logger.error(f"The file {json_file_path} was not found.") + return None + except json.JSONDecodeError as e: + logger.error(f"JSON decode error in file {json_file_path}: {str(e)}") + return None + except Exception as e: + logger.error(f"An unexpected error occurred: {str(e)}") + return None -# Call the ML service to perform OCR on the receipt -def call_ml_service(Object_ID): - url = "http://machine-learning-client:5002/predict" - headers = {'Content-Type': 'application/json'} - data = json.dumps({"Object_ID": str(Object_ID)}) # Serialize the Object_ID into a JSON string - response = requests.post(url, data=data, headers=headers) - logger.debug(f"Response Status Code: {response.status_code}") - logger.debug(f"Response Text: {response.text}") - return response.json() #homepage -add receipt - history @@ -55,19 +83,16 @@ def upload_image(): file = request.files['image'] if file.filename == '': return jsonify({"error": "No selected file"}), 400 - if file: - image_data = file.read() - try: - result = db.receipts.insert_one({"image": image_data}) - inserted_id = str(result.inserted_id) - #logger.debug("YAY", inserted_id) - call_ml_service(inserted_id) - return redirect(url_for('numofpeople', receipt_id=inserted_id)) - except pymongo.errors.ServerSelectionTimeoutError as e: - logger.error("Could not connect to MongoDB: %s", str(e)) - return jsonify({"error": "Database connection failed"}), 503 - return jsonify({"error": "Unexpected error occurred"}), 500 + # Simulate OCR by loading data from a JSON file + receipt_data = perform_ocr() + if not receipt_data: + return jsonify({"error": "OCR simulation failed or JSON file is incorrect"}), 500 + + # Insert parsed data into MongoDB + result = db.receipts.insert_one(receipt_data) + inserted_id = str(result.inserted_id) + return redirect(url_for('numofpeople', receipt_id=inserted_id)) #( pull receipt from database ) @@ -98,6 +123,13 @@ def submit_people(receipt_id): return jsonify({"error": "Database connection failed"}), 503 #label appetizers +def is_valid_uuid(uuid_to_test, version=4): + try: + uuid_obj = uuid.UUID(uuid_to_test, version=version) + return str(uuid_obj) == uuid_to_test + except ValueError: + return False + @app.route('/select_appetizers/', methods=['GET', 'POST']) def select_appetizers(receipt_id): if request.method == 'POST': @@ -112,21 +144,29 @@ def select_appetizers(receipt_id): appetizer_ids = request.form.getlist('appetizers') logging.debug(f"Received appetizer IDs: {appetizer_ids}") - valid_ids = [id for id in appetizer_ids if ObjectId.is_valid(id) and id.strip() != ''] + valid_ids = [id for id in appetizer_ids if is_valid_uuid(id)] logging.debug(f"Valid appetizer IDs: {valid_ids}") + + # First reset all items to not be appetizers + db.receipts.update_one( + {'_id': ObjectId(receipt_id)}, + {'$set': {'items.$[].is_appetizer': False}} + ) if valid_ids: - object_ids = [ObjectId(id) for id in valid_ids] + # Update items where the ID matches any of the valid appetizer IDs db.receipts.update_many( - {'_id': ObjectId(receipt_id)}, - {'$set': {'items.$[elem].is_appetizer': True}}, - array_filters=[{'elem._id': {'$in': object_ids}}] + {'_id': ObjectId(receipt_id), 'items._id': {'$in': valid_ids}}, + {'$set': {'items.$.is_appetizer': True}} ) - db.receipts.update_one( - {'_id': ObjectId(receipt_id)}, - {'$set': {'items.$[elem].is_appetizer': False}}, - array_filters=[{'elem._id': {'$nin': object_ids}}] + # Reset is_appetizer for other items + db.receipts.update_many( + {'_id': ObjectId(receipt_id), 'items._id': {'$nin': valid_ids}}, + {'$set': {'items.$.is_appetizer': False}} ) + selected_appetizers = db.receipts.find_one({'_id': ObjectId(receipt_id)}, {'items': 1})['items'] + selected_appetizer_details = [(item['description'], item['amount']) for item in selected_appetizers if str(item['_id']) in valid_ids] + logger.debug(f"Selected Appetizers: {selected_appetizer_details}") else: db.receipts.update_one( {'_id': ObjectId(receipt_id)}, @@ -150,25 +190,27 @@ def allocateitems(receipt_id): # Clear previous allocations to avoid duplicates db.receipts.update_one({'_id': ObjectId(receipt_id)}, {'$unset': {'allocations': ''}}) - # Process form data and re-allocate items - allocations = {key: request.form.getlist(key) for key in request.form.keys()} - for name, items in allocations.items(): - if items: # Ensure we don't push empty lists - db.receipts.update_one( - {'_id': ObjectId(receipt_id)}, - {'$push': {'allocations': {'name': name, 'items': items}}} - ) + allocations = {} # This will store which items are chosen by which people + item_counts = {} # This will count how many people have chosen each item + + for key, values in request.form.lists(): + if key.startswith("item_"): + item_id = key[5:] # Remove 'item_' prefix + allocations[item_id] = values + item_counts[item_id] = len(values) + + logger.debug(f"Updated allocations: {allocations}") + logger.debug(f"Updated item counts: {item_counts}") + + # Store the updated allocations and counts in the database + db.receipts.update_one( + {'_id': ObjectId(receipt_id)}, + {'$set': {'allocations': allocations, 'item_counts': item_counts}} + ) return redirect(url_for('enter_tip', receipt_id=receipt_id)) - - # Fetch data to display form - receipt = db.receipts.find_one({'_id': ObjectId(receipt_id)}) - if not receipt: - return jsonify({"error": "Receipt not found"}), 404 - - people = receipt.get('names', []) - food_items = receipt.get('items', []) - - return render_template('allocateitems.html', people=people, food_items=food_items, receipt_id=receipt_id) + else: + receipt = db.receipts.find_one({'_id': ObjectId(receipt_id)}) + return render_template('allocateitems.html', people=receipt.get('names', []), food_items=receipt.get('items', []), receipt_id=receipt_id) @app.route('/enter_tip/', methods=['GET', 'POST']) def enter_tip(receipt_id): @@ -204,41 +246,77 @@ def calculate_bill(receipt_id): return jsonify({"error": "Receipt not found"}), 404 items = receipt.get('items', []) - allocations = receipt.get('allocations', []) + allocations = receipt.get('allocations', {}) + item_counts = receipt.get('item_counts', {}) + logger.debug(f"Allocations retrieved: {allocations}") + logger.debug(f"Item counts retrieved: {item_counts}") + + # Aggregate total appetizer cost + appetizer_items = [item for item in items if item.get('is_appetizer', False)] + logger.debug(f"Items marked as appetizers: {[(item['description'], item['amount']) for item in appetizer_items]}") + + appetizer_total = sum(item['amount'] for item in appetizer_items if item.get('is_appetizer', False)) + logger.debug(f"Total appetizer cost: {appetizer_total}") + tax = float(receipt.get('tax', 0.00)) subtotal = float(receipt.get('subtotal', 0.00)) - + + logger.debug(f"Subtotal and tax values: Subtotal={subtotal}, Tax={tax}") + + if not items or subtotal <= 0: + logger.error("No items found or subtotal is zero or negative.") + return jsonify({"error": "Invalid receipt data"}), 400 + payments = {name: 0 for name in receipt.get('names', [])} - appetizer_total = sum(item.get('amount', 0.00) for item in items if item.get('is_appetizer', False)) + num_people = len(receipt.get('names', [])) if num_people == 0: logger.error("Number of people is zero.") return jsonify({"error": "Number of people cannot be zero"}), 400 - appetizer_split = appetizer_total / num_people + if num_people > 0: + appetizer_cost_per_person = appetizer_total / num_people + else: + appetizer_cost_per_person = 0 + logger.debug(f"Appetizer cost per person: {appetizer_cost_per_person}") + appetizer_cost_per_person = appetizer_total / num_people if num_people else 0 for name in payments: - payments[name] += appetizer_split + payments[name] += appetizer_cost_per_person + logger.debug(f"Initial payment for {name}: {payments[name]}") + + # Calculate individual item costs and distribute them + for item_id, users in allocations.items(): + item = next((item for item in items if str(item['_id']) == item_id), None) + if item: + num_users = item_counts.get(item_id, 1) + cost_per_user = item['amount'] / num_users + for user in users: + payments[user] += cost_per_user + logger.debug(f"Allocating ${cost_per_user:.2f} to {user} for item {item['description']}") + else: + logger.debug(f"Item not found for ID: {item_id}") + + - # Calculating individual payments - for allocation in allocations: - for item_index in allocation.get('items', []): - if item_index.isdigit() and int(item_index) < len(items): - payments[allocation['name']] += items[int(item_index)].get('amount', 0.00) total_with_tax = subtotal + tax total_with_tip = total_with_tax * (1 + tip_percentage) + logger.debug(f"Total with tax: {total_with_tax}, Total with tip: {total_with_tip}") - # Distributing tax and tip across individuals + # Apply tax and tip proportionally + total_payment = 0 for name, payment in payments.items(): - if subtotal > 0: - person_share_before_tax = payment / subtotal - payments[name] = payment + (total_with_tax + total_with_tip - subtotal) * person_share_before_tax + person_share_before_tax = payment / subtotal if subtotal > 0 else 0 + final_payment = payment + (total_with_tax - subtotal) * person_share_before_tax + (total_with_tip - total_with_tax) * person_share_before_tax + payments[name] = round(final_payment, 2) + total_payment += payments[name] + logger.debug(f"Final payment for {name}: {payments[name]}") db.receipts.update_one({"_id": ObjectId(receipt_id)}, {'$set': {'payments': payments}}) - return render_template('results.html', payments=payments, receipt_id=receipt_id) + return render_template('results.html', payments=payments, total_payment=total_payment, receipt_id=receipt_id) except Exception as e: logger.error(f"Error in calculate_bill: {str(e)}") return jsonify({"error": "An unexpected error occurred"}), 500 diff --git a/web-app/response1.json b/web-app/response1.json new file mode 100644 index 0000000..2400278 --- /dev/null +++ b/web-app/response1.json @@ -0,0 +1,166 @@ +{ + "ocr_type" : "receipts", + "request_id" : "P_72.80.97.228_luxbmz9s_bz6", + "ref_no" : "ocr_python_123", + "file_name" : "RestaurantReceipt1.png", + "request_received_on" : 1712965847825, + "success" : true, + "image_width" : 812, + "image_height" : 1354, + "image_rotation" : 0, + "recognition_completed_on" : 1712965848215, + "receipts" : [ { + "merchant_name" : "HARBOR LANE CAFE", + "merchant_address" : "HARBOR LANE CAFE", + "merchant_phone" : null, + "merchant_website" : null, + "merchant_tax_reg_no" : null, + "merchant_company_reg_no" : null, + "region" : null, + "mall" : null, + "country" : "US", + "state" : "IL", + "city" : "CHICAGO", + "receipt_no" : null, + "date" : "2019-11-20", + "time" : null, + "items" : [ { + "amount" : 14.98, + "category" : null, + "description" : "Tacos Del Mal Shrimp", + "flags" : "", + "qty" : 1, + "remarks" : null, + "tags" : null, + "unitPrice" : null + }, { + "amount" : 12.50, + "category" : null, + "description" : "Especial Salad Chicken", + "flags" : "", + "qty" : 1, + "remarks" : null, + "tags" : null, + "unitPrice" : null + }, { + "amount" : 1.99, + "category" : null, + "description" : "Fountain Beverage", + "flags" : "", + "qty" : 1, + "remarks" : null, + "tags" : null, + "unitPrice" : null + } ], + "currency" : "USD", + "total" : 31.39, + "subtotal" : 29.47, + "tax" : 1.92, + "service_charge" : null, + "tip" : null, + "payment_method" : null, + "payment_details" : null, + "credit_card_type" : null, + "credit_card_number" : null, + "ocr_text" : " HARBOR LANE CAFE\n 3941 GREEN OAKS BLVD\n CHICAGO, IL\n SALE\n 11/20/2019 11:05 AM\n BATCH #: 01A2A\n APPR #: 34362\n TRACE #: 9\n VISA 3483\n 1 Tacos Del Mal Shrimp $14.98\n 1 Especial Salad Chicken $12.50\n 1 Fountain Beverage $1.99\n SUBTOTAL: $29.47\n TAX: $1.92\n TOTAL: $31.39\n TIP:\n TOTAL:\n APPROVED\n THANK YOU\n CUSTOMER COPY", + "ocr_confidence" : 98.50, + "width" : 596, + "height" : 1111, + "avg_char_width" : 16.9954, + "avg_line_height" : 28.3333, + "conf_amount" : 83, + "source_locations" : { + "date" : [ [ { + "x" : 46, + "y" : 216 + }, { + "x" : 240, + "y" : 216 + }, { + "x" : 240, + "y" : 246 + }, { + "x" : 46, + "y" : 246 + } ] ], + "total" : [ [ { + "x" : 275, + "y" : 696 + }, { + "x" : 381, + "y" : 696 + }, { + "x" : 381, + "y" : 726 + }, { + "x" : 275, + "y" : 726 + } ] ], + "subtotal" : [ [ { + "x" : 276, + "y" : 615 + }, { + "x" : 384, + "y" : 615 + }, { + "x" : 384, + "y" : 646 + }, { + "x" : 276, + "y" : 646 + } ] ], + "merchant_name" : [ [ { + "x" : 40, + "y" : 13 + }, { + "x" : 357, + "y" : 15 + }, { + "x" : 357, + "y" : 47 + }, { + "x" : 40, + "y" : 46 + } ] ], + "doc" : [ [ { + "x" : 24, + "y" : -40 + }, { + "x" : 679, + "y" : -40 + }, { + "x" : 679, + "y" : 1181 + }, { + "x" : 24, + "y" : 1181 + } ] ], + "tax" : [ [ { + "x" : 277, + "y" : 656 + }, { + "x" : 361, + "y" : 656 + }, { + "x" : 361, + "y" : 685 + }, { + "x" : 277, + "y" : 685 + } ] ], + "merchant_address" : [ [ { + "x" : 24, + "y" : 11 + }, { + "x" : 373, + "y" : 13 + }, { + "x" : 373, + "y" : 49 + }, { + "x" : 24, + "y" : 48 + } ] ] + } + } ] + } \ No newline at end of file diff --git a/web-app/templates/allocateitems.html b/web-app/templates/allocateitems.html index 3aa4aee..053085b 100644 --- a/web-app/templates/allocateitems.html +++ b/web-app/templates/allocateitems.html @@ -8,11 +8,11 @@

Allocate Food Items to Individuals

{% for person in people %} -

{{ person }}

+

{{ person }}

{% for item in food_items %}
- - + +
{% endfor %} {% endfor %} diff --git a/web-app/templates/results.html b/web-app/templates/results.html index 44cf957..e095ac5 100644 --- a/web-app/templates/results.html +++ b/web-app/templates/results.html @@ -17,6 +17,10 @@

Bill Calculation Results

${{ "%.2f"|format(amount) }} {% endfor %} + + Total + ${{ "%.2f"|format(total_payment) }} + Return Home diff --git a/web-app/templates/select_appetizers.html b/web-app/templates/select_appetizers.html index 7f2d9c0..1607680 100644 --- a/web-app/templates/select_appetizers.html +++ b/web-app/templates/select_appetizers.html @@ -3,31 +3,62 @@ Select Appetizers +

Select Appetizers

- +
- +
{% for item in items %}
- - + +
{% endfor %}