58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
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()
|