From 2f917ec085699220a752ad182ae422034a0c309e Mon Sep 17 00:00:00 2001 From: bolade Date: Thu, 23 Oct 2025 23:11:13 +0100 Subject: [PATCH] Added source column --- app/database.py | 11 +++++++---- app/main.py | 35 +++++++++++++++++++++++++---------- app/schemas.py | 5 +++++ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/app/database.py b/app/database.py index 82bb52b..b0ef326 100644 --- a/app/database.py +++ b/app/database.py @@ -29,23 +29,25 @@ Base = declarative_base() def create_db_tables(): """Create database tables safely with error handling""" import logging + logger = logging.getLogger(__name__) - + try: # Check if tables already exist to avoid unnecessary DDL operations from sqlalchemy import inspect + inspector = inspect(engine) existing_tables = inspector.get_table_names() - + if existing_tables: logger.info(f"Database tables already exist: {existing_tables}") return - + # Create tables with timeout protection logger.info("Creating database tables...") Base.metadata.create_all(bind=engine, checkfirst=True) logger.info("Database tables created successfully") - + except KeyboardInterrupt: logger.warning("Database creation interrupted by user") raise @@ -81,6 +83,7 @@ class DBTransaction(Base): tax_amount = Column(Float, nullable=True) categorisation_id = Column(String, nullable=True) user_id = Column(String, nullable=True) + source = Column(String, nullable=True) # e.g., "csv", "image", "manual", "api" # Additional QuickBooks CSV columns TxnId = Column(String, nullable=True) diff --git a/app/main.py b/app/main.py index a983783..c756410 100644 --- a/app/main.py +++ b/app/main.py @@ -1,7 +1,6 @@ import csv import io import logging -import uuid from datetime import datetime from typing import List @@ -147,6 +146,7 @@ async def import_transactions_csv( vendor_name = row.get("VendorName", "").strip() account_id = row.get("AccountId", "").strip() account_name = row.get("AccountName", "").strip() + source = row.get("Source", "").strip() # Compose internal ID internal_txn_id = ( @@ -189,6 +189,7 @@ async def import_transactions_csv( description=memo, categorisation_id=categorization_id, user_id=user_id, + source=source, # Source of this transaction # QuickBooks CSV columns TxnId=txn_id, AccountType=account_type, @@ -229,6 +230,7 @@ async def import_transactions_csv( "VendorName": vendor_name, "AccountId": account_id, "AccountName": account_name, + "source": source, } ) except Exception as e: @@ -352,7 +354,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. @@ -360,7 +362,7 @@ 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 = [] @@ -375,18 +377,22 @@ async def upload_multiple_documents( 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}") + ) + logger.info( + f"filename: {file_name}, extension: {file_extension}, google_file_id: {google_file_id}" + ) # Generate unique file ID file_id = google_file_id # Using Google Drive file ID as file_id # 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") + logger.info( + f"File {file_name} with ID {file_id} already exists, returning existing record" + ) responses.append( DocumentUploadResponse( file_id=existing_file.file_id, @@ -475,10 +481,12 @@ async def process_document( # 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") + 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, @@ -494,7 +502,9 @@ async def process_document( 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, + 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, @@ -614,6 +624,7 @@ async def match_specific_receipts(request: MatchSpecificRequest, db: db_dependen amount=db_txn.amount, vendor=db_txn.vendor, notes=db_txn.description or "", + source=db_txn.source, # QuickBooks CSV fields TxnId=db_txn.TxnId, AccountType=db_txn.AccountType, @@ -752,6 +763,10 @@ async def match_specific_receipts(request: MatchSpecificRequest, db: db_dependen tax_analysis=result.tax_analysis, flag_for_review=flag_for_review, auto_approve=auto_approve, + # Transaction metadata + transaction_source=result.transaction.source + if result.transaction + else None, # QuickBooks CSV fields TxnId=result.transaction.TxnId if result.transaction else None, AccountType=result.transaction.AccountType diff --git a/app/schemas.py b/app/schemas.py index 42a058d..126354c 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -43,6 +43,7 @@ class Transaction: # Tax rule fields currency: str = "CAD" fx_rate: Optional[float] = None + source: Optional[str] = None # e.g., "csv", "image", "manual", "api" # QuickBooks CSV fields TxnId: Optional[str] = None @@ -115,6 +116,7 @@ class TransactionRequest(BaseModel): # Tax rule fields currency: str = "CAD" fx_rate: Optional[float] = None + source: Optional[str] = None # e.g., "csv", "image", "manual", "api" # QuickBooks CSV fields TxnId: Optional[str] = None @@ -163,6 +165,9 @@ class MatchResponse(BaseModel): flag_for_review: Optional[bool] = None auto_approve: Optional[bool] = None + # Transaction metadata + transaction_source: Optional[str] = None # Source of the transaction + # QuickBooks CSV fields from transaction TxnId: Optional[str] = None AccountType: Optional[str] = None