from dataclasses import dataclass from datetime import date, timedelta import time import pandas as pd from loguru import logger from ..db.session import get_db, get_db_session from ..db.queries import QueryLoader, to_sql_string from ..config.paths import QUERY_PATHS from ..config.countries import COUNTRY_DICT @dataclass class FillStatus: run_data: bool run_email: bool dates_to_fill: list[date] class FillService: def __init__(self): self.db = get_db() self.dbs = get_db_session() self.query_loader = QueryLoader() def check_availability(self) -> FillStatus: base, max_s = self._get_dates() date_list = self._get_date_list(base, max_s) if not date_list: logger.info("No new data available") return FillStatus(run_data=False, run_email=False, dates_to_fill=[]) run_email = max_s.weekday() in [1, 4, 6] logger.info(f"Found {len(date_list)} date(s) to process, run_email={run_email}") return FillStatus(run_data=True, run_email=run_email, dates_to_fill=date_list) def fill_dates(self, dates: list[date]) -> bool: for d in dates: try: self._fill_table(d) except Exception as e: logger.error(f"Failed to fill {d}: {e}") return False return True def _get_dates(self) -> tuple[date, date]: query = self.query_loader.load(QUERY_PATHS.date) data = self.db.query(query) return data["base"][0], data["max_s"][0] def _get_date_list(self, base: date, max_s: date) -> list[date]: delta = max_s - base return [base + timedelta(days=x) for x in range(1, delta.days + 1)] def _fill_table(self, fill_date: date) -> None: logger.info(f"Filling data for {fill_date}") start = time.time() cc_str = to_sql_string(list(COUNTRY_DICT.keys())) query = self.query_loader.load( QUERY_PATHS.fill, cc_str=cc_str, date=f"'{fill_date}'", ) self.dbs.execute(query) self.dbs.commit() elapsed = round(time.time() - start) logger.info(f"Filled {fill_date} in {elapsed}s")