Finance-Accounts/ar-aging-app/backend/app/api/routes/fx.py

48 lines
2.0 KiB
Python

"""Fetch exchange rates from the configured provider (Frankfurter by default).
Fetched rates arrive UNCONFIRMED: Control C5 still blocks the close until a person
confirms them for the reporting month — this endpoint only replaces typing rates by hand."""
from __future__ import annotations
import datetime as dt
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.orm import Session as OrmSession
from ...services.fx_service import FxProviderError, seed_daily_fx, seed_session_fx
from ..deps import db_dep, ensure_editable, get_session_or_404
router = APIRouter(prefix="/api/sessions", tags=["fx"])
@router.post("/{session_id}/fx/fetch")
def fetch_month_end_rates(session_id: int, db: OrmSession = Depends(db_dep)) -> dict:
"""Pre-fill this closing's FX table with the provider's month-end rates."""
s = get_session_or_404(session_id, db)
ensure_editable(s)
try:
return seed_session_fx(db, s)
except FxProviderError as e:
raise HTTPException(502, f"{e} — enter the rates manually on the Controls tab.")
class DailyFetchIn(BaseModel):
marketplace: str | None = None # default: every non-USD marketplace in the closing
date_from: dt.date | None = None # default: first day of the reporting month
date_to: dt.date | None = None # default: month-end
@router.post("/{session_id}/fx/fetch-daily")
def fetch_daily_rates(session_id: int, body: DailyFetchIn | None = None,
db: OrmSession = Depends(db_dep)) -> dict:
"""Fill the per-date FX override table from the provider for a date range."""
s = get_session_or_404(session_id, db)
ensure_editable(s)
body = body or DailyFetchIn()
try:
return seed_daily_fx(db, s, marketplace=body.marketplace,
date_from=body.date_from, date_to=body.date_to)
except FxProviderError as e:
raise HTTPException(502, f"{e} — enter daily rates manually on the AR Ledger tab.")