from collections.abc import Sequence from dataclasses import dataclass, field from typing import ClassVar from anydi import singleton from fansifter_common.auth.requests import AuthRequest from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from dmp.ad_reporting.dtos import ( AdReportingAdSet, AdReportingAdSetCriteria, AdReportingSummary, ) from dmp.ad_reporting.enums import AdReportingObjective, AdReportingPlatform from dmp.ad_reporting.repositories import AdReportingAdSetRepository from dmp.ad_reporting.services import ( AdReportingAccountService, AdReportingBenchmarkService, ) from dmp.ad_reporting.types import AdReportingAdSetOrderBy @dataclass(kw_only=True) class GetAdReportingAdSetsRequest(AuthRequest): DEFAULT_LIMIT: ClassVar[int] = 25 DEFAULT_OFFSET: ClassVar[int] = 0 DEFAULT_ORDER_BY: ClassVar[list[AdReportingAdSetOrderBy]] = [ "startAt.desc", "name.asc", ] search: str | None campaign_id: str | None global_participant_id: str | None platform: AdReportingPlatform | None objective: AdReportingObjective | None countries: list[str] | None = None order_by: list[AdReportingAdSetOrderBy] limit: int offset: int @dataclass class GetAdReportingAdSetsResponse: items: Sequence[AdReportingAdSet] summary: AdReportingSummary # deprecated total: int = field(init=False) def __post_init__(self) -> None: self.total = self.summary.total @singleton class GetAdReportingAdSetsHandler: roster_permission = Permission("roster", "view") permission = Permission("ad_campaign", "view") def __init__( self, auth_service: AuthService, ad_set_repository: AdReportingAdSetRepository, account_service: AdReportingAccountService, benchmark_service: AdReportingBenchmarkService, ) -> None: self.auth_service = auth_service self.ad_set_repository = ad_set_repository self.account_service = account_service self.benchmark_service = benchmark_service def handle( self, request: GetAdReportingAdSetsRequest ) -> GetAdReportingAdSetsResponse: account_access = self.auth_service.authorize_for_permission( request.identity_id, permission=self.permission, ) all_account_access = self.auth_service.authorize_for_permission( request.identity_id, permission=self.roster_permission ) ad_account_labels = self.account_service.get_allowed_ad_account_labels( account_access, platform=request.platform ) if not ad_account_labels: return GetAdReportingAdSetsResponse(items=[], summary=AdReportingSummary()) criteria = AdReportingAdSetCriteria( search=request.search, global_participant_id=request.global_participant_id, platform=request.platform, objective=request.objective, countries=request.countries, account_ids=set(ad_account_labels.keys()), campaign_ids={request.campaign_id} if request.campaign_id else None, ) summary = self.ad_set_repository.summary_by_criteria(criteria) if summary.total == 0: return GetAdReportingAdSetsResponse(items=[], summary=summary) ad_sets = self.ad_set_repository.find_by_criteria( criteria, order_by=request.order_by, limit=request.limit, offset=request.offset, ) # Prefetch label ad accounts for ad_set in ad_sets: ad_set.accounts = ad_account_labels.get(ad_set.account_id, set()) if not request.countries or len(request.countries) <= 1: self.benchmark_service.prefetch_campaign_benchmarks( items=ad_sets, allowed_ad_account_labels=self.account_service.get_allowed_ad_account_labels( account_access=all_account_access, platform=request.platform, ), countries=request.countries, ) return GetAdReportingAdSetsResponse(items=ad_sets, summary=summary)