from __future__ import annotations from collections.abc import Sequence from datetime import date from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.db.models import ExchangeRate from app.integrations.cbr import FxRate from app.repositories._upsert import insert_for class ExchangeRateRepository: def __init__(self, session: AsyncSession) -> None: self.session = session async def last_rate_date(self, currency_id: int) -> date | None: result = await self.session.execute( select(func.max(ExchangeRate.rate_date)).where( ExchangeRate.currency_id == currency_id ) ) return result.scalar_one_or_none() async def upsert_many( self, currency_id: int, rates: Sequence[FxRate], user: str ) -> None: for rate in rates: stmt = insert_for(self.session, ExchangeRate.__table__).values( currency_id=currency_id, rate_date=rate.rate_date, nominal=rate.nominal, rate=rate.value, created_by=user, updated_by=user, ) stmt = stmt.on_conflict_do_update( index_elements=["currency_id", "rate_date"], set_={ "nominal": stmt.excluded.nominal, "rate": stmt.excluded.rate, "loaded_at": func.now(), "updated_at": func.now(), "updated_by": user, }, ) await self.session.execute(stmt) async def list_recent(self, currency_id: int, limit: int) -> Sequence[ExchangeRate]: result = await self.session.execute( select(ExchangeRate) .where(ExchangeRate.currency_id == currency_id) .order_by(ExchangeRate.rate_date.desc()) .limit(limit) ) return result.scalars().all()