from anydi import singleton from fansifter_common.artist.validators import ArtistValidator from fansifter_common.auth.account import Account from dmp.audiences.enums import AudienceTarget from dmp.audiences.exceptions import ( ArtistPhoneNumberNotFoundError, AudienceInvalidCustomListIdError, AudienceTargetInvalidArtistIdError, AudienceUniqueNameError, ) from dmp.audiences.repositories import AudienceRepository from dmp.audiences.types import FanDataListId from dmp.rosters.enums import FanDataListType from dmp.rosters.exceptions import MainRepArtistOnlyAllowedError from dmp.rosters.repositories import ArtistRosterMainRepRepository, CustomListRepository from dmp.text_campaigns.repositories import ArtistPhoneNumberRepository @singleton class AudienceValidator: def __init__( self, audience_repository: AudienceRepository, custom_list_repository: CustomListRepository, artist_roster_main_rep_repository: ArtistRosterMainRepRepository, artist_validator: ArtistValidator, artist_phone_number_repository: ArtistPhoneNumberRepository, ) -> None: self.audience_repository = audience_repository self.custom_list_repository = custom_list_repository self.artist_roster_main_rep_repository = artist_roster_main_rep_repository self.artist_validator = artist_validator self.artist_phone_number_repository = artist_phone_number_repository def validate_name(self, name: str, account: Account) -> None: """Validate audience name under account.""" if self.audience_repository.exists_by_name_and_account( name=name, account=account ): raise AudienceUniqueNameError def validate_fandata_list( self, fandata_list_ids: list[FanDataListId], account: Account, target: AudienceTarget, ) -> None: """Validate fandata_list_ids.""" custom_list_ids = set() artist_ids = set() for fandata_list_id in fandata_list_ids: if fandata_list_id.type == FanDataListType.CUSTOM_LIST: custom_list_ids.add(fandata_list_id.id) elif fandata_list_id.type == FanDataListType.ARTIST: artist_ids.add(fandata_list_id.id) # Email/text target requires at least one fandata_list_id of type # CUSTOM_LIST or ARTIST if ( target in (AudienceTarget.EMAIL, AudienceTarget.TEXT) and len(custom_list_ids) + len(artist_ids) != 1 ): raise AudienceTargetInvalidArtistIdError # Validate artist ids for global_participant_id in artist_ids: self.artist_validator.validate_global_participant_id( global_participant_id, ) # Validate custom list ids if custom_list_ids: allowed_custom_list_ids = self.custom_list_repository.get_allowed_ids( vendor_ids=[account.vendor_id], subaccount_ids=[account.subaccount_id], ) if custom_list_ids - set(allowed_custom_list_ids): raise AudienceInvalidCustomListIdError def validate_main_rep_only_artists( self, fandata_list_ids: list[FanDataListId], account: Account, target: AudienceTarget, ) -> None: # Only required for email and text targets if target not in (AudienceTarget.EMAIL, AudienceTarget.TEXT): return None # Get artist only ids global_participant_ids = [ fandata_list_id.id for fandata_list_id in fandata_list_ids if fandata_list_id.type == FanDataListType.ARTIST ] if not global_participant_ids: return None main_reps = self.artist_roster_main_rep_repository.find_by_account_and_global_participant_ids( vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, global_participant_ids=global_participant_ids, ) allowed_global_participant_ids = [ main_rep.global_participant_id for main_rep in main_reps ] for global_participant_id in global_participant_ids: if global_participant_id not in allowed_global_participant_ids: raise MainRepArtistOnlyAllowedError( global_participant_id=global_participant_id, ) return None def validate_artist_has_phone_number( self, fandata_list_ids: list[FanDataListId] ) -> None: for fan_list in fandata_list_ids: if fan_list.type == FanDataListType.ARTIST: if not self.artist_phone_number_repository.exists_by_id( global_participant_id=fan_list.id ): raise ArtistPhoneNumberNotFoundError