from dataclasses import dataclass from anydi import singleton from fansifter_common.auth.identity import Identity from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from dmp.adapters.db import DefaultDB, ReportingDB from dmp.adapters.features import AUDIENCE_SHOW_SMS_CAMPAIGNS_PAGE, Features from dmp.audiences.enums import AudienceTarget from dmp.audiences.exceptions import AudienceTargetNotSupportedError from dmp.audiences.filters import AudienceFilters from dmp.audiences.models import Audience from dmp.audiences.services import AudienceService from dmp.audiences.validators import AudienceValidator from dmp.rosters.services import GlobalFanDataAccessService @dataclass class UpdateAudienceRequest: identity: Identity audience_id: str name: str target: AudienceTarget filters: AudienceFilters @singleton class UpdateAudienceHandler: ad_target_permission = Permission("audience", "edit_ad_target") email_target_permission = Permission("audience", "edit_email_target") text_target_permission = Permission("audience", "edit_text_target") def __init__( self, db: DefaultDB, reporting_db: ReportingDB, auth_service: AuthService, audience_service: AudienceService, audience_validator: AudienceValidator, global_fandata_access_service: GlobalFanDataAccessService, features: Features, ) -> None: self.db = db self.reporting_db = reporting_db self.auth_service = auth_service self.audience_service = audience_service self.audience_validator = audience_validator self.global_fandata_access_service = global_fandata_access_service self.features = features def handle(self, request: UpdateAudienceRequest) -> Audience: with self.db.transaction(), self.reporting_db.transaction(): audience = self.audience_service.get_audience( audience_id=request.audience_id ) match audience.target: case AudienceTarget.EMAIL: self.auth_service.check_account_resource( request.identity.id, account=audience.account, permission=self.email_target_permission, ) case AudienceTarget.ADS: self.auth_service.check_account_resource( request.identity.id, account=audience.account, permission=self.ad_target_permission, ) case AudienceTarget.TEXT if self.features.is_on_for_identity( feature_flag_name=AUDIENCE_SHOW_SMS_CAMPAIGNS_PAGE, identity_id=request.identity.id, ): self.auth_service.check_account_resource( request.identity.id, account=audience.account, permission=self.text_target_permission, ) case _: raise AudienceTargetNotSupportedError # Validate audience name under account if name is changed if audience.name.lower() != request.name.lower(): self.audience_validator.validate_name( name=request.name, account=audience.account ) # Validate fandata_list_ids self.audience_validator.validate_fandata_list( fandata_list_ids=audience.fandata_list_ids, account=audience.account, target=request.target, ) # Validate TEXT audience if request.target == AudienceTarget.TEXT: self.audience_validator.validate_artist_has_phone_number( fandata_list_ids=audience.fandata_list_ids ) global_fandata_list_enabled = ( self.global_fandata_access_service.is_enabled_for_any_vendor( vendor_ids=[audience.vendor_id], ) ) audience.name = request.name audience.target = request.target audience.filters = request.filters audience.updated_by = request.identity.id self.audience_service.refresh_audience( audience, identity=request.identity, is_global=global_fandata_list_enabled, ) return audience