# mypy: disable-error-code=operator import decimal from decimal import Decimal from unittest import mock import pytest from dirty_equals import IsApprox from fansifter_common.auth.account import Account, AccountAccess from dmp.ad_reporting.enums import ( AdReportingActionType, AdReportingBudgetType, AdReportingObjective, AdReportingPlatform, AdReportingRateType, ) from dmp.ad_reporting.exceptions import AdReportingReportNotFoundError from dmp.ad_reporting.handlers import ( GetAdReportingReportAdSetsHandler, GetAdReportingReportAdSetsRequest, ) from dmp.ad_reporting.models import ( AdReportingAdSetCountryDbt, AdReportingAdSetDbt, AdReportingCampaignBenchmarkByAccountArtistCountryDbt, AdReportingCampaignBenchmarkByAccountArtistDbt, AdReportingCampaignBenchmarkByAccountCountryDbt, AdReportingCampaignBenchmarkByAccountDbt, AdReportingCampaignDbt, AdReportingReport, ) from dmp.meta.models import MetaAdAccount, MetaUserAdAccount from tests.unit.faker import FakerTyped from tests.unit.types import CreateModel, CreateReportingModel class TestGetAdReportingReportAdSetsHandler: @pytest.mark.db def test_get_report_ad_sets( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, ) -> None: ad_account_1 = create_model(MetaAdAccount) ad_account_2 = create_model(MetaAdAccount) create_model( MetaUserAdAccount, ad_account_id=ad_account_1.id, identity_id=identity_id, ) create_model( MetaUserAdAccount, ad_account_id=ad_account_2.id, identity_id=identity_id, ) campaign_1 = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account_1.external_id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, ) ad_set_1 = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account_1.external_id, campaign_id=campaign_1.id, platform=AdReportingPlatform.META, campaign_objective=campaign_1.objective, ) # This ad set should not be returned campaign_2 = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account_2.external_id, platform=AdReportingPlatform.META, ) create_reporting_model( AdReportingAdSetDbt, account_id=ad_account_1.external_id, campaign_id=campaign_2.id, platform=AdReportingPlatform.META, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign_1.id}, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) assert response.summary.total == 1 assert response.items[0].id == ad_set_1.id @pytest.mark.db def test_get_report_ad_sets_not_found( self, handler: GetAdReportingReportAdSetsHandler, identity_id: str, fake: FakerTyped, ) -> None: with pytest.raises(AdReportingReportNotFoundError): handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=fake.uuid4_string(), search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) @pytest.mark.db def test_get_ad_reporting_report_ads_single_bm( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, auth_service_mock: mock.MagicMock, ) -> None: ad_account = create_model(MetaAdAccount) user_ad_account = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id ) auth_service_mock.authorize_for_permission.return_value = AccountAccess( accounts=[ Account( vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, ) ] ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_id=campaign.id, campaign_objective=campaign.objective, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) bm = create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, ) artist_bm = create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, global_participant_id=ad_set.campaign_global_participant_id, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) assert response assert response.items assert response.items[0].benchmark == bm.rate assert response.items[0].vs_benchmark == ad_set.rate - bm.rate assert response.items[0].artist_benchmark == artist_bm.rate assert response.items[0].vs_artist_benchmark == ad_set.rate - artist_bm.rate @pytest.mark.db def test_get_ad_reporting_report_ads_multiple_bm( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, ) -> None: platform = AdReportingPlatform.META objective = AdReportingObjective.OUTCOME_AWARENESS global_participant_id_1 = fake.uuid4_string() global_participant_id_2 = fake.uuid4_string() ad_account = create_model(MetaAdAccount) user_ad_account_1 = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id ) user_ad_account_2 = create_model(MetaUserAdAccount, ad_account_id=ad_account.id) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=platform, objective=objective, _global_participant_ids=[global_participant_id_1, global_participant_id_2], ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=platform, campaign_id=campaign.id, campaign_objective=campaign.objective, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, global_participant_id=global_participant_id_1, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, global_participant_id=global_participant_id_2, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) assert response assert response.items assert response.items[0].benchmark is None assert response.items[0].vs_benchmark is None assert response.items[0].artist_benchmark is None assert response.items[0].vs_artist_benchmark is None @pytest.mark.db def test_get_report_ad_sets_with_country_filter_empty( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, auth_service_mock: mock.MagicMock, ) -> None: ad_account = create_model(MetaAdAccount) user_ad_account = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, ) auth_service_mock.authorize_for_permission.return_value = AccountAccess( accounts=[ Account( vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, ) ] ) ad_set = create_reporting_model( AdReportingAdSetDbt, platform=AdReportingPlatform.META, account_id=ad_account.external_id, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, ) create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set.campaign_id, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="GB", ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={ad_set.campaign_id}, ) response = handler.handle( GetAdReportingReportAdSetsRequest( report_id=report.id, identity_id=identity_id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, countries=["US"], ) ) assert response.summary.total == 1 assert response.summary.clicks == 0 assert response.summary.spend_usd == 0 assert response.summary.reach is None assert response.summary.actions is None assert response.summary.rate is None assert len(response.items) == 1 assert response.items[0].accounts == {user_ad_account.account} assert response.items[0].clicks == 0 assert response.items[0].spend_usd == 0 assert response.items[0].reach is None assert response.items[0].frequency is None assert response.items[0].artist_benchmark is None assert response.items[0].benchmark is None assert response.items[0].vs_artist_benchmark is None @pytest.mark.db def test_get_report_ad_sets_with_country_filter_recalculate_single_ad( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, auth_service_mock: mock.MagicMock, ) -> None: ad_account = create_model(MetaAdAccount) user_ad_account = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, ) auth_service_mock.authorize_for_permission.return_value = AccountAccess( accounts=[ Account( vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, ) ] ) ad_set = create_reporting_model( AdReportingAdSetDbt, name="a", account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, ) ad_set_2 = create_reporting_model( AdReportingAdSetDbt, name="b", account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, ) create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set.campaign_id, external_id=ad_set.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="GB", ) ad_set_country_1 = create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set.campaign_id, external_id=ad_set.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="US", estimated_ad_recallers=fake.integer(), ) ad_set_country_2 = create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set.campaign_id, external_id=ad_set.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="EE", estimated_ad_recallers=fake.integer(), ) create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set_2.campaign_id, external_id=ad_set_2.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="US", estimated_ad_recallers=fake.integer(), ) create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set_2.campaign_id, external_id=ad_set_2.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="EE", estimated_ad_recallers=fake.integer(), ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={ad_set.campaign_id}, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, countries=["US", "EE"], ) ) assert response.summary.total == 1 assert ( response.summary.clicks == ad_set_country_1.clicks + ad_set_country_2.clicks ) assert ad_set_country_1.reach and ad_set_country_2.reach assert ad_set_country_1.estimated_ad_recallers is not None assert ad_set_country_2.estimated_ad_recallers is not None assert response.summary.reach == ad_set_country_1.reach + ad_set_country_2.reach assert ( response.summary.spend_usd == ad_set_country_1.spend_usd + ad_set_country_2.spend_usd ) assert response.summary.rate == IsApprox( Decimal( ( ad_set_country_1.estimated_ad_recallers + ad_set_country_2.estimated_ad_recallers ) / (ad_set_country_1.reach + ad_set_country_2.reach) ), delta=Decimal("0.001"), ) assert len(response.items) == 1 assert response.items[0].accounts == {user_ad_account.account} assert ( response.items[0].clicks == ad_set_country_1.clicks + ad_set_country_2.clicks ) assert ( response.items[0].reach == ad_set_country_1.reach + ad_set_country_2.reach ) assert ( response.items[0].spend_usd == ad_set_country_1.spend_usd + ad_set_country_2.spend_usd ) assert response.items[0].rate == IsApprox( Decimal( ( ad_set_country_1.estimated_ad_recallers + ad_set_country_2.estimated_ad_recallers ) / (ad_set_country_1.reach + ad_set_country_2.reach) ), delta=Decimal("0.001"), ) assert response.items[0].artist_benchmark is None assert response.items[0].benchmark is None assert response.items[0].vs_artist_benchmark is None @pytest.mark.db def test_get_report_campaigns_with_country_filter_multiple_ad_sets( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, auth_service_mock: mock.MagicMock, ) -> None: ad_account = create_model(MetaAdAccount) user_ad_account = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, ) auth_service_mock.authorize_for_permission.return_value = AccountAccess( accounts=[ Account( vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, ) ] ) ad_set_1 = create_reporting_model( AdReportingAdSetDbt, name="a", account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, rate_type=AdReportingRateType.CTR, action_type=AdReportingActionType.CLICKS, ) ad_set_2 = create_reporting_model( AdReportingAdSetDbt, name="b", account_id=ad_account.external_id, platform=AdReportingPlatform.TIKTOK, campaign_objective=AdReportingObjective.VIDEO_VIEWS, currency=ad_set_1.currency, rate_type=AdReportingRateType.EARR, action_type=AdReportingActionType.EAR, ) create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set_1.campaign_id, external_id=ad_set_1.external_id, name=ad_set_1.name, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="GB", ) ad_set_country_1 = create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set_1.campaign_id, external_id=ad_set_1.external_id, name=ad_set_1.name, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="US", ) create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set_1.campaign_id, external_id=ad_set_1.external_id, name=ad_set_1.name, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="EE", estimated_ad_recallers=fake.integer(), ) ad_set_country_2 = create_reporting_model( AdReportingAdSetCountryDbt, name=ad_set_2.name, campaign_id=ad_set_2.campaign_id, external_id=ad_set_2.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.TIKTOK, campaign_objective=AdReportingObjective.VIDEO_VIEWS, country_code="US", ) create_reporting_model( AdReportingAdSetCountryDbt, name=ad_set_2.name, campaign_id=ad_set_2.campaign_id, external_id=ad_set_2.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.TIKTOK, campaign_objective=AdReportingObjective.VIDEO_VIEWS, country_code="GB", estimated_ad_recallers=fake.integer(), ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={ad_set_1.campaign_id, ad_set_2.campaign_id}, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.desc"], limit=10, offset=0, countries=["US"], ) ) assert response.summary.total == 2 assert ( response.summary.clicks == ad_set_country_1.clicks + ad_set_country_2.clicks ) assert ( response.summary.impressions == ad_set_country_1.impressions + ad_set_country_2.impressions ) assert ad_set_country_1.reach and ad_set_country_2.reach assert response.summary.reach == ad_set_country_1.reach + ad_set_country_2.reach assert ( response.summary.estimated_ad_recallers and ad_set_country_1.estimated_ad_recallers and ad_set_country_2.estimated_ad_recallers ) assert ( response.summary.estimated_ad_recallers == ad_set_country_1.estimated_ad_recallers + ad_set_country_2.estimated_ad_recallers ) assert ( response.summary.views_p25 == ad_set_country_1.views_p25 + ad_set_country_2.views_p25 ) assert response.summary.views == ad_set_country_1.views + ad_set_country_2.views assert ( response.summary.purchases and ad_set_country_1.purchases and ad_set_country_2.purchases ) assert ( response.summary.purchases == int(ad_set_country_1.purchases) + ad_set_country_2.purchases ) assert ( response.summary.follows and ad_set_country_1.follows and ad_set_country_2.follows ) assert ( response.summary.follows == ad_set_country_1.follows + ad_set_country_2.follows ) assert ( response.summary.spend_usd == ad_set_country_1.spend_usd + ad_set_country_2.spend_usd ) assert response.summary.actions is None assert response.summary.action_type is None assert response.summary.rate is None assert response.summary.rate_type is None assert response.summary.cost_per_action_usd is None assert response.summary.cost_per_action is None assert ad_set_country_1.reach and ad_set_country_2.reach assert response.summary.frequency == IsApprox( decimal.Decimal(ad_set_country_1.impressions + ad_set_country_2.impressions) / (ad_set_country_1.reach + ad_set_country_2.reach) ) assert ad_set_1.daily_budget is not None assert ad_set_2.daily_budget is not None assert response.summary.budget == ad_set_1.daily_budget + ad_set_2.daily_budget assert response.summary.budget_type == AdReportingBudgetType.DAILY_BUDGET assert len(response.items) == 2 assert response.items[0].id == ad_set_2.id assert response.items[0].account_id == ad_account.external_id assert response.items[0].accounts == {user_ad_account.account} assert response.items[0].action_type == ad_set_2.action_type assert response.items[0].currency == ad_set_2.currency assert response.items[0].effective_status == ad_set_2.effective_status assert response.items[0].end_at == ad_set_2.end_at assert response.items[0].name == ad_set_2.name assert response.items[0].objective == ad_set_2.campaign_objective assert response.items[0].platform == ad_set_2.platform assert response.items[0].rate_type == ad_set_2.rate_type assert response.items[0].start_at == ad_set_2.start_at assert response.items[0].targeting_countries == set( ad_set_2.targeting_countries ) assert response.items[0].actions == ad_set_country_2.actions assert response.items[0].clicks == ad_set_country_2.clicks assert response.items[0].cost_per_action == IsApprox( ad_set_country_2.spend / ad_set_country_2.actions ) assert response.items[0].cost_per_action_usd == IsApprox( ad_set_country_2.spend_usd / ad_set_country_2.actions ) assert ( response.items[0].estimated_ad_recallers == ad_set_country_2.estimated_ad_recallers ) assert response.items[0].follows == ad_set_country_2.follows assert ad_set_country_2.reach assert response.items[0].frequency == IsApprox( decimal.Decimal(ad_set_country_2.impressions / ad_set_country_2.reach) ) assert response.items[0].impressions == ad_set_country_2.impressions assert response.items[0].purchases == ad_set_country_2.purchases assert response.items[0].rate == IsApprox( Decimal((ad_set_country_2.views or 0) / ad_set_country_2.impressions), delta=Decimal("0.001"), ) assert response.items[0].reach == ad_set_country_2.reach assert response.items[0].spend == ad_set_country_2.spend assert response.items[0].spend_usd == ad_set_country_2.spend_usd assert response.items[0].views == ad_set_country_2.views assert response.items[0].views_p25 == ad_set_country_2.views_p25 assert response.items[0].artist_benchmark is None assert response.items[0].benchmark is None assert response.items[0].vs_artist_benchmark is None assert response.items[0].vs_artist_benchmark is None assert response.items[1].id == ad_set_1.id assert response.items[1].account_id == ad_account.external_id assert response.items[1].accounts == {user_ad_account.account} assert response.items[1].action_type == ad_set_1.action_type assert response.items[1].currency == ad_set_1.currency assert response.items[1].effective_status == ad_set_1.effective_status assert response.items[1].end_at == ad_set_1.end_at assert response.items[1].name == ad_set_1.name assert response.items[1].objective == ad_set_1.campaign_objective assert response.items[1].platform == ad_set_1.platform assert response.items[1].rate_type == ad_set_1.rate_type assert response.items[1].start_at == ad_set_1.start_at assert response.items[1].targeting_countries == set( ad_set_1.targeting_countries ) assert response.items[1].actions == ad_set_country_1.actions assert response.items[1].clicks == ad_set_country_1.clicks assert response.items[1].cost_per_action == IsApprox( ad_set_country_1.spend / ad_set_country_1.actions ) assert response.items[1].cost_per_action_usd == IsApprox( ad_set_country_1.spend_usd / ad_set_country_1.actions ) assert ( response.items[1].estimated_ad_recallers == ad_set_country_1.estimated_ad_recallers ) assert response.items[1].follows == ad_set_country_1.follows assert ad_set_country_1.reach assert response.items[1].frequency == IsApprox( decimal.Decimal(ad_set_country_1.impressions / ad_set_country_1.reach) ) assert response.items[1].impressions == ad_set_country_1.impressions assert response.items[1].purchases == ad_set_country_1.purchases assert response.items[1].rate == IsApprox( Decimal( (ad_set_country_1.estimated_ad_recallers or 0) / ad_set_country_1.reach ), delta=Decimal("0.001"), ) assert response.items[1].reach == ad_set_country_1.reach assert response.items[1].spend == ad_set_country_1.spend assert response.items[1].spend_usd == ad_set_country_1.spend_usd assert response.items[1].views == ad_set_country_1.views assert response.items[1].views_p25 == ad_set_country_1.views_p25 assert response.items[1].artist_benchmark is None assert response.items[1].benchmark is None assert response.items[1].vs_artist_benchmark is None assert response.items[1].vs_artist_benchmark is None @pytest.mark.db def test_get_report_ad_sets_with_country_filter_multiple_ads_summary_matching( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, ) -> None: ad_account = create_model(MetaAdAccount) create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, ) ad_set_1 = create_reporting_model( AdReportingAdSetDbt, campaign_id=campaign.id, account_id=ad_account.external_id, platform=campaign.platform, campaign_objective=campaign.objective, action_type=campaign.action_type, ) ad_set_2 = create_reporting_model( AdReportingAdSetDbt, campaign_id=campaign.id, account_id=ad_account.external_id, platform=campaign.platform, campaign_objective=campaign.objective, currency=ad_set_1.currency, ) ad_set_country_1 = create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set_1.campaign_id, external_id=ad_set_1.external_id, name=ad_set_1.name, account_id=ad_account.external_id, platform=ad_set_1.platform, campaign_objective=ad_set_1.campaign_objective, country_code="GB", action_type=campaign.action_type, ) ad_set_country_2 = create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set_2.campaign_id, external_id=ad_set_2.external_id, name=ad_set_2.name, account_id=ad_account.external_id, platform=ad_set_2.platform, campaign_objective=ad_set_2.campaign_objective, country_code="US", action_type=campaign.action_type, ) create_reporting_model( AdReportingAdSetCountryDbt, campaign_id=ad_set_1.campaign_id, external_id=ad_set_1.external_id, name=ad_set_1.name, account_id=ad_account.external_id, platform=ad_set_1.platform, campaign_objective=ad_set_1.campaign_objective, country_code="EE", ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.desc"], limit=10, offset=0, countries=["US", "GB"], ) ) assert response.summary.total == 2 assert ( response.summary.clicks == ad_set_country_1.clicks + ad_set_country_2.clicks ) assert ( response.summary.impressions == ad_set_country_1.impressions + ad_set_country_2.impressions ) assert ad_set_country_1.reach and ad_set_country_2.reach assert response.summary.reach == ad_set_country_1.reach + ad_set_country_2.reach assert ( response.summary.estimated_ad_recallers and ad_set_country_1.estimated_ad_recallers and ad_set_country_2.estimated_ad_recallers ) assert ( response.summary.estimated_ad_recallers == ad_set_country_1.estimated_ad_recallers + ad_set_country_2.estimated_ad_recallers ) assert ( response.summary.views_p25 == ad_set_country_1.views_p25 + ad_set_country_2.views_p25 ) assert response.summary.views == ad_set_country_1.views + ad_set_country_2.views assert ( response.summary.purchases and ad_set_country_1.purchases and ad_set_country_2.purchases ) assert ( response.summary.purchases == int(ad_set_country_1.purchases) + ad_set_country_2.purchases ) assert ( response.summary.follows and ad_set_country_1.follows and ad_set_country_2.follows ) assert ( response.summary.follows == ad_set_country_1.follows + ad_set_country_2.follows ) assert ( response.summary.spend_usd == ad_set_country_1.spend_usd + ad_set_country_2.spend_usd ) assert ( response.summary.actions == ad_set_country_1.actions + ad_set_country_2.actions ) assert response.summary.rate == IsApprox( Decimal( ( ad_set_country_1.estimated_ad_recallers + ad_set_country_2.estimated_ad_recallers ) / (ad_set_country_1.reach + ad_set_country_2.reach) ) ) assert response.summary.cost_per_action_usd == IsApprox( (ad_set_country_1.spend_usd + ad_set_country_2.spend_usd) / (ad_set_country_1.actions + ad_set_country_2.actions) ) assert response.summary.cost_per_action is None assert response.summary.frequency == IsApprox( decimal.Decimal(ad_set_country_1.impressions + ad_set_country_2.impressions) / (ad_set_country_1.reach + ad_set_country_2.reach) ) assert ad_set_1.daily_budget is not None assert ad_set_2.daily_budget is not None assert response.summary.budget == ad_set_1.daily_budget + ad_set_2.daily_budget assert response.summary.budget_type == AdReportingBudgetType.DAILY_BUDGET assert len(response.items) == 2 @pytest.mark.db def test_get_report_ad_sets_with_country_filter_showing_benchmarks( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, auth_service_mock: mock.MagicMock, ) -> None: ad_account = create_model(MetaAdAccount) global_participant_id = fake.uuid4_string() country_code = fake.country() platform = AdReportingPlatform.META objective = AdReportingObjective.OUTCOME_AWARENESS user_ad_account = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, ) auth_service_mock.authorize_for_permission.return_value = AccountAccess( accounts=[ Account( vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, ) ] ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=platform, objective=objective, global_participant_id=global_participant_id, ) create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=platform, campaign_id=campaign.id, campaign_objective=campaign.objective, campaign_global_participant_id=campaign.global_participant_id, ) create_reporting_model( AdReportingAdSetCountryDbt, account_id=ad_account.external_id, platform=platform, country_code=country_code, campaign_id=campaign.id, campaign_objective=campaign.objective, campaign_global_participant_id=campaign.global_participant_id, ) benchmark = create_reporting_model( AdReportingCampaignBenchmarkByAccountCountryDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, country_code=country_code, platform=platform, objective=objective, ) artist_benchmark = create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistCountryDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, global_participant_id=global_participant_id, country_code=country_code, platform=platform, objective=objective, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, campaign_id=None, search=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, countries=[country_code], ) ) assert len(response.items) == 1 assert response.items[0].benchmark == benchmark.rate assert response.items[0].artist_benchmark == artist_benchmark.rate @pytest.mark.db def test_get_report_ad_sets_with_country_filter_not_showing_benchmarks( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) global_participant_id = fake.uuid4_string() country_code_1 = fake.uuid4_string() country_code_2 = fake.uuid4_string() platform = AdReportingPlatform.META objective = AdReportingObjective.OUTCOME_AWARENESS user_ad_account = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=platform, objective=objective, global_participant_id=global_participant_id, ) create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=platform, campaign_id=campaign.id, campaign_objective=campaign.objective, campaign_global_participant_id=campaign.global_participant_id, ) create_reporting_model( AdReportingAdSetCountryDbt, account_id=ad_account.external_id, platform=platform, country_code=country_code_1, campaign_id=campaign.id, campaign_objective=campaign.objective, campaign_global_participant_id=campaign.global_participant_id, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountCountryDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, country_code=country_code_1, platform=platform, objective=objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistCountryDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, global_participant_id=global_participant_id, country_code=country_code_1, platform=platform, objective=objective, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, campaign_id=None, search=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, countries=[country_code_1, country_code_2], ) ) assert len(response.items) == 1 assert response.items[0].artist_benchmark is None assert response.items[0].benchmark is None @pytest.mark.db def test_get_report_ad_sets_country_filter_with_zeros( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) global_participant_id = fake.uuid4_string() platform = AdReportingPlatform.META objective = AdReportingObjective.OUTCOME_AWARENESS create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=platform, objective=objective, global_participant_id=global_participant_id, ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=platform, campaign_id=campaign.id, campaign_objective=campaign.objective, campaign_global_participant_id=campaign.global_participant_id, ) create_reporting_model( AdReportingAdSetCountryDbt, account_id=ad_account.external_id, external_id=ad_set.external_id, platform=platform, country_code="US", campaign_id=campaign.id, campaign_objective=campaign.objective, campaign_global_participant_id=campaign.global_participant_id, impressions=0, clicks=0, reach=0, actions=0, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], countries=["US"], limit=10, offset=0, ) ) assert response @pytest.mark.db def test_get_ad_reporting_report_ads_single_vendor_access( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, auth_service_mock: mock.MagicMock, ) -> None: platform = AdReportingPlatform.META objective = AdReportingObjective.OUTCOME_AWARENESS global_participant_id_1 = fake.uuid4_string() global_participant_id_2 = fake.uuid4_string() ad_account = create_model(MetaAdAccount) user_ad_account_1 = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id ) user_ad_account_2 = create_model(MetaUserAdAccount, ad_account_id=ad_account.id) account = Account( vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, ) auth_service_mock.authorize_for_permission.return_value = AccountAccess( accounts=[account] ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=platform, objective=objective, _global_participant_ids=[global_participant_id_1, global_participant_id_2], ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=platform, campaign_id=campaign.id, campaign_objective=campaign.objective, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, global_participant_id=global_participant_id_1, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, global_participant_id=global_participant_id_2, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) assert response assert response.items assert response.items[0].accounts == {account} @pytest.mark.db def test_get_ad_reporting_report_ads_multiple_vendor_access( self, handler: GetAdReportingReportAdSetsHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, auth_service_mock: mock.MagicMock, ) -> None: platform = AdReportingPlatform.META objective = AdReportingObjective.OUTCOME_AWARENESS global_participant_id_1 = fake.uuid4_string() global_participant_id_2 = fake.uuid4_string() ad_account = create_model(MetaAdAccount) user_ad_account_1 = create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id ) user_ad_account_2 = create_model(MetaUserAdAccount, ad_account_id=ad_account.id) account_1 = Account( vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, ) account_2 = Account( vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, ) auth_service_mock.authorize_for_permission.return_value = AccountAccess( accounts=[account_1, account_2] ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=platform, objective=objective, _global_participant_ids=[global_participant_id_1, global_participant_id_2], ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=platform, campaign_id=campaign.id, campaign_objective=campaign.objective, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, global_participant_id=global_participant_id_1, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, platform=ad_set.platform, objective=ad_set.campaign_objective, global_participant_id=global_participant_id_2, ) response = handler.handle( GetAdReportingReportAdSetsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) assert response assert response.items assert response.items[0].accounts == {account_1, account_2}