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 fansifter_common.auth.types import Permission from dmp.adapters.db import DefaultDB, transactional from dmp.adapters.fivetran import FivetranClient from dmp.adapters.fivetran.exceptions import FivetranClientError from dmp.adapters.fivetran.models import ConnectCard from dmp.config import Settings from dmp.meta.exceptions import MetaAdReportingConnectionSyncingError from dmp.meta.models import MetaAdReportingConnection from dmp.meta.repositories import ( MetaAdReportingConnectionRepository, ) from dmp.meta.services import MetaUserConnectionService from dmp.meta.utils import generate_fivetran_schema from dmp.meta.validators import MetaAdReportingConnectionValidator @dataclass class ConnectMetaAdReportingRequest(AuthRequest): redirect_uri: str @singleton class ConnectMetaAdReportingHandler: permission = Permission("ad_connection", "connect") def __init__( self, db: DefaultDB, auth_service: AuthService, ad_reporting_connection_repository: MetaAdReportingConnectionRepository, ad_reporting_connection_validator: MetaAdReportingConnectionValidator, user_connection_service: MetaUserConnectionService, fivetran_client: FivetranClient, settings: Settings, ) -> None: self.db = db self.auth_service = auth_service self.ad_reporting_connection_repository = ad_reporting_connection_repository self.ad_reporting_connection_validator = ad_reporting_connection_validator self.user_connection_service = user_connection_service self.fivetran_client = fivetran_client self.settings = settings @transactional def handle( self, request: ConnectMetaAdReportingRequest ) -> tuple[MetaAdReportingConnection, ConnectCard]: self.auth_service.check_owned_resource( request.identity_id, permission=self.permission, resource_id=None, ) self.ad_reporting_connection_validator.validate_uniqueness(request.identity_id) user_connection = self.user_connection_service.get_user_connection( request.identity_id ) ad_account_external_ids = [] if user_connection: ad_account_external_ids = [ ad_account.external_id for ad_account in user_connection.ad_accounts ] fivetran_schema = generate_fivetran_schema( request.identity_id, prefix=self.settings.fivetran_schema_prefix ) try: connection = self.fivetran_client.create_facebook_ads_connection( group_id=self.settings.fivetran_reporting_group_id, schema=fivetran_schema, redirect_uri=request.redirect_uri, accounts=ad_account_external_ids, ) except FivetranClientError as exc: if exc.status_code == 409: raise MetaAdReportingConnectionSyncingError from exc raise exc ad_reporting_connection = MetaAdReportingConnection( fivetran_connector_id=connection.id, fivetran_schema=fivetran_schema, identity_id=request.identity_id, ) self.ad_reporting_connection_repository.add(ad_reporting_connection) return ad_reporting_connection, connection.connect_card