from dataclasses import dataclass from anydi import singleton from fansifter_common.auth.requests import AuthRequest from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from email_campaigns.automated.exceptions import ( InvalidSourceCampaignIdError, SourceCampaignNotAttachedError, ) from email_campaigns.automated.models import AutomatedEmail from email_campaigns.automated.repositories import ( AutomatedEmailRepository, SourceCampaignRepository, ) from email_campaigns.emails.exceptions import EmailNotFoundError @dataclass(kw_only=True) class DetachSourceCampaignsRequest(AuthRequest): email_id: str source_campaign_ids: list[str] @singleton class DetachSourceCampaignsHandler: # TODO: ---> Permission("automated_email", "edit") permission = Permission("email_campaign", "edit") def __init__( self, auth_service: AuthService, automated_email_repository: AutomatedEmailRepository, source_campaign_repository: SourceCampaignRepository, ) -> None: self.auth_service = auth_service self.automated_email_repository = automated_email_repository self.source_campaign_repository = source_campaign_repository def handle(self, request: DetachSourceCampaignsRequest) -> AutomatedEmail: automated_email = self.automated_email_repository.get(request.email_id) if automated_email is None: raise EmailNotFoundError self.auth_service.authorize_account( request.identity_id, account=automated_email.account, permission=self.permission, ) # Validate that all source campaign IDs exist source_campaigns = self.source_campaign_repository.find_by_ids( request.source_campaign_ids ) source_campaign_by_id = { source_campaign.id: source_campaign for source_campaign in source_campaigns } attached_ids = { conn.source_campaign_id for conn in automated_email.source_campaign_connections } for source_campaign_id in request.source_campaign_ids: if source_campaign_id not in source_campaign_by_id: raise InvalidSourceCampaignIdError if source_campaign_id not in attached_ids: raise SourceCampaignNotAttachedError # Remove associations source_campaign_ids_to_remove = set(request.source_campaign_ids) automated_email.source_campaign_connections = [ conn for conn in automated_email.source_campaign_connections if conn.source_campaign_id not in source_campaign_ids_to_remove ] self.automated_email_repository.save(automated_email) return automated_email