Added source column

This commit is contained in:
bolade
2025-10-23 23:11:13 +01:00
parent 7296d09319
commit 2f917ec085
3 changed files with 37 additions and 14 deletions
+7 -4
View File
@@ -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)
+25 -10
View File
@@ -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
+5
View File
@@ -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