Added quickbooks data
This commit is contained in:
@@ -82,6 +82,20 @@ class DBTransaction(Base):
|
|||||||
categorisation_id = Column(String, nullable=True)
|
categorisation_id = Column(String, nullable=True)
|
||||||
user_id = Column(String, nullable=True)
|
user_id = Column(String, nullable=True)
|
||||||
|
|
||||||
|
# Additional QuickBooks CSV columns
|
||||||
|
TxnId = Column(String, nullable=True)
|
||||||
|
AccountType = Column(String, nullable=True)
|
||||||
|
AccountNumber = Column(String, nullable=True)
|
||||||
|
TransactionDate = Column(String, nullable=True)
|
||||||
|
TransactionType = Column(String, nullable=True)
|
||||||
|
ChequeNumber = Column(String, nullable=True)
|
||||||
|
Description1 = Column(String, nullable=True)
|
||||||
|
Description2 = Column(String, nullable=True)
|
||||||
|
VendorId = Column(String, nullable=True)
|
||||||
|
VendorName = Column(String, nullable=True)
|
||||||
|
AccountId = Column(String, nullable=True)
|
||||||
|
AccountName = Column(String, nullable=True)
|
||||||
|
|
||||||
|
|
||||||
# Uploaded Files table
|
# Uploaded Files table
|
||||||
class DBUploadedFile(Base):
|
class DBUploadedFile(Base):
|
||||||
|
|||||||
+114
-24
@@ -133,46 +133,75 @@ async def import_transactions_csv(
|
|||||||
errors = []
|
errors = []
|
||||||
for idx, row in enumerate(reader):
|
for idx, row in enumerate(reader):
|
||||||
try:
|
try:
|
||||||
# Use correct headers and strip whitespace
|
# Extract all CSV columns with proper header handling
|
||||||
account_number = row.get("Account Number") or row.get(
|
txn_id = row.get("TxnId", "").strip()
|
||||||
"Account Number ".strip()
|
account_type = row.get("Account Type", "").strip()
|
||||||
|
account_number = row.get("Account Number", "").strip()
|
||||||
|
transaction_date = row.get("Transaction Date", "").strip()
|
||||||
|
transaction_type = row.get("Transaction Type", "").strip()
|
||||||
|
cheque_number = row.get("Cheque Number", "").strip()
|
||||||
|
description_1 = row.get("Description 1", "").strip()
|
||||||
|
description_2 = row.get("Description 2", "").strip()
|
||||||
|
amount_raw = row.get("Amount", "").strip()
|
||||||
|
vendor_id = row.get("VendorId", "").strip()
|
||||||
|
vendor_name = row.get("VendorName", "").strip()
|
||||||
|
account_id = row.get("AccountId", "").strip()
|
||||||
|
account_name = row.get("AccountName", "").strip()
|
||||||
|
|
||||||
|
# Compose internal ID
|
||||||
|
internal_txn_id = (
|
||||||
|
f"{account_number}_{idx + 1}"
|
||||||
|
if account_number
|
||||||
|
else f"txn_{idx + 1}"
|
||||||
)
|
)
|
||||||
txn_date_raw = row.get("Transaction Date") or row.get(
|
|
||||||
"Transaction Date ".strip() or row.get("Date")
|
|
||||||
)
|
|
||||||
amount_raw = row.get("Amount") or row.get("Amount ".strip())
|
|
||||||
payee_name = row.get("Description 2") or row.get(
|
|
||||||
"Description 2 ".strip()
|
|
||||||
)
|
|
||||||
memo = f"{row.get('Account Type', '').strip()} {row.get('Cheque Number', '').strip()} {row.get('Description 1', '').strip()}".strip()
|
|
||||||
# Compose ID
|
|
||||||
txn_id = f"{account_number}_{idx + 1}"
|
|
||||||
# Parse date (try multiple formats)
|
# Parse date (try multiple formats)
|
||||||
txn_date_str = txn_date_raw.strip()
|
|
||||||
txn_date = None
|
txn_date = None
|
||||||
for fmt in ("%m/%d/%y", "%m/%d/%Y"):
|
for fmt in ("%m/%d/%y", "%m/%d/%Y", "%Y-%m-%d"):
|
||||||
try:
|
try:
|
||||||
txn_date = datetime.strptime(txn_date_str, fmt).strftime(
|
txn_date = datetime.strptime(transaction_date, fmt).strftime(
|
||||||
"%Y-%m-%d"
|
"%Y-%m-%d"
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
if not txn_date:
|
if not txn_date:
|
||||||
raise ValueError(f"Could not parse date: {txn_date_str}")
|
raise ValueError(f"Could not parse date: {transaction_date}")
|
||||||
# Parse amount
|
|
||||||
amount = float(amount_raw.replace(",", "").strip())
|
|
||||||
|
|
||||||
# Create database transaction object
|
# Parse amount
|
||||||
|
amount = (
|
||||||
|
float(amount_raw.replace(",", "").strip()) if amount_raw else 0.0
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use vendor_name (Description 2) as the vendor, fallback to description_2
|
||||||
|
vendor = vendor_name if vendor_name else description_2
|
||||||
|
|
||||||
|
# Compose description/memo from multiple fields
|
||||||
|
memo = f"{account_type} {cheque_number} {description_1}".strip()
|
||||||
|
|
||||||
|
# Create database transaction object with all QuickBooks fields
|
||||||
txn_date_obj = datetime.strptime(txn_date, "%Y-%m-%d")
|
txn_date_obj = datetime.strptime(txn_date, "%Y-%m-%d")
|
||||||
db_transaction = DBTransaction(
|
db_transaction = DBTransaction(
|
||||||
transaction_id=txn_id,
|
transaction_id=internal_txn_id,
|
||||||
amount=amount,
|
amount=amount,
|
||||||
date=txn_date_obj,
|
date=txn_date_obj,
|
||||||
vendor=payee_name.strip(),
|
vendor=vendor,
|
||||||
description=memo,
|
description=memo,
|
||||||
categorisation_id=categorization_id,
|
categorisation_id=categorization_id,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
|
# QuickBooks CSV columns
|
||||||
|
TxnId=txn_id,
|
||||||
|
AccountType=account_type,
|
||||||
|
AccountNumber=account_number,
|
||||||
|
TransactionDate=transaction_date,
|
||||||
|
TransactionType=transaction_type,
|
||||||
|
ChequeNumber=cheque_number,
|
||||||
|
Description1=description_1,
|
||||||
|
Description2=description_2,
|
||||||
|
VendorId=vendor_id,
|
||||||
|
VendorName=vendor_name,
|
||||||
|
AccountId=account_id,
|
||||||
|
AccountName=account_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add to database
|
# Add to database
|
||||||
@@ -180,13 +209,26 @@ async def import_transactions_csv(
|
|||||||
|
|
||||||
transactions.append(
|
transactions.append(
|
||||||
{
|
{
|
||||||
"id": txn_id,
|
"id": internal_txn_id,
|
||||||
"txn_date": txn_date,
|
"txn_date": txn_date,
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"payee_name": payee_name.strip(),
|
"payee_name": vendor,
|
||||||
"memo": memo,
|
"memo": memo,
|
||||||
"categorization_id": categorization_id,
|
"categorization_id": categorization_id,
|
||||||
"user_id": user_id,
|
"user_id": user_id,
|
||||||
|
# Include QuickBooks fields in response
|
||||||
|
"TxnId": txn_id,
|
||||||
|
"AccountType": account_type,
|
||||||
|
"AccountNumber": account_number,
|
||||||
|
"TransactionDate": transaction_date,
|
||||||
|
"TransactionType": transaction_type,
|
||||||
|
"ChequeNumber": cheque_number,
|
||||||
|
"Description1": description_1,
|
||||||
|
"Description2": description_2,
|
||||||
|
"VendorId": vendor_id,
|
||||||
|
"VendorName": vendor_name,
|
||||||
|
"AccountId": account_id,
|
||||||
|
"AccountName": account_name,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -572,6 +614,19 @@ async def match_specific_receipts(request: MatchSpecificRequest, db: db_dependen
|
|||||||
amount=db_txn.amount,
|
amount=db_txn.amount,
|
||||||
vendor=db_txn.vendor,
|
vendor=db_txn.vendor,
|
||||||
notes=db_txn.description or "",
|
notes=db_txn.description or "",
|
||||||
|
# QuickBooks CSV fields
|
||||||
|
TxnId=db_txn.TxnId,
|
||||||
|
AccountType=db_txn.AccountType,
|
||||||
|
AccountNumber=db_txn.AccountNumber,
|
||||||
|
TransactionDate=db_txn.TransactionDate,
|
||||||
|
TransactionType=db_txn.TransactionType,
|
||||||
|
ChequeNumber=db_txn.ChequeNumber,
|
||||||
|
Description1=db_txn.Description1,
|
||||||
|
Description2=db_txn.Description2,
|
||||||
|
VendorId=db_txn.VendorId,
|
||||||
|
VendorName=db_txn.VendorName,
|
||||||
|
AccountId=db_txn.AccountId,
|
||||||
|
AccountName=db_txn.AccountName,
|
||||||
)
|
)
|
||||||
transactions.append(transaction)
|
transactions.append(transaction)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -697,6 +752,41 @@ async def match_specific_receipts(request: MatchSpecificRequest, db: db_dependen
|
|||||||
tax_analysis=result.tax_analysis,
|
tax_analysis=result.tax_analysis,
|
||||||
flag_for_review=flag_for_review,
|
flag_for_review=flag_for_review,
|
||||||
auto_approve=auto_approve,
|
auto_approve=auto_approve,
|
||||||
|
# QuickBooks CSV fields
|
||||||
|
TxnId=result.transaction.TxnId if result.transaction else None,
|
||||||
|
AccountType=result.transaction.AccountType
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
AccountNumber=result.transaction.AccountNumber
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
TransactionDate=result.transaction.TransactionDate
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
TransactionType=result.transaction.TransactionType
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
ChequeNumber=result.transaction.ChequeNumber
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
Description1=result.transaction.Description1
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
Description2=result.transaction.Description2
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
VendorId=result.transaction.VendorId
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
VendorName=result.transaction.VendorName
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
AccountId=result.transaction.AccountId
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
|
AccountName=result.transaction.AccountName
|
||||||
|
if result.transaction
|
||||||
|
else None,
|
||||||
)
|
)
|
||||||
match_responses.append(match_response)
|
match_responses.append(match_response)
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,20 @@ class Transaction:
|
|||||||
currency: str = "CAD"
|
currency: str = "CAD"
|
||||||
fx_rate: Optional[float] = None
|
fx_rate: Optional[float] = None
|
||||||
|
|
||||||
|
# QuickBooks CSV fields
|
||||||
|
TxnId: Optional[str] = None
|
||||||
|
AccountType: Optional[str] = None
|
||||||
|
AccountNumber: Optional[str] = None
|
||||||
|
TransactionDate: Optional[str] = None
|
||||||
|
TransactionType: Optional[str] = None
|
||||||
|
ChequeNumber: Optional[str] = None
|
||||||
|
Description1: Optional[str] = None
|
||||||
|
Description2: Optional[str] = None
|
||||||
|
VendorId: Optional[str] = None
|
||||||
|
VendorName: Optional[str] = None
|
||||||
|
AccountId: Optional[str] = None
|
||||||
|
AccountName: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Asset:
|
class Asset:
|
||||||
@@ -102,6 +116,20 @@ class TransactionRequest(BaseModel):
|
|||||||
currency: str = "CAD"
|
currency: str = "CAD"
|
||||||
fx_rate: Optional[float] = None
|
fx_rate: Optional[float] = None
|
||||||
|
|
||||||
|
# QuickBooks CSV fields
|
||||||
|
TxnId: Optional[str] = None
|
||||||
|
AccountType: Optional[str] = None
|
||||||
|
AccountNumber: Optional[str] = None
|
||||||
|
TransactionDate: Optional[str] = None
|
||||||
|
TransactionType: Optional[str] = None
|
||||||
|
ChequeNumber: Optional[str] = None
|
||||||
|
Description1: Optional[str] = None
|
||||||
|
Description2: Optional[str] = None
|
||||||
|
VendorId: Optional[str] = None
|
||||||
|
VendorName: Optional[str] = None
|
||||||
|
AccountId: Optional[str] = None
|
||||||
|
AccountName: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class AssetRequest(BaseModel):
|
class AssetRequest(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
@@ -135,6 +163,20 @@ class MatchResponse(BaseModel):
|
|||||||
flag_for_review: Optional[bool] = None
|
flag_for_review: Optional[bool] = None
|
||||||
auto_approve: Optional[bool] = None
|
auto_approve: Optional[bool] = None
|
||||||
|
|
||||||
|
# QuickBooks CSV fields from transaction
|
||||||
|
TxnId: Optional[str] = None
|
||||||
|
AccountType: Optional[str] = None
|
||||||
|
AccountNumber: Optional[str] = None
|
||||||
|
TransactionDate: Optional[str] = None
|
||||||
|
TransactionType: Optional[str] = None
|
||||||
|
ChequeNumber: Optional[str] = None
|
||||||
|
Description1: Optional[str] = None
|
||||||
|
Description2: Optional[str] = None
|
||||||
|
VendorId: Optional[str] = None
|
||||||
|
VendorName: Optional[str] = None
|
||||||
|
AccountId: Optional[str] = None
|
||||||
|
AccountName: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class MatchingResponse(BaseModel):
|
class MatchingResponse(BaseModel):
|
||||||
matches: List[MatchResponse]
|
matches: List[MatchResponse]
|
||||||
|
|||||||
Reference in New Issue
Block a user