Files
WealthySmart/backend/app/services/csv_export.py
Carlos Escalante 571428f5ac CSV export for transactions with download buttons (ARCH-18)
GET /api/v1/transactions/export streams a CSV (optional source/type/
date filters), cookie-authenticated so window.open downloads work.
Buttons on the Budget transactions tab (all) and Salarios (SALARY
only). Quoting and category resolution covered by tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 18:03:55 -06:00

58 lines
1.7 KiB
Python

"""CSV export of transactions (review ARCH-18 / wishlist #4)."""
import csv
import io
from datetime import datetime
from typing import Optional
from sqlmodel import Session, col, select
from app.models.models import Transaction, TransactionSource, TransactionType
COLUMNS = [
"id", "date", "merchant", "city", "amount", "currency",
"transaction_type", "source", "bank", "category", "notes", "reference",
]
def build_transactions_csv(
session: Session,
*,
source: Optional[TransactionSource] = None,
transaction_type: Optional[TransactionType] = None,
start_date: Optional[datetime] = None,
end_date: Optional[datetime] = None,
) -> str:
q = select(Transaction)
if source:
q = q.where(Transaction.source == source)
if transaction_type:
q = q.where(Transaction.transaction_type == transaction_type)
if start_date:
q = q.where(Transaction.date >= start_date)
if end_date:
q = q.where(Transaction.date < end_date)
q = q.order_by(col(Transaction.date).desc(), col(Transaction.id).desc())
buf = io.StringIO()
writer = csv.writer(buf)
writer.writerow(COLUMNS)
for tx in session.exec(q).all():
writer.writerow(
[
tx.id,
tx.date.isoformat(),
tx.merchant,
tx.city or "",
f"{tx.amount:.2f}",
tx.currency.value,
tx.transaction_type.value,
tx.source.value,
tx.bank.value,
tx.category.name if tx.category else "",
tx.notes or "",
tx.reference or "",
]
)
return buf.getvalue()