from unittest import mock import pytest from dirty_equals import IsList from fansifter_common.auth.account import Account, AccountAccess from dmp.ad_accounts.enums import AdAccountPlatform from dmp.ad_accounts.models import AdAccountDbt from dmp.app_connections.enums import AppConnectionStatus from dmp.meta.dtos import MetaAdAccountOverview from dmp.meta.enums import MetaUserConnectionStatus from dmp.meta.handlers import GetMetaAdAccountsHandler, GetMetaAdAccountsRequest from dmp.meta.models import ( MetaAdAccount, MetaAdReportingConnection, MetaUserAdAccount, MetaUserConnection, ) from tests.unit.faker import FakerTyped from tests.unit.types import CreateModel, CreateReportingModel class TestGetMetaAdAccountsHandler: @pytest.mark.db def test_get_ad_accounts_empty( self, handler: GetMetaAdAccountsHandler, identity_id: str ) -> None: ad_accounts = handler.handle( GetMetaAdAccountsRequest(identity_id=identity_id), ) assert ad_accounts == [] @pytest.mark.db def test_get_ad_accounts_self_sharing_account_without_vendor( self, handler: GetMetaAdAccountsHandler, create_model: CreateModel, identity_id: str, ) -> None: ad_account = create_model(MetaAdAccount, business_account_picture_key=None) create_model( MetaUserConnection, is_valid=True, identity_id=identity_id, ad_accounts=[ad_account], ) ad_accounts = handler.handle(GetMetaAdAccountsRequest(identity_id=identity_id)) assert ad_accounts == [ MetaAdAccountOverview( id=ad_account.id, user_ad_account_id=None, external_id=ad_account.external_id, name=ad_account.name or "", business_account_name=ad_account.business_account_name, business_account_picture=ad_account.business_account_picture, vendor_id=None, subaccount_id=None, is_self_connected=True, user_connection_status=MetaUserConnectionStatus.TOS_NOT_ACCEPTED, user_self_connected=True, ad_reporting_connection_status=AppConnectionStatus.NOT_CONNECTED, ad_reporting_self_connected=False, campaigns_count=ad_account.campaigns_count, ) ] @pytest.mark.db def test_get_ad_accounts_self_sharing_and_reporting_account_multiple( self, handler: GetMetaAdAccountsHandler, create_model: CreateModel, identity_id: str, account: Account, ) -> None: reporting_connection_status = AppConnectionStatus.PENDING ad_account_1 = create_model( MetaAdAccount, business_account_picture_key=None, ) ad_account_1.user_custom_audience_tos_accepted = True ad_account_2 = create_model( MetaAdAccount, name=None, business_account_id=None, business_account_name=None, business_account_picture_key=None, ) user_connection = create_model( MetaUserConnection, is_valid=True, identity_id=identity_id, ad_accounts=[ad_account_1], ) user_ad_account_1 = create_model( MetaUserAdAccount, ad_account_id=ad_account_1.id, identity_id=user_connection.identity_id, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) create_model( MetaAdReportingConnection, status=reporting_connection_status, identity_id=identity_id, ad_accounts=[ad_account_1, ad_account_2], ) user_ad_account_2 = create_model( MetaUserAdAccount, ad_account_id=ad_account_2.id, identity_id=user_connection.identity_id, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) result = handler.handle(GetMetaAdAccountsRequest(identity_id=identity_id)) assert result == IsList( MetaAdAccountOverview.model_construct( id=ad_account_1.id, user_ad_account_id=user_ad_account_1.id, external_id=ad_account_1.external_id, name=ad_account_1.name or "", business_account_name=ad_account_1.business_account_name, business_account_picture=ad_account_1.business_account_picture, vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, is_self_connected=True, user_connection_status=MetaUserConnectionStatus.CONNECTED, user_self_connected=True, ad_reporting_connection_status=reporting_connection_status, ad_reporting_self_connected=True, campaigns_count=ad_account_1.campaigns_count, ), MetaAdAccountOverview.model_construct( id=ad_account_2.id, user_ad_account_id=user_ad_account_2.id, external_id=ad_account_2.external_id, name=ad_account_2.external_id, business_account_name=ad_account_2.business_account_name, business_account_picture=ad_account_2.business_account_picture, vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, is_self_connected=True, user_connection_status=MetaUserConnectionStatus.NOT_CONNECTED, user_self_connected=False, ad_reporting_connection_status=reporting_connection_status, ad_reporting_self_connected=True, campaigns_count=ad_account_2.campaigns_count, ), check_order=False, ) @pytest.mark.db def test_get_ad_accounts_self_reporting_account( self, handler: GetMetaAdAccountsHandler, create_model: CreateModel, identity_id: str, account: Account, ) -> None: ad_account = create_model( MetaAdAccount, name=None, business_account_id=None, business_account_name=None, business_account_picture_key=None, ) user_ad_account = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) create_model( MetaUserConnection, is_valid=False, identity_id=identity_id, ad_accounts=[ad_account], ) reporting_user_connection = create_model( MetaAdReportingConnection, identity_id=identity_id, ad_accounts=[ad_account] ) ad_accounts = handler.handle(GetMetaAdAccountsRequest(identity_id=identity_id)) assert ad_accounts == [ MetaAdAccountOverview.model_construct( id=ad_account.id, user_ad_account_id=user_ad_account.id, external_id=ad_account.external_id, name=ad_account.external_id, business_account_name=ad_account.business_account_name, business_account_picture=ad_account.business_account_picture, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, is_self_connected=True, user_connection_status=MetaUserConnectionStatus.INVALID, user_self_connected=True, ad_reporting_connection_status=reporting_user_connection.status, ad_reporting_self_connected=True, campaigns_count=ad_account.campaigns_count, ) ] @pytest.mark.db def test_get_ad_accounts_self_and_vendor_sharing_and_reporting_account_multiple_overlapping( self, handler: GetMetaAdAccountsHandler, create_model: CreateModel, auth_service_mock: mock.MagicMock, fake: FakerTyped, ) -> None: account_1 = Account(vendor_id=1, subaccount_id=1) account_2 = Account(vendor_id=2, subaccount_id=2) account_3 = Account(vendor_id=3, subaccount_id=3) reporting_connection_status_1 = AppConnectionStatus.SYNCING reporting_connection_status_2 = AppConnectionStatus.ERROR reporting_connection_status_3 = AppConnectionStatus.CONNECTED auth_service_mock.authorize_for_permission.return_value = AccountAccess( accounts=[account_1, account_2], ) identity_id_1 = fake.uuid4_string() identity_id_2 = fake.uuid4_string() identity_id_3 = fake.uuid4_string() identity_id_4 = fake.uuid4_string() ad_account_1 = create_model( MetaAdAccount, id="ad_account_id_1", business_account_picture_key=None, ) ad_account_2 = create_model( MetaAdAccount, id="ad_account_id_2", business_account_picture_key=None, ) ad_account_3 = create_model( MetaAdAccount, business_account_picture_key=None, ) # user 1 create_model( MetaUserConnection, is_valid=False, identity_id=identity_id_1, ad_accounts=[ad_account_1], ) create_model( MetaUserAdAccount, id="meta_user_ad_account_aa", ad_account_id=ad_account_1.id, identity_id=identity_id_1, vendor_id=account_1.vendor_id, subaccount_id=account_1.subaccount_id, ) # user 2 create_model( MetaUserConnection, is_valid=True, identity_id=identity_id_2, ad_accounts=[ad_account_1], ) user_ad_account_2 = create_model( MetaUserAdAccount, id="meta_user_ad_account_ba", ad_account_id=ad_account_1.id, identity_id=identity_id_2, vendor_id=account_1.vendor_id, subaccount_id=account_1.subaccount_id, ) create_model( MetaAdReportingConnection, status=reporting_connection_status_1, identity_id=identity_id_2, ad_accounts=[ad_account_2], ) user_ad_account_3 = create_model( MetaUserAdAccount, id="meta_user_ad_account_bb", ad_account_id=ad_account_2.id, identity_id=identity_id_2, vendor_id=account_2.vendor_id, subaccount_id=account_2.subaccount_id, ) # user 3 create_model( MetaAdReportingConnection, status=reporting_connection_status_2, identity_id=identity_id_3, ad_accounts=[ad_account_2], ) create_model( MetaUserAdAccount, id="meta_user_ad_account_ca", ad_account_id=ad_account_2.id, identity_id=identity_id_3, vendor_id=account_1.vendor_id, subaccount_id=account_1.subaccount_id, ) # user 4 create_model( MetaAdReportingConnection, status=reporting_connection_status_3, identity_id=identity_id_4, ad_accounts=[ad_account_2, ad_account_3], ) user_ad_account_5 = create_model( MetaUserAdAccount, id="meta_user_ad_account_da", ad_account_id=ad_account_2.id, identity_id=identity_id_4, vendor_id=account_1.vendor_id, subaccount_id=account_1.subaccount_id, ) create_model( MetaUserAdAccount, id="meta_user_ad_account_db", ad_account_id=ad_account_3.id, identity_id=identity_id_4, vendor_id=account_3.vendor_id, subaccount_id=account_3.subaccount_id, ) result = handler.handle(GetMetaAdAccountsRequest(identity_id=identity_id_1)) assert result == IsList( MetaAdAccountOverview.model_construct( id=ad_account_1.id, user_ad_account_id=user_ad_account_2.id, external_id=ad_account_1.external_id, name=ad_account_1.name or "", business_account_name=ad_account_1.business_account_name, business_account_picture=ad_account_1.business_account_picture, vendor_id=account_1.vendor_id, subaccount_id=account_1.subaccount_id, is_self_connected=True, user_connection_status=MetaUserConnectionStatus.TOS_NOT_ACCEPTED, user_self_connected=False, ad_reporting_connection_status=AppConnectionStatus.NOT_CONNECTED, ad_reporting_self_connected=False, campaigns_count=ad_account_1.campaigns_count, ), MetaAdAccountOverview.model_construct( id=ad_account_2.id, user_ad_account_id=user_ad_account_3.id, external_id=ad_account_2.external_id, name=ad_account_2.name or "", business_account_name=ad_account_2.business_account_name, business_account_picture=ad_account_2.business_account_picture, vendor_id=account_2.vendor_id, subaccount_id=account_2.subaccount_id, is_self_connected=False, user_connection_status=MetaUserConnectionStatus.NOT_CONNECTED, user_self_connected=False, ad_reporting_connection_status=AppConnectionStatus.SYNCING, ad_reporting_self_connected=False, campaigns_count=ad_account_2.campaigns_count, ), MetaAdAccountOverview.model_construct( id=ad_account_2.id, user_ad_account_id=user_ad_account_5.id, external_id=ad_account_2.external_id, name=ad_account_2.name or "", business_account_name=ad_account_2.business_account_name, business_account_picture=ad_account_2.business_account_picture, vendor_id=account_1.vendor_id, subaccount_id=account_1.subaccount_id, is_self_connected=False, user_connection_status=MetaUserConnectionStatus.NOT_CONNECTED, user_self_connected=False, ad_reporting_connection_status=AppConnectionStatus.CONNECTED, ad_reporting_self_connected=False, campaigns_count=ad_account_2.campaigns_count, ), check_order=False, ) @pytest.mark.db def test_get_ad_accounts_multi_vendors_reporting_account_same_statuses_deduplicated( self, handler: GetMetaAdAccountsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: connection_status = AppConnectionStatus.SYNCING user_ad_account_id_1 = "a" user_ad_account_id_2 = "b" ad_account = create_model( MetaAdAccount, name=None, business_account_id=None, business_account_name=None, business_account_picture_key=None, ) connection_1 = create_model( MetaAdReportingConnection, status=connection_status, ad_accounts=[ad_account], ) connection_2 = create_model( MetaAdReportingConnection, status=connection_status, ad_accounts=[ad_account], ) create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=connection_1.identity_id, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, id=user_ad_account_id_1, ) create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=connection_2.identity_id, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, id=user_ad_account_id_2, ) ad_account_dbt = create_reporting_model( AdAccountDbt, platform=AdAccountPlatform.META, id=ad_account.external_id, ) result = handler.handle(GetMetaAdAccountsRequest(identity_id=identity_id)) assert result == [ MetaAdAccountOverview.model_construct( id=ad_account.id, user_ad_account_id=user_ad_account_id_1, external_id=ad_account.external_id, name=ad_account_dbt.name, business_account_name=ad_account_dbt.business_account_name, business_account_picture=ad_account.business_account_picture, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, is_self_connected=False, user_connection_status=MetaUserConnectionStatus.NOT_CONNECTED, user_self_connected=False, ad_reporting_connection_status=connection_status, ad_reporting_self_connected=False, campaigns_count=max( ad_account_dbt.campaigns_count or 0, ad_account.campaigns_count or 0 ), ), ]