import decimal from dataclasses import dataclass from anydi import singleton from fansifter_common.auth.types import Permission from pydantic import TypeAdapter from dmp.adapters.db import ReportingDB from dmp.artists.cache import ArtistCache, cached_artist_data from dmp.artists.dtos import FansShareByCountry from dmp.artists.requests import ArtistFanReportFilterRequest from dmp.artists.services import ArtistAccessService @dataclass class GetArtistFansShareByLocationRequest(ArtistFanReportFilterRequest): pass @dataclass class GetArtistFansShareByLocationResponse: available_fans_share: decimal.Decimal items: list[FansShareByCountry] CountryFansShareListValidator = TypeAdapter(list[FansShareByCountry]) @singleton class GetArtistFansShareByLocationHandler: permission = Permission("fan_data_list", "view") def __init__( self, db: ReportingDB, artist_access_service: ArtistAccessService, artist_cache: ArtistCache, ) -> None: self.db = db self.artist_access_service = artist_access_service self.artist_cache = artist_cache def handle( self, request: GetArtistFansShareByLocationRequest ) -> GetArtistFansShareByLocationResponse: artist_access = self.artist_access_service.check_artist_access( request.identity_id, request.global_participant_id, request.account, permission=self.permission, ) available_fans_share = self._get_available_fans_share( request.global_participant_id, vendor_id=request.vendor_id, subaccount_id=request.subaccount_id, is_global=artist_access.is_global, ) countries = self._get_countries( request.global_participant_id, vendor_id=request.vendor_id, subaccount_id=request.subaccount_id, is_global=artist_access.is_global, ) return GetArtistFansShareByLocationResponse( available_fans_share=available_fans_share, items=countries, ) @cached_artist_data("country-available-fans-share") def _get_available_fans_share( self, global_participant_id: str, vendor_id: int | None, subaccount_id: int | None, is_global: bool, ) -> decimal.Decimal: query = self.db.query_from_template( "artist/get-artist-country-available-fans-share.sql", context={ "vendor_id": vendor_id, "subaccount_id": subaccount_id, "global_participant_id": global_participant_id, "is_global": is_global, }, ) return decimal.Decimal(self.db.session.execute(query).scalar_one_or_none() or 0) @cached_artist_data("fans-share-by-country") def _get_countries( self, global_participant_id: str, vendor_id: int | None, subaccount_id: int | None, is_global: bool, ) -> list[FansShareByCountry]: query = self.db.query_from_template( "artist/get-artist-fans-share-by-country.sql", context={ "vendor_id": vendor_id, "subaccount_id": subaccount_id, "global_participant_id": global_participant_id, "is_global": is_global, }, ) result = self.db.session.execute(query).mappings() return CountryFansShareListValidator.validate_python(result)