from dataclasses import dataclass from anydi import singleton from fansifter_common.auth.exceptions import PermissionDenied from fansifter_common.auth.requests import AuthRequest 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_ALLOW_AUDIENCE_EXPORT_TO_FILE, Features from dmp.audiences.enums import ( AudienceExportFormat, AudienceExportJustification, AudienceExportReason, AudienceTarget, ) from dmp.audiences.exceptions import AudienceTargetNotSupportedError, EmptyAudienceError from dmp.audiences.models import AudienceExport from dmp.audiences.repositories import AudienceExportRepository from dmp.audiences.services import AudienceService @dataclass class ExportAudienceRequest(AuthRequest): audience_id: str reason: AudienceExportReason justification: AudienceExportJustification reason_notes: str | None @singleton class ExportAudienceHandler: permission = Permission("audience", "export_to_csv") def __init__( self, db: DefaultDB, reporting_db: ReportingDB, auth_service: AuthService, audience_service: AudienceService, audience_export_repository: AudienceExportRepository, features: Features, ) -> None: self.db = db self.reporting_db = reporting_db self.auth_service = auth_service self.audience_service = audience_service self.audience_export_repository = audience_export_repository self.features = features def handle(self, request: ExportAudienceRequest) -> AudienceExport: if not self.features.is_on_for_identity( feature_flag_name=AUDIENCE_ALLOW_AUDIENCE_EXPORT_TO_FILE, identity_id=request.identity_id, ): raise PermissionDenied with self.db.transaction(): audience = self.audience_service.get_audience(request.audience_id) self.auth_service.check_account_resource( request.identity_id, account=audience.account, permission=self.permission, resource_id=audience.id, ) if audience.target == AudienceTarget.TEXT: raise AudienceTargetNotSupportedError( "Export audience target not supported" ) latest_snapshot = audience.latest_snapshot if latest_snapshot is None or not latest_snapshot.fan_count: raise EmptyAudienceError export = AudienceExport( audience=audience, snapshot=latest_snapshot, format=AudienceExportFormat.CSV, reason=request.reason, justification=request.justification, reason_notes=request.reason_notes, created_by=request.identity_id, ) self.audience_service.export_audience_to_csv(export) self.audience_export_repository.add(export) return export