from typing import List, Optional from models import ProductFamily, Playlist, Campaign, Artist, StreamRate from models.campaign import CampaignSourceType from projects.repositories.projects_repository import ProjectsRepository from reporting.repositories.reporting_repository import ReportingRepository from services.territory.territories_service import TerritoriesService from services.territory.constants import WORLDWIDE, GLOBAL_TERRITORY_ID from datetime import date from reporting.schemas import ReportingType from reporting.services.reporting_metrics.combined_metrics_fetcher import CombinedMetricsFetcher class ReportingMetricsBuilder: reporting_repository: ReportingRepository = ReportingRepository() territories_service: TerritoriesService = TerritoriesService() projects_repository: ProjectsRepository = ProjectsRepository() metrics_fetcher: CombinedMetricsFetcher = CombinedMetricsFetcher() revenue_rates_by_country: Optional[StreamRate] = None tracks_isrcs = None artists_ids = None playlists_ids = [] def __init__(self, reporting_type: int): self.reporting_type = reporting_type def is_in_type(self, r_type): return self.reporting_type == r_type or self.reporting_type == ReportingType.ALL_METRICS.value async def get_metrics_for_project( self, project_id: int, start_date: date, end_date: date, dsps: List[str], territory_id: int ): artists_ids = [] campaigns_ids = [] # Followers Task params = artists_ids, start_date, end_date if self.is_in_type(ReportingType.FOLLOWERS.value) and territory_id == GLOBAL_TERRITORY_ID: artists_ids = self.artist_ids(project_id) # DSP params campaigns_ids, project_id, start_date, end_date if self.is_in_type(ReportingType.DSP_METRICS.value): campaigns = self.projects_repository.get_external_campaigns(project_id) campaigns_ids = self.__get_campaigns_external_ids(campaigns) external_project_id = self.projects_repository.get_project_prs_id(project_id) project_gras_code = self.projects_repository.get_project_by_id(project_id).gras_project_code country_code = self.territories_service.get_country_code_for_delphi_api(territory_id, global_value=WORLDWIDE) return await self.metrics_fetcher.fetch_metrics( start_date=start_date, end_date=end_date, artists_ids=artists_ids, project_id=external_project_id, campaigns_ids=campaigns_ids, dsps=dsps, revenue_stream_rate=self.get_revenue_stream_rates_data_by_country(country_id=territory_id), reporting_type=self.reporting_type, country_code=country_code, project_gras_code=project_gras_code, ) def tracks_isrc(self, project_id): if self.tracks_isrcs is None: product_families = self.projects_repository.get_product_families(project_id) self.tracks_isrcs = self.get_product_families_tracks_isrc(product_families) return self.tracks_isrcs def artist_ids(self, project_id): if self.artists_ids is None: artists = self.projects_repository.get_external_primary_artists(project_id) self.artists_ids = self.__get_artists_ids(artists) return self.artists_ids def playlist_ids(self, project_id, artists_ids): if not self.playlists_ids and not artists_ids: playlists = self.projects_repository.get_target_playlists(project_id) self.playlists_ids = self.__get_playlists_external_ids(playlists) return self.playlists_ids def get_product_families_tracks_isrc(self, product_families: List[ProductFamily]) -> List[str]: tracks_isrc = [] for product_family in product_families: tracks_isrc += self.__get_tracks_isrc(product_family.tracks) return tracks_isrc def __get_tracks_isrc(self, tracks): return [track.isrc for track in tracks if track.isrc] def __get_playlists_external_ids(self, playlists: List[Playlist]) -> List[str]: gras_ids = [] # Here I use full for form because gras_id is generated value and I don't want it to be calculated twice for playlist in playlists: gras_id = playlist.gras_id if gras_id: gras_ids.append(gras_id) return gras_ids def __get_campaigns_external_ids(self, campaigns: List[Campaign]) -> List[str]: def __dsp_campaign_source(source): if source == CampaignSourceType.PRS.value: return CampaignSourceType.INTERNAL.value else: return source return [f"{__dsp_campaign_source(c.source) }_{c.external_id}" for c in campaigns if c.external_id] def __get_artists_ids(self, artists: List[Artist]) -> List[str]: return [a.external_id for a in artists if a.external_id is not None and a.external_id.startswith("GRAS_")] def get_revenue_stream_rates_data_by_country(self, country_id: Optional[int] = None) -> Optional[StreamRate]: if not country_id: country_id = GLOBAL_TERRITORY_ID if not self.revenue_rates_by_country: self.revenue_rates_by_country = self.reporting_repository.get_revenue_stream_rates_by_country(country_id) return self.revenue_rates_by_country