From 01aa2efa4318521495eb9e098040dfc79b18ca5d Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 13 Oct 2025 17:06:03 +0000 Subject: [PATCH] Implement code changes to enhance functionality and improve performance --- app/main.py | 104 +++- nohup.out | 1540 +++------------------------------------------------ 2 files changed, 157 insertions(+), 1487 deletions(-) diff --git a/app/main.py b/app/main.py index cec68d2..733ff69 100644 --- a/app/main.py +++ b/app/main.py @@ -310,7 +310,7 @@ async def import_transactions_from_image( tags=["Document Processing"], ) async def upload_multiple_documents( - files: List[UploadFile] = File(...), db: db_dependency = None + files: List[UploadFile] = File(...), db: db_dependency = None ): """ Upload multiple receipt images for processing. @@ -318,51 +318,73 @@ async def upload_multiple_documents( This endpoint accepts multiple image files and returns file IDs that can be used with the /process/{file_id} endpoint. """ + try: responses = [] for file in files: # Validate file type - allowed_types = ["jpg", "jpeg", "png", "gif", "bmp", "pdf"] - file_extension = file.filename.split(".")[-1].lower() + allowed_types = ["jpg", "jpeg", "png", "gif", "bmp", "pdf"] + + file_extension = file.filename.split(".")[-1].lower() + google_file_id, file_name = file.filename.split("|") if file_extension not in allowed_types: raise HTTPException( status_code=400, detail=f"Unsupported file type for {file.filename}. Allowed: {allowed_types}", - ) + ) + logger.info(f"filename: {file_name}, extension: {file_extension}, google_file_id: {google_file_id}") # Generate unique file ID - file_id = str(uuid.uuid4()) + file_id = google_file_id # Using Google Drive file ID as file_id - # Read file content and save to disk - content = await file.read() - file_path = await document_processor.save_uploaded_file( - content, file.filename - ) + # Check if file already exists in database + existing_file = get_uploaded_file_from_db(db, file_id) + + if existing_file: + # File already exists, return existing record + logger.info(f"File {file_name} with ID {file_id} already exists, returning existing record") + responses.append( + DocumentUploadResponse( + file_id=existing_file.file_id, + filename=existing_file.filename, + file_type=existing_file.file_type, + upload_date=existing_file.upload_date, + status=existing_file.status, + ) + ) + else: + # File doesn't exist, create new record + # Read file content and save to disk + content = await file.read() + file_path = await document_processor.save_uploaded_file( + content, file_name + ) - # Create database record for uploaded file - db_uploaded_file = DBUploadedFile( - file_id=file_id, - filename=file.filename, - file_path=file_path, - file_type=file_extension, - upload_date=datetime.now(), - status="uploaded", - ) - - # Add to database - db.add(db_uploaded_file) - - responses.append( - DocumentUploadResponse( + # Create database record for uploaded file + db_uploaded_file = DBUploadedFile( file_id=file_id, - filename=file.filename, + filename=file_name, + file_path=file_path, file_type=file_extension, upload_date=datetime.now(), status="uploaded", ) - ) + logger.info(f"Uploaded new file {file_name} with ID {file_id}") + + # Add to database + db.add(db_uploaded_file) + + responses.append( + DocumentUploadResponse( + file_id=file_id, + filename=file_name, + file_type=file_extension, + upload_date=datetime.now(), + status="uploaded", + ) + ) # Commit all uploaded files to database db.commit() @@ -409,6 +431,34 @@ async def process_document( for rule in request.ai_rules ] + # Check if receipt already exists for this file_id + existing_receipt = get_receipt_from_db(db, file_id) + + if existing_receipt: + # Receipt already processed, return existing data + logger.info(f"Receipt for file {file_id} already exists, returning existing record") + return DocumentProcessResponse( + file_id=file_id, + receipt_id=existing_receipt.receipt_id, + extraction_success=existing_receipt.extraction_success == "True", + vendor=existing_receipt.vendor, + description=existing_receipt.description, + total_amount=existing_receipt.amount, + tax_amount=existing_receipt.tax_amount, + date=existing_receipt.date.strftime("%Y-%m-%d"), + category=existing_receipt.category, + confidence=existing_receipt.confidence, + error=existing_receipt.error_message, + receipt_currency=existing_receipt.receipt_currency, + receipt_location=existing_receipt.receipt_location, + calculated_tax=existing_receipt.calculated_tax, + is_depreciable=existing_receipt.is_depreciable == "True" if existing_receipt.is_depreciable else None, + name_of_asset=existing_receipt.name_of_asset, + cca_rate=existing_receipt.cca_rate, + useful_life=existing_receipt.useful_life, + residual_value=existing_receipt.residual_value, + ) + # Process the file using the stored file path receipt_data = await document_processor.process_file( db_uploaded_file.file_path, diff --git a/nohup.out b/nohup.out index c2ac1af..b97bb08 100644 --- a/nohup.out +++ b/nohup.out @@ -1,1476 +1,96 @@ -INFO: 102.88.104.195:1167 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:filename: photo_2025-10-10_12-09-46.jpg, extension: jpg, google_file_id: 1Iv7JThQ59ZunCuUiz6YKRl2OTgbwLtkN +INFO:__main__:File photo_2025-10-10_12-09-46.jpg with ID 1Iv7JThQ59ZunCuUiz6YKRl2OTgbwLtkN already exists, returning existing record +INFO: 199.241.139.243:44702 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'MAPLE LEAF MOTORS INC.', 'description': 'ROMATOKI', 'total_amount': 38531.87, 'tax_amount': 4432.87, 'date': '2025-10-07', 'category': 'Supercar', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': True, 'name_of_asset': 'ROMATOKI', 'cca_rate': 0.3, 'useful_life': 8, 'residual_value': 7706.37, 'extraction_success': True} -INFO: 102.88.104.195:1167 - "POST /process/db3e3177-060e-410d-8595-a23db76ef26d HTTP/1.1" 200 OK -INFO: 102.88.104.195:1167 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1Iv7JThQ59ZunCuUiz6YKRl2OTgbwLtkN already exists, returning existing record +INFO: 199.241.139.243:44718 - "POST /process/1Iv7JThQ59ZunCuUiz6YKRl2OTgbwLtkN HTTP/1.1" 200 OK +INFO:__main__:filename: Gemini_Generated_Image_9xuhxd9xuhxd9xuh.png, extension: png, google_file_id: 1pjzC6yldJGxbL6n7Q2N6Dthp3e5rWCwl +INFO:__main__:File Gemini_Generated_Image_9xuhxd9xuhxd9xuh.png with ID 1pjzC6yldJGxbL6n7Q2N6Dthp3e5rWCwl already exists, returning existing record +INFO: 199.241.139.243:44720 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Figma, Inc.', 'description': 'Professional Full seats (monthly) Jun 19 - Jul 19, 2025', 'total_amount': 27.0, 'tax_amount': 0.0, 'date': '2025-06-19', 'category': 'technology', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:1167 - "POST /process/f02ced44-bd42-4ea3-a01c-a507c61e7b09 HTTP/1.1" 200 OK -INFO: 102.88.104.195:1167 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1pjzC6yldJGxbL6n7Q2N6Dthp3e5rWCwl already exists, returning existing record +INFO: 199.241.139.243:44726 - "POST /process/1pjzC6yldJGxbL6n7Q2N6Dthp3e5rWCwl HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-10-08 at 18.25.20_7f76d34e.jpg, extension: jpg, google_file_id: 11m5rdg47YPr41BKYIMvYdmPnZYnb0K4g +INFO:__main__:File WhatsApp Image 2025-10-08 at 18.25.20_7f76d34e.jpg with ID 11m5rdg47YPr41BKYIMvYdmPnZYnb0K4g already exists, returning existing record +INFO: 199.241.139.243:44732 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Google LLC', 'description': 'Google Workspace', 'total_amount': 21.15, 'tax_amount': 2.43, 'date': '2025-05-31', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:1167 - "POST /process/1a0f6d00-3fb2-4335-87ad-b50ea4a70c48 HTTP/1.1" 200 OK -INFO: 102.88.104.195:1167 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 11m5rdg47YPr41BKYIMvYdmPnZYnb0K4g already exists, returning existing record +INFO: 199.241.139.243:44746 - "POST /process/11m5rdg47YPr41BKYIMvYdmPnZYnb0K4g HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.19.jpeg, extension: jpeg, google_file_id: 1elaDnpZhtFJezqXZraFbaWxhJMqC9IfW +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.19.jpeg with ID 1elaDnpZhtFJezqXZraFbaWxhJMqC9IfW already exists, returning existing record +INFO: 199.241.139.243:44758 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Figma, Inc.', 'description': 'Professional Full seats (monthly) Jun 19 - Jul 19, 2025', 'total_amount': 27.0, 'tax_amount': 0.0, 'date': '2025-06-19', 'category': 'technology', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:1167 - "POST /process/ff8f82fc-ea85-4422-8383-097df9991068 HTTP/1.1" 200 OK -INFO: 102.88.104.195:1167 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1elaDnpZhtFJezqXZraFbaWxhJMqC9IfW already exists, returning existing record +INFO: 199.241.139.243:44774 - "POST /process/1elaDnpZhtFJezqXZraFbaWxhJMqC9IfW HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.19 (2).jpeg, extension: jpeg, google_file_id: 1ygCC6SwLP13OY3Tv8UmKYKCfqHZQIO-E +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.19 (2).jpeg with ID 1ygCC6SwLP13OY3Tv8UmKYKCfqHZQIO-E already exists, returning existing record +INFO: 199.241.139.243:44780 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'PAYPAL *BZABAWSKYJ', 'description': '', 'total_amount': 37.55, 'tax_amount': 0.0, 'date': '2024-05-22', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'USD', 'location': None, 'calculated_tax': 0.0, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:1167 - "POST /process/85b41eb7-67fb-4079-8be3-e3676b1ab7c7 HTTP/1.1" 200 OK -INFO: 102.88.104.195:1167 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1ygCC6SwLP13OY3Tv8UmKYKCfqHZQIO-E already exists, returning existing record +INFO: 199.241.139.243:44784 - "POST /process/1ygCC6SwLP13OY3Tv8UmKYKCfqHZQIO-E HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.19 (1).jpeg, extension: jpeg, google_file_id: 1j6guW-2aBy9pqCOzQGR1_iSCARR3KTGa +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.19 (1).jpeg with ID 1j6guW-2aBy9pqCOzQGR1_iSCARR3KTGa already exists, returning existing record +INFO: 199.241.139.243:45370 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Eleven Labs Inc.', 'description': 'Pro Jun 10 - Jul 10, 2025', 'total_amount': 111.87, 'tax_amount': 12.87, 'date': '2025-06-10', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'USD', 'location': 'New York, United States', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:1167 - "POST /process/c5fd6b40-31d1-4447-8784-162682239234 HTTP/1.1" 200 OK -INFO: 199.241.139.243:17476 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1j6guW-2aBy9pqCOzQGR1_iSCARR3KTGa already exists, returning existing record +INFO: 199.241.139.243:45378 - "POST /process/1j6guW-2aBy9pqCOzQGR1_iSCARR3KTGa HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.18.jpeg, extension: jpeg, google_file_id: 1IPNowE0xtbWUt1aqG8YPPVhqhBaPJsBY +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.18.jpeg with ID 1IPNowE0xtbWUt1aqG8YPPVhqhBaPJsBY already exists, returning existing record +INFO: 199.241.139.243:45392 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'MAPLE LEAF MOTORS INC.', 'description': 'ROMATOKI', 'total_amount': 38531.87, 'tax_amount': 4432.87, 'date': '2025-10-07', 'category': 'Supercar', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': True, 'name_of_asset': 'ROMATOKI', 'cca_rate': 0.3, 'useful_life': 8, 'residual_value': 7706.37, 'extraction_success': True} -INFO: 199.241.139.243:17488 - "POST /process/63c105a3-9768-4582-b5fe-a333b2098aee HTTP/1.1" 200 OK -INFO: 199.241.139.243:17492 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1IPNowE0xtbWUt1aqG8YPPVhqhBaPJsBY already exists, returning existing record +INFO: 199.241.139.243:45398 - "POST /process/1IPNowE0xtbWUt1aqG8YPPVhqhBaPJsBY HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.18 (1).jpeg, extension: jpeg, google_file_id: 1-ocsQytyZP397IrLSEv5j5pco10UTbaq +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.18 (1).jpeg with ID 1-ocsQytyZP397IrLSEv5j5pco10UTbaq already exists, returning existing record +INFO: 199.241.139.243:45408 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Figma, Inc.', 'description': 'Professional Full seats (monthly) Jun 19 - Jul 19, 2025', 'total_amount': 27.0, 'tax_amount': 0.0, 'date': '2025-06-19', 'category': 'technology', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 199.241.139.243:17494 - "POST /process/7856d060-e28a-4a5f-8c15-8761a7d2640c HTTP/1.1" 200 OK -INFO: 199.241.139.243:17500 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1-ocsQytyZP397IrLSEv5j5pco10UTbaq already exists, returning existing record +INFO: 199.241.139.243:45418 - "POST /process/1-ocsQytyZP397IrLSEv5j5pco10UTbaq HTTP/1.1" 200 OK +INFO:__main__:filename: photo_2025-10-10_12-09-46.jpg, extension: jpg, google_file_id: 1Iv7JThQ59ZunCuUiz6YKRl2OTgbwLtkN +INFO:__main__:File photo_2025-10-10_12-09-46.jpg with ID 1Iv7JThQ59ZunCuUiz6YKRl2OTgbwLtkN already exists, returning existing record +INFO: 199.241.139.243:46978 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Google LLC', 'description': 'Google Workspace', 'total_amount': 21.15, 'tax_amount': 2.43, 'date': '2025-05-31', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 199.241.139.243:17504 - "POST /process/13531ba3-31fb-4ba5-b8e2-df9d78f51719 HTTP/1.1" 200 OK -INFO: 199.241.139.243:17516 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1Iv7JThQ59ZunCuUiz6YKRl2OTgbwLtkN already exists, returning existing record +INFO: 199.241.139.243:46994 - "POST /process/1Iv7JThQ59ZunCuUiz6YKRl2OTgbwLtkN HTTP/1.1" 200 OK +INFO:__main__:filename: Gemini_Generated_Image_9xuhxd9xuhxd9xuh.png, extension: png, google_file_id: 1pjzC6yldJGxbL6n7Q2N6Dthp3e5rWCwl +INFO:__main__:File Gemini_Generated_Image_9xuhxd9xuhxd9xuh.png with ID 1pjzC6yldJGxbL6n7Q2N6Dthp3e5rWCwl already exists, returning existing record +INFO: 199.241.139.243:47002 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Figma, Inc.', 'description': 'Professional Full seats (monthly) Jun 19 - Jul 19, 2025', 'total_amount': 27.0, 'tax_amount': 0.0, 'date': '2025-06-19', 'category': 'technology', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 199.241.139.243:17528 - "POST /process/45cb4bac-e73c-4c4f-bed5-4af6cab3e993 HTTP/1.1" 200 OK -INFO: 199.241.139.243:17544 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1pjzC6yldJGxbL6n7Q2N6Dthp3e5rWCwl already exists, returning existing record +INFO: 199.241.139.243:47004 - "POST /process/1pjzC6yldJGxbL6n7Q2N6Dthp3e5rWCwl HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-10-08 at 18.25.20_7f76d34e.jpg, extension: jpg, google_file_id: 11m5rdg47YPr41BKYIMvYdmPnZYnb0K4g +INFO:__main__:File WhatsApp Image 2025-10-08 at 18.25.20_7f76d34e.jpg with ID 11m5rdg47YPr41BKYIMvYdmPnZYnb0K4g already exists, returning existing record +INFO: 199.241.139.243:47010 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Bzabaowskyj', 'description': 'Paypal *Bzabaowskyj* 4029357733 On', 'total_amount': 37.55, 'tax_amount': 0.0, 'date': '2024-05-22', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'USD', 'location': None, 'calculated_tax': 0.0, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 199.241.139.243:17554 - "POST /process/568a856a-73ce-4078-95ec-81bb115ca4f1 HTTP/1.1" 200 OK -INFO: 199.241.139.243:46606 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 11m5rdg47YPr41BKYIMvYdmPnZYnb0K4g already exists, returning existing record +INFO: 199.241.139.243:47022 - "POST /process/11m5rdg47YPr41BKYIMvYdmPnZYnb0K4g HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.19.jpeg, extension: jpeg, google_file_id: 1elaDnpZhtFJezqXZraFbaWxhJMqC9IfW +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.19.jpeg with ID 1elaDnpZhtFJezqXZraFbaWxhJMqC9IfW already exists, returning existing record +INFO: 199.241.139.243:47028 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Eleven Labs Inc.', 'description': 'Pro Jun 10 - Jul 10, 2025', 'total_amount': 111.87, 'tax_amount': 12.87, 'date': '2025-06-10', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'USD', 'location': 'New York, United States', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 199.241.139.243:46622 - "POST /process/11ae69f1-e664-48f9-8ee8-54df6817989e HTTP/1.1" 200 OK -INFO: 102.88.104.195:174 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1elaDnpZhtFJezqXZraFbaWxhJMqC9IfW already exists, returning existing record +INFO: 199.241.139.243:47750 - "POST /process/1elaDnpZhtFJezqXZraFbaWxhJMqC9IfW HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.19 (2).jpeg, extension: jpeg, google_file_id: 1ygCC6SwLP13OY3Tv8UmKYKCfqHZQIO-E +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.19 (2).jpeg with ID 1ygCC6SwLP13OY3Tv8UmKYKCfqHZQIO-E already exists, returning existing record +INFO: 199.241.139.243:47762 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'MAPLE LEAF MOTORS INC.', 'description': 'ROMATOKI', 'total_amount': 38531.87, 'tax_amount': 4432.87, 'date': '2025-10-07', 'category': 'Supercar', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': True, 'name_of_asset': 'ROMATOKI', 'cca_rate': 0.3, 'useful_life': 8, 'residual_value': 7706.37, 'extraction_success': True} -INFO: 102.88.104.195:174 - "POST /process/b066dac1-7f46-42b9-89ac-46690e9b6095 HTTP/1.1" 200 OK -INFO: 102.88.104.195:174 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1ygCC6SwLP13OY3Tv8UmKYKCfqHZQIO-E already exists, returning existing record +INFO: 199.241.139.243:47768 - "POST /process/1ygCC6SwLP13OY3Tv8UmKYKCfqHZQIO-E HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.19 (1).jpeg, extension: jpeg, google_file_id: 1j6guW-2aBy9pqCOzQGR1_iSCARR3KTGa +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.19 (1).jpeg with ID 1j6guW-2aBy9pqCOzQGR1_iSCARR3KTGa already exists, returning existing record +INFO: 199.241.139.243:47784 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Figma, Inc.', 'description': 'Professional Full seats (monthly) Jun 19 - Jul 19, 2025', 'total_amount': 27.0, 'tax_amount': 0.0, 'date': '2025-06-19', 'category': 'technology', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:174 - "POST /process/ffa33cc8-a74f-4349-8848-592913572700 HTTP/1.1" 200 OK -INFO: 102.88.104.195:174 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1j6guW-2aBy9pqCOzQGR1_iSCARR3KTGa already exists, returning existing record +INFO: 199.241.139.243:47786 - "POST /process/1j6guW-2aBy9pqCOzQGR1_iSCARR3KTGa HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.18.jpeg, extension: jpeg, google_file_id: 1IPNowE0xtbWUt1aqG8YPPVhqhBaPJsBY +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.18.jpeg with ID 1IPNowE0xtbWUt1aqG8YPPVhqhBaPJsBY already exists, returning existing record +INFO: 199.241.139.243:47798 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Google LLC', 'description': 'Google Workspace', 'total_amount': 21.15, 'tax_amount': 2.43, 'date': '2025-05-31', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:174 - "POST /process/cdad9235-a8e8-45c4-ad84-16f8def25356 HTTP/1.1" 200 OK -INFO: 102.88.104.195:174 - "POST /upload-multiple HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1IPNowE0xtbWUt1aqG8YPPVhqhBaPJsBY already exists, returning existing record +INFO: 199.241.139.243:47812 - "POST /process/1IPNowE0xtbWUt1aqG8YPPVhqhBaPJsBY HTTP/1.1" 200 OK +INFO:__main__:filename: WhatsApp Image 2025-07-04 at 11.52.18 (1).jpeg, extension: jpeg, google_file_id: 1-ocsQytyZP397IrLSEv5j5pco10UTbaq +INFO:__main__:File WhatsApp Image 2025-07-04 at 11.52.18 (1).jpeg with ID 1-ocsQytyZP397IrLSEv5j5pco10UTbaq already exists, returning existing record +INFO: 199.241.139.243:47824 - "POST /upload-multiple HTTP/1.1" 200 OK INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Figma, Inc.', 'description': 'Professional Full seats (monthly) Jun 19 - Jul 19, 2025', 'total_amount': 27.0, 'tax_amount': 0.0, 'date': '2025-06-19', 'category': 'technology', 'confidence': 0.95, 'currency': 'CAD', 'location': 'Ontario, Canada', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:174 - "POST /process/beba5f48-d7db-4797-94bf-5b08ff939b4a HTTP/1.1" 200 OK -INFO: 102.88.104.195:174 - "POST /upload-multiple HTTP/1.1" 200 OK -INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Bzabaowskyj', 'description': 'Paypal *Bzabaowskyj* 4029357733 On', 'total_amount': 37.55, 'tax_amount': 0.0, 'date': '2024-05-22', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'USD', 'location': None, 'calculated_tax': 0.0, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:174 - "POST /process/4756524a-1118-433b-a0e7-ff2c5a1cc0b7 HTTP/1.1" 200 OK -INFO: 102.88.104.195:174 - "POST /upload-multiple HTTP/1.1" 200 OK -INFO:__main__:Request: file_id=None user_location=None ai_rules=[AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "mkd"', action='SET_CATEGORY: technology'), AIRules(condition='Vendor CONTAINS "aws"', action='SET_CATEGORY: cloud service'), AIRules(condition='Vendor CONTAINS "Maple"', action='SET_CATEGORY: Supercar')] -INFO:services.document_processor:This is the prompt: - Analyze this receipt image and extract the following information in JSON format. - - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "mkd": Set category to "technology" - If the Vendor name contains "aws": Set category to "cloud service" - If the Vendor name contains "Maple": Set category to "Supercar" - - - JSON Format: - { - "vendor": "Store/company name", - "description": "Detailed description of items/services purchased", - "total_amount": 0.00, - "tax_amount": 0.00, - "date": "YYYY-MM-DD", - "category": "Check rules above first", - "confidence": 0.95, - "currency": "USD", - "location": "Province/State, Country", - "calculated_tax": 0.00, - "is_depreciable": false, - "name_of_asset": null, - "cca_rate": null, - "useful_life": null, - "residual_value": null, - "extraction_success": True - } - - EXTRACTION Rules: - - Extract vendor name as it appears on receipt - - Extract description of items/services purchased (e.g., "Coffee and sandwich", "Gasoline", "Office supplies") - - Total amount should be the final total including tax - - Tax amount is separate tax line if available (if not clearly shown, calculate based on location) - - Date should be the date on the receipt - - Confidence score 0-1 based on how clear the receipt is - - Currency should be the currency used on the receipt (e.g., "USD", "EUR", "CAD") - - - LOCATION & TAX RULES: - - Extract location from receipt (look for store address, province/state, country) - - Format location as "Province/State, Country" (e.g., "Ontario, Canada" or "California, USA") - - If location not shown on receipt, return null for location (system will use user location as fallback) - - TAX EXTRACTION RULES (IMPORTANT): - - If tax is EXPLICITLY shown on receipt (even if $0 or 0%), use that exact value: - * If receipt shows "Tax: $0", "Tax: $0.00", "Tax (0%)", or similar → set tax_amount to 0.00 and calculated_tax to null - * If receipt shows any other tax amount → set tax_amount to that value and calculated_tax to null - - - If tax_amount is NOT shown or UNCLEAR on receipt, calculate it based on location: - * Ontario, Canada: 13% HST - * Quebec, Canada: 9.975% QST + 5% GST = 14.975% total - * British Columbia, Canada: 12% (5% GST + 7% PST) - * Alberta, Canada: 5% GST - * California, USA: ~7.25% (varies by locality) - * New York, USA: ~8.875% (varies by locality) - * Texas, USA: 6.25% - * For other locations, estimate based on typical rates - * Store calculated tax in "calculated_tax" field and set tax_amount to the calculated value - - DEPRECIATION RULES: - - Determine if item is a depreciable asset (vehicles, machinery, equipment, computers, furniture, buildings) - - Set is_depreciable to true only for capital assets, false for consumables/services - - If is_depreciable is true, provide: - * name_of_asset: Specific name/model of the asset (e.g., "2024 Honda Accord", "Dell Laptop XPS 15", "Office Desk") - * cca_rate: CCA rate as decimal (e.g., 0.30 for 30%, 0.20 for 20%, 0.04 for 4%) - - Class 10 (Vehicles): 30% - - Class 8 (Furniture, equipment): 20% - - Class 50 (Computers, software): 55% - - Class 1 (Buildings): 4% - - Class 10.1 (Passenger vehicles >$30k): 30% - * useful_life: Expected years of use (e.g., 5 for computers, 8 for vehicles, 10 for furniture) - * residual_value: Estimated value at end of life (typically 10% of purchase price for equipment, 20% for vehicles) - - If is_depreciable is false, set name_of_asset, cca_rate, useful_life, and residual_value to null - - Return only valid JSON. - -INFO:httpx:HTTP Request: POST https://api.groq.com/openai/v1/chat/completions "HTTP/1.1 200 OK" -INFO:__main__:Extracted receipt data: {'vendor': 'Eleven Labs Inc.', 'description': 'Pro Jun 10 - Jul 10, 2025', 'total_amount': 111.87, 'tax_amount': 12.87, 'date': '2025-06-10', 'category': 'cloud service', 'confidence': 0.95, 'currency': 'USD', 'location': 'New York, United States', 'calculated_tax': None, 'is_depreciable': False, 'name_of_asset': None, 'cca_rate': None, 'useful_life': None, 'residual_value': None, 'extraction_success': True} -INFO: 102.88.104.195:174 - "POST /process/da8b53da-c5c4-43df-9ea1-3765c7ad73df HTTP/1.1" 200 OK +INFO:__main__:Receipt for file 1-ocsQytyZP397IrLSEv5j5pco10UTbaq already exists, returning existing record +INFO: 199.241.139.243:47832 - "POST /process/1-ocsQytyZP397IrLSEv5j5pco10UTbaq HTTP/1.1" 200 OK