"""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: the closing's earliest dated transaction date_to: dt.date | None = None # default: month-end (or the latest transaction) @router.post("/{session_id}/fx/fetch-daily") def fetch_daily_rates(session_id: int, body: DailyFetchIn | None = None, db: OrmSession = Depends(db_dep)) -> dict: """(Re-)fetch the per-date FX table from the provider. Processing already does this automatically; the explicit fetch also replaces hand-entered overrides.""" 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.")