"""Dividend calendar Oracle service methods.""" from __future__ import annotations import datetime as dt from typing import Sequence from libs.oracle_client.client import OracleClient from libs.oracle_client.models import ( DividendCalendarEntry, DividendHistoryResponse, DividendIngestResponse, DividendUpcomingResponse, ) def _date_param(value: dt.date | str | None) -> str | None: if value is None: return None if isinstance(value, dt.date): return value.isoformat() return str(value) class DividendService: def __init__(self, client: OracleClient) -> None: self._client = client async def get_upcoming( self, *, as_of_date: dt.date | str | None = None, from_ex_date: dt.date | str | None = None, to_ex_date: dt.date | str | None = None, symbols: Sequence[str] | None = None, limit: int = 500, force_refresh: bool = False, ) -> DividendUpcomingResponse: params: dict[str, object] = { "limit": int(limit), "force_refresh": bool(force_refresh), } as_of = _date_param(as_of_date) from_ex = _date_param(from_ex_date) to_ex = _date_param(to_ex_date) if as_of: params["as_of_date"] = as_of if from_ex: params["from_ex_date"] = from_ex if to_ex: params["to_ex_date"] = to_ex if symbols: params["symbols"] = [str(symbol).strip().upper() for symbol in symbols if str(symbol).strip()] data = await self._client.get("/api/v1/dividends/upcoming", params=params) entries = [DividendCalendarEntry.model_validate(item) for item in data.get("dividends", [])] return DividendUpcomingResponse( dividends=entries, total_count=int(data.get("total_count", len(entries))), metadata=dict(data.get("metadata") or {}), ) async def get_history( self, symbol: str, *, limit: int = 1000, force_refresh: bool = False, ) -> DividendHistoryResponse: data = await self._client.get( f"/api/v1/dividends/history/{symbol}", params={"limit": int(limit), "force_refresh": bool(force_refresh)}, ) entries = [DividendCalendarEntry.model_validate(item) for item in data.get("dividends", [])] annual_yield_estimate = data.get("annual_yield_estimate") return DividendHistoryResponse( symbol=data.get("symbol", symbol), dividends=entries, total_count=int(data.get("total_count", len(entries))), annual_yield_estimate=float(annual_yield_estimate) if annual_yield_estimate is not None else None, metadata=dict(data.get("metadata") or {}), ) async def ingest( self, symbols: Sequence[str], *, force_refresh: bool = False, ) -> DividendIngestResponse: payload = { "symbols": [str(symbol).strip().upper() for symbol in symbols if str(symbol).strip()], "force_refresh": bool(force_refresh), } data = await self._client.post("/api/v1/dividends/admin/ingest", json=payload) return DividendIngestResponse.model_validate(data)