from collections import namedtuple from typing import List, Optional, Dict from models.user_project import UserProjectRoles from utils.date_utils import DateRange from performance.schemas import ( PerformanceMetricsResponseSchema, PerformanceMetricsCampaignMetadata, PerformanceMetricsParamsSchema, PerformanceMetricsProjectsMetadata, ) from performance.constants import METRICS_FIELDS_MAPPING from performance.repository import MetricsRepository from utils.list_utils import any_present from utils.snowflake.metrics.schema import MetricsFilters from projects.repositories.projects_repository import ProjectsRepository class UtilsService: projects_repository: ProjectsRepository = ProjectsRepository() metrics_repository = MetricsRepository() def map_fields_to_dict(self, data: namedtuple, user_metrics_fields: List[int]): user_metrics_fields_dict = {} if data: for field_id in user_metrics_fields: field_alias = METRICS_FIELDS_MAPPING.get(field_id) user_metrics_fields_dict[field_id] = getattr(data, field_alias) if field_alias else None return user_metrics_fields_dict def map_performance_metrics_fields( self, data: namedtuple, names: dict, user_metrics_fields: List[int] ) -> PerformanceMetricsResponseSchema: name = names.get(int(data.entity_id)) user_metrics_fields_dict = self.map_fields_to_dict(data, user_metrics_fields) return PerformanceMetricsResponseSchema(entityId=data.entity_id, name=name, fields=user_metrics_fields_dict) def parse_sort_filter(self, sort: str) -> Optional[str]: sort_dir = "ASC" if sort.startswith("-"): sort = sort[1:] sort_dir = "DESC" sort = METRICS_FIELDS_MAPPING.get(int(sort), "entity_id") if sort != "entity_id": return f"{sort}_value {sort_dir}, entity_id ASC" return f"{sort} {sort_dir}" def campaign_metadata( self, campaign_external_ids: List[str], project_id: Optional[int] = None, project_dsp_id: Optional[str] = None, is_in_project: Optional[bool] = False, ) -> Dict[str, PerformanceMetricsCampaignMetadata]: result = {} details_project_id = None if is_in_project: details_project_id = project_id for item in self.metrics_repository.get_campaigns_metadata(campaign_external_ids, project_id, project_dsp_id): result[item.campaign_dsp_id] = self.__map_campaign_metadata_item(item, details_project_id) return result def __map_campaign_metadata_item(self, item, project_id: Optional[int] = None): if project_id is None: project_ids = list(set(i for i in item.project_ids if i is not None)) project_id = next(iter(project_ids), None) if len(project_ids) > 1: project_id = None is_pending = item.pending_count > 0 return PerformanceMetricsCampaignMetadata(campaignId=item.id, projectId=project_id, isPending=is_pending) def gras_projects_metadata(self, projects_ids: List[str]) -> Dict[str, PerformanceMetricsProjectsMetadata]: result = {} for item in self.metrics_repository.get_projects_metadata(projects_ids): has_pending_campaigns = item.pending_campaigns > 0 can_approve_campaigns = any_present( [item.role], (UserProjectRoles.ADMIN.value, UserProjectRoles.EDITOR.value) ) result[str(item.project_dsp_id)] = PerformanceMetricsProjectsMetadata( projectId=item.id, hasPendingCampaigns=has_pending_campaigns, canApproveCampaigns=can_approve_campaigns, isConfidential=item.is_confidential, ) return result def metrics_details_filters(self, params: PerformanceMetricsParamsSchema) -> MetricsFilters: filters = MetricsFilters(dates=DateRange(params.startDate, params.endDate)) return filters def get_dsp_project_id(self, project_id: int): return self.projects_repository.get_dsp_project_code_with_prefix(project_id)