from typing import List, Optional from external_api.base.clients.client_factory import ApiClientFactory from external_api.base.clients.delphi_client import DelphiClient, AdsPerformanceQuery, AdPerformanceSummaryItem from models.performance_breakdown_option import BreakdownOptions from performance.schemas import PerformanceMetricsParamsSchema, PerformanceMetricsListResponseSchema from performance.services.metrics_api.dimensions import Dimensions from performance.services.metrics_api.metadata_providers import ( MetadataProvider, CampaignMetadataProvider, ProjectMetadataProvider, ) from utils.list_utils import get_nested_attr from performance.services.metrics_api.metrics_mapper import MetricsMapper from performance.services.metrics_api import utils from services.territory.territories_service import TerritoriesService from performance.repository import MetricsApiSearchRepository from projects.repositories.projects_repository import ProjectsRepository class MetricsDetailsApiService: projects_repository: ProjectsRepository = ProjectsRepository() delphi_client: DelphiClient = ApiClientFactory.delphi_client() mapper: MetricsMapper = MetricsMapper() territories_service: TerritoriesService = TerritoriesService() search_repo: MetricsApiSearchRepository = MetricsApiSearchRepository() async def get_campaign_metrics_details( self, user_id: int, campaign_id: str, params: PerformanceMetricsParamsSchema ): dimension = Dimensions.get_from_breakdown_option(BreakdownOptions(params.breakdown)) query = utils.build_performance_query(dimension, user_id, params) query.country_code = self.territories_service.get_country_code_for_delphi_api(params.territoryId) query.campaign_id = [campaign_id] query.is_assigned = True query.is_pending = params.isPending return await self.__get_metrics(dimension, query) async def get_unassigned_campaigns_metrics_details( self, user_id: int, campaign_id: str, params: PerformanceMetricsParamsSchema ): dimension = Dimensions.get_from_breakdown_option(BreakdownOptions(params.breakdown)) query = utils.build_performance_query(dimension, user_id, params) query.country_code = self.territories_service.get_country_code_for_delphi_api(params.territoryId) query.campaign_id = [campaign_id] query.is_assigned = False query.is_pending = params.isPending or False return await self.__get_metrics(dimension, query) async def get_project_metrics_details(self, user_id: int, project_id: str, params: PerformanceMetricsParamsSchema): dimension = Dimensions.get_from_breakdown_option(BreakdownOptions(params.breakdown)) query = utils.build_performance_query(dimension, user_id, params) query.country_code = self.territories_service.get_country_code_for_delphi_api(params.territoryId) query.project_id = project_id query.is_assigned = True query.is_pending = params.isPending metadata_provider = None if dimension == Dimensions.CAMPAIGN: query.is_assigned = None if params.freeText: campaign_ids = await self.search_repo.search_campaigns_in_project(project_id, params) if not campaign_ids: return PerformanceMetricsListResponseSchema(items=[]) query.campaign_id = campaign_ids project = self.projects_repository.get_project_by_PRS_id(project_id.split("_")[1]) metadata_provider = CampaignMetadataProvider(project_id=project.id, is_in_project=True) return await self.__get_metrics(dimension, query, metadata_provider) async def get_artist_metrics_details(self, user_id: int, artist_id: str, params: PerformanceMetricsParamsSchema): dimension = Dimensions.get_from_breakdown_option(BreakdownOptions(params.breakdown)) query = utils.build_performance_query(dimension, user_id, params) query.country_code = self.territories_service.get_country_code_for_delphi_api(params.territoryId) query.artist_id = artist_id query.is_assigned = True query.is_pending = params.isPending or False metadata_provider = None if dimension == Dimensions.PROJECT: metadata_provider = ProjectMetadataProvider() return await self.__get_metrics(dimension, query, metadata_provider) async def __get_metrics( self, dimension: Dimensions, query: AdsPerformanceQuery, metadata_provider: Optional[MetadataProvider] = None ): metrics = await self.delphi_client.get_ads_performance(query) ids = self.__get_dimensions_ids(dimension, metrics.items) metadata = {} if metadata_provider is not None and ids is not None: metadata = metadata_provider.get_metadata(ids) return self.mapper.map_metrics(dimension=dimension, metrics=metrics, metadata=metadata) def __get_dimensions_ids(self, dimension: Dimensions, items: List[AdPerformanceSummaryItem]): path = dimension.dimension_entity_id_path() if path is None: return None return list(filter(None, map(lambda x: get_nested_attr(x.dimensions, path, None), items)))