from typing import cast from pydantic import TypeAdapter from dmp.ad_reporting.dtos import ( AdReportingAd, AdReportingAdCriteria, AdReportingAdGroup, AdReportingSummary, ) from dmp.ad_reporting.models import AdReportingAdCountryDbt, AdReportingAdDbt from dmp.ad_reporting.types import AdReportingAdCIFields, AdReportingAdOrderBy from dmp.adapters.db import ReportingDB, ReportingRepository from dmp.config import Settings AdReportingAdList = TypeAdapter(list[AdReportingAd]) AdReportingAdGroupList = TypeAdapter(list[AdReportingAdGroup]) class AdReportingAdRepository(ReportingRepository[AdReportingAdDbt]): def __init__(self, db: ReportingDB, settings: Settings) -> None: super().__init__(db) self.settings = settings def find_by_criteria( self, criteria: AdReportingAdCriteria, *, order_by: list[AdReportingAdOrderBy] | None = None, limit: int | None = None, offset: int | None = None, ) -> list[AdReportingAd]: if criteria.countries: template_name = "ad-reporting/ad/find-by-criteria-country.sql" else: template_name = "ad-reporting/ad/find-by-criteria.sql" query = self.db.query_from_template( template_name, context={ "criteria": criteria, "order_by": order_by, "ci_fields": AdReportingAdCIFields, "limit": limit, "offset": offset, }, ) result = self.db.session.execute(query) return AdReportingAdList.validate_python( result.mappings(), context={"assets_cdn_domain": self.settings.assets_cdn_domain}, ) def summary_by_criteria( self, criteria: AdReportingAdCriteria ) -> AdReportingSummary: if criteria.countries: data_table_name = AdReportingAdCountryDbt.__tablename__ else: data_table_name = AdReportingAdDbt.__tablename__ query = self.db.query_from_template( "ad-reporting/summary.sql", context={ "criteria": criteria, "id_column": AdReportingAdDbt.id.name, "data_id_column": AdReportingAdDbt.id.name, "table_name": AdReportingAdDbt.__tablename__, "data_table_name": data_table_name, "campaign_id_column": AdReportingAdDbt.campaign_id.name, "data_campaign_id_column": AdReportingAdDbt.campaign_id.name, "ad_set_id_column": AdReportingAdDbt.ad_set_id.name, "global_participant_id_column": AdReportingAdDbt.campaign_global_participant_id.name, "objective_column": AdReportingAdDbt.campaign_objective.name, "budget_type_for": "ad", }, ) result = self.db.session.execute(query) return AdReportingSummary.model_validate(result.mappings().one()) def find_by_criteria_grouped( self, criteria: AdReportingAdCriteria, *, order_by: list[AdReportingAdOrderBy] | None = None, limit: int | None = None, offset: int | None = None, ) -> list[AdReportingAdGroup]: if criteria.countries: template_name = "ad-reporting/ad/find-by-criteria-grouped-country.sql" else: template_name = "ad-reporting/ad/find-by-criteria-grouped.sql" query = self.db.query_from_template( template_name, context={ "criteria": criteria, "order_by": order_by, "ci_fields": AdReportingAdCIFields, "limit": limit, "offset": offset, }, ) result = self.db.session.execute(query) return AdReportingAdGroupList.validate_python( result.mappings(), context={"assets_cdn_domain": self.settings.assets_cdn_domain}, ) def count_by_criteria_grouped(self, criteria: AdReportingAdCriteria) -> int: if criteria.countries: template_name = "ad-reporting/ad/count-by-criteria-grouped-country.sql" else: template_name = "ad-reporting/ad/count-by-criteria-grouped.sql" query = self.db.query_from_template( template_name, context={ "criteria": criteria, }, ) result = self.db.session.execute(query) return cast(int, result.scalar_one())