mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 10:08:46 +02:00
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>
This commit is contained in:
@@ -2,6 +2,7 @@ from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from fastapi.responses import Response as FastAPIResponse
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import and_, or_
|
||||
from sqlmodel import Session, col, func, select
|
||||
@@ -21,6 +22,7 @@ from app.models.models import (
|
||||
)
|
||||
|
||||
from app.services.budget_projection import get_cycle_range, get_previous_cycle
|
||||
from app.services.csv_export import build_transactions_csv
|
||||
from app.services.exchange_rate import get_converted_amount_expr
|
||||
|
||||
router = APIRouter(prefix="/transactions", tags=["transactions"])
|
||||
@@ -97,6 +99,33 @@ def list_transactions(
|
||||
return session.exec(query).all()
|
||||
|
||||
|
||||
@router.get("/export")
|
||||
def export_transactions_csv(
|
||||
source: Optional[TransactionSource] = None,
|
||||
transaction_type: Optional[TransactionType] = None,
|
||||
start_date: Optional[str] = None,
|
||||
end_date: Optional[str] = None,
|
||||
session: Session = Depends(get_session),
|
||||
_user: str = Depends(get_current_user),
|
||||
):
|
||||
"""Download transactions as CSV (filters optional). Cookie-authenticated,
|
||||
so a plain <a href> download works from the SPA."""
|
||||
csv_text = build_transactions_csv(
|
||||
session,
|
||||
source=source,
|
||||
transaction_type=transaction_type,
|
||||
start_date=datetime.fromisoformat(start_date) if start_date else None,
|
||||
end_date=datetime.fromisoformat(end_date) if end_date else None,
|
||||
)
|
||||
return FastAPIResponse(
|
||||
content=csv_text,
|
||||
media_type="text/csv; charset=utf-8",
|
||||
headers={
|
||||
"Content-Disposition": 'attachment; filename="wealthysmart-transactions.csv"'
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.get("/cycles", response_model=list[BillingCycle])
|
||||
def list_billing_cycles(
|
||||
session: Session = Depends(get_session),
|
||||
|
||||
Reference in New Issue
Block a user