mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 15:28:47 +02:00
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>
58 lines
1.7 KiB
Python
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()
|