Files
WealthySmart/backend/app/api/v1/endpoints/salarios.py
Carlos Escalante 94a8a894a6
All checks were successful
Deploy to VPS / deploy (push) Successful in 14s
Convert all currencies to CRC and poll rates every 6h
Budget/transactions/salarios totals summed Transaction.amount directly,
so USD/EUR entries were treated as CRC and effectively disappeared from
the dashboard (the analytics fix in 9a80f2a only covered analytics).
Adds a shared get_converted_amount_expr() helper driven by the full
Currency enum — USD/EUR via ExchangeRate-API, BTC/XMR via CoinGecko —
and wires it into every func.sum(Transaction.amount) site.

Also starts a background task in the FastAPI lifespan that force-refreshes
every currency 4x/day, persisting USD to the DB and updating in-memory
caches for the rest. Failures are swallowed per-currency so a CoinGecko
outage cannot take out USD/EUR, and the last-known rate is always retained.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:16:20 -06:00

57 lines
1.7 KiB
Python

from datetime import datetime
from typing import Optional
from fastapi import APIRouter, Depends, Query
from pydantic import BaseModel
from sqlmodel import Session, col, func, select
from app.auth import get_current_user
from app.db import get_session
from app.models.models import Transaction, TransactionRead, TransactionType
from app.services.exchange_rate import get_converted_amount_expr
router = APIRouter(prefix="/salarios", tags=["salarios"])
class SalariosSummary(BaseModel):
count: int
total_amount: float
latest_date: Optional[datetime] = None
@router.get("/", response_model=list[TransactionRead])
def list_salarios(
limit: int = Query(default=50, le=500),
offset: int = 0,
session: Session = Depends(get_session),
_user: str = Depends(get_current_user),
):
query = (
select(Transaction)
.where(Transaction.transaction_type == TransactionType.DEPOSITO)
.order_by(col(Transaction.date).desc())
.offset(offset)
.limit(limit)
)
return session.exec(query).all()
@router.get("/summary", response_model=SalariosSummary)
def salarios_summary(
session: Session = Depends(get_session),
_user: str = Depends(get_current_user),
):
amount_crc = get_converted_amount_expr(session)
result = session.exec(
select(
func.count(),
func.coalesce(func.sum(amount_crc), 0),
func.max(Transaction.date),
).where(Transaction.transaction_type == TransactionType.DEPOSITO)
).first()
return SalariosSummary(
count=result[0] if result else 0,
total_amount=float(result[1]) if result else 0.0,
latest_date=result[2] if result else None,
)