from fastapi import APIRouter, Depends, UploadFile from pydantic import BaseModel from sqlmodel import Session, select from app.auth import get_current_user from app.db import get_session from app.models.models import Bank, PensionSnapshot, PensionSnapshotRead from app.services.pension_pdf import parse_pension_pdf router = APIRouter(prefix="/pensions", tags=["pensions"]) class PensionUploadResult(BaseModel): imported: int duplicates: int errors: list[str] snapshots: list[PensionSnapshotRead] @router.post("/upload", response_model=PensionUploadResult) async def upload_pension_pdfs( files: list[UploadFile], session: Session = Depends(get_session), _user: str = Depends(get_current_user), ): imported = 0 duplicates = 0 errors: list[str] = [] created: list[PensionSnapshot] = [] for file in files: filename = file.filename or "unknown.pdf" try: pdf_bytes = await file.read() fund_snapshots = parse_pension_pdf(pdf_bytes, filename) except ValueError as e: errors.append(str(e)) continue except Exception as e: errors.append(f"{filename}: {e}") continue for snap in fund_snapshots: existing = session.exec( select(PensionSnapshot).where( PensionSnapshot.fund == Bank(snap.fund), PensionSnapshot.period_start == snap.period_start, PensionSnapshot.period_end == snap.period_end, ) ).first() if existing: duplicates += 1 continue row = PensionSnapshot( fund=Bank(snap.fund), contract_number=snap.contract_number, period_start=snap.period_start, period_end=snap.period_end, saldo_anterior=snap.saldo_anterior, aportes=snap.aportes, rendimientos=snap.rendimientos, retiros=snap.retiros, traslados=snap.traslados, comision=snap.comision, correccion=snap.correccion, bonificacion=snap.bonificacion, saldo_final=snap.saldo_final, source_filename=filename, ) session.add(row) created.append(row) imported += 1 if imported > 0: session.commit() for row in created: session.refresh(row) return PensionUploadResult( imported=imported, duplicates=duplicates, errors=errors, snapshots=[PensionSnapshotRead.model_validate(r) for r in created], ) @router.get("/snapshots", response_model=list[PensionSnapshotRead]) def get_snapshots( session: Session = Depends(get_session), _user: str = Depends(get_current_user), ): rows = session.exec( select(PensionSnapshot).order_by( PensionSnapshot.period_end.desc(), # type: ignore[union-attr] PensionSnapshot.fund, ) ).all() return rows @router.get("/fund-summary", response_model=list[PensionSnapshotRead]) def get_fund_summary( session: Session = Depends(get_session), _user: str = Depends(get_current_user), ): """Return the latest snapshot per fund (by most recent period_end).""" all_rows = session.exec( select(PensionSnapshot).order_by( PensionSnapshot.period_end.desc(), # type: ignore[union-attr] ) ).all() seen: set[str] = set() latest: list[PensionSnapshot] = [] for row in all_rows: if row.fund.value not in seen: seen.add(row.fund.value) latest.append(row) return latest