# mypy: disable-error-code=operator import decimal from decimal import Decimal import pytest from dirty_equals import IsApprox from fansifter_common.auth.account import Account from dmp.ad_reporting.enums import ( AdReportingActionType, AdReportingBudgetType, AdReportingObjective, AdReportingPlatform, AdReportingRateType, ) from dmp.ad_reporting.exceptions import AdReportingReportNotFoundError from dmp.ad_reporting.handlers import ( GetAdReportingReportAdsGroupedHandler, GetAdReportingReportAdsRequest, ) from dmp.ad_reporting.models import ( AdReportingAdCountryDbt, AdReportingAdDbt, 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 TestGetAdReportingReportAdsGroupedHandler: @pytest.mark.db def test_get_report_ads_grouped_not_found( self, handler: GetAdReportingReportAdsGroupedHandler, identity_id: str, fake: FakerTyped, ) -> None: with pytest.raises(AdReportingReportNotFoundError): handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=fake.uuid4_string(), search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_grouping_by_name( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 2 assert len(response.items[0].items) == 1 assert len(response.items[1].items) == 1 @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_filter_by_name( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=ad_1.name, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 1 @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_filter_by_campaign( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign_1 = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) campaign_2 = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign_1.id, campaign_2.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign_1.id, ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign_2.id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign_1.id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign_2.id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=campaign_1.id, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 1 @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_filter_by_ad_set( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=ad_1.ad_set_id, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 1 @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_filter_by_platform( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, platform="META", ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, platform="GOOGLE", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=AdReportingPlatform.META, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 1 @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_filter_by_objective( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_objective="OUTCOME_AWARENESS", ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_objective="OUTCOME_SALES", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=AdReportingObjective.OUTCOME_AWARENESS, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 1 @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_limit( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=1, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 1 @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_offset( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=1, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 1 @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_summary_common_fields( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, impressions=ad_1.impressions, actions=ad_1.actions, spend=ad_1.spend, spend_usd=ad_1.spend_usd, clicks=ad_1.clicks, reach=ad_1.reach, estimated_ad_recallers=ad_1.estimated_ad_recallers, views=ad_1.views, views_p25=ad_1.views_p25, purchases=ad_1.purchases, follows=ad_1.follows, likes=ad_1.likes, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ad_set_daily_budget=ad_1.ad_set_daily_budget, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, impressions=ad_2.impressions, actions=ad_2.actions, spend=ad_2.spend, spend_usd=ad_2.spend_usd, clicks=ad_2.clicks, reach=ad_2.reach, estimated_ad_recallers=ad_2.estimated_ad_recallers, views=ad_2.views, views_p25=ad_2.views_p25, purchases=ad_2.purchases, follows=ad_2.follows, likes=ad_2.likes, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ad_set_daily_budget=ad_2.ad_set_daily_budget, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) summary = response.summary assert summary.total == 2 assert summary.clicks == ad_1.clicks + ad_2.clicks assert summary.impressions == ad_1.impressions + ad_2.impressions assert ad_1.reach is not None assert ad_2.reach is not None assert summary.reach == ad_1.reach + ad_2.reach assert ad_1.estimated_ad_recallers is not None assert ad_2.estimated_ad_recallers is not None assert ( summary.estimated_ad_recallers == ad_1.estimated_ad_recallers + ad_2.estimated_ad_recallers ) assert summary.views_p25 == ad_1.views_p25 + ad_2.views_p25 assert summary.views == ad_1.views + ad_2.views assert ad_1.purchases is not None assert ad_2.purchases is not None assert summary.purchases == ad_1.purchases + ad_2.purchases assert ad_1.follows is not None assert ad_2.follows is not None assert summary.follows == ad_1.follows + ad_2.follows assert summary.spend_usd == ad_1.spend_usd + ad_2.spend_usd assert ad_1.likes is not None assert ad_2.likes is not None assert summary.likes == ad_1.likes + ad_2.likes assert summary.frequency is not None assert float(summary.frequency) == IsApprox( (ad_1.impressions + ad_2.impressions) / (ad_1.reach + ad_2.reach) ) assert summary.budget is None assert summary.budget_type == AdReportingBudgetType.CAMPAIGN_BUDGET @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_summary_computed_fields_same_values( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective="OUTCOME_TRAFFIC", ) ad_2 = create_reporting_model( AdReportingAdDbt, name=ad_1.name, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective=ad_1.campaign_objective, ad_set_id=ad_1.ad_set_id, ad_set_name=ad_1.ad_set_name, effective_status=ad_1.effective_status, action_type=ad_1.action_type, rate_type=ad_1.rate_type, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, impressions=ad_1.impressions, actions=ad_1.actions, spend=ad_1.spend, spend_usd=ad_1.spend_usd, clicks=ad_1.clicks, reach=ad_1.reach, estimated_ad_recallers=ad_1.estimated_ad_recallers, views=ad_1.views, views_p25=ad_1.views_p25, purchases=ad_1.purchases, follows=ad_1.follows, likes=ad_1.likes, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ad_set_daily_budget=ad_1.ad_set_daily_budget, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, impressions=ad_2.impressions, actions=ad_2.actions, spend=ad_2.spend, spend_usd=ad_2.spend_usd, clicks=ad_2.clicks, reach=ad_2.reach, estimated_ad_recallers=ad_2.estimated_ad_recallers, views=ad_2.views, views_p25=ad_2.views_p25, purchases=ad_2.purchases, follows=ad_2.follows, likes=ad_2.likes, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ad_set_daily_budget=ad_2.ad_set_daily_budget, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) summary = response.summary assert summary.actions == ad_1.actions + ad_2.actions assert summary.action_type == ad_1.action_type assert summary.rate_type == ad_1.rate_type assert summary.cost_per_action_usd is not None assert float(summary.cost_per_action_usd) == IsApprox( float((ad_1.spend_usd + ad_2.spend_usd) / (ad_1.actions + ad_2.actions)) ) assert summary.cost_per_action is None assert summary.rate is not None assert float(summary.rate) == IsApprox( (ad_1.clicks + ad_2.clicks) / (ad_1.impressions + ad_2.impressions) ) assert summary.budget is None assert summary.budget_type == AdReportingBudgetType.CAMPAIGN_BUDGET @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_summary_computed_fields_different_values( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective="OUTCOME_AWARENESS", ad_set_daily_budget=None, ad_set_lifetime_budget=None, campaign_daily_budget=None, campaign_lifetime_budget=None, action_type=AdReportingActionType.EAR, rate_type=AdReportingRateType.EARR, ) ad_2 = create_reporting_model( AdReportingAdDbt, name=ad_1.name, campaign_id=campaign.id, campaign_objective="OUTCOME_SALES", action_type=AdReportingActionType.CLICKS, rate_type=AdReportingRateType.CTR, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, impressions=ad_1.impressions, actions=ad_1.actions, spend=ad_1.spend, spend_usd=ad_1.spend_usd, clicks=ad_1.clicks, reach=ad_1.reach, estimated_ad_recallers=ad_1.estimated_ad_recallers, views=ad_1.views, views_p25=ad_1.views_p25, purchases=ad_1.purchases, follows=ad_1.follows, likes=ad_1.likes, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ad_set_daily_budget=ad_1.ad_set_daily_budget, ad_set_lifetime_budget=ad_1.ad_set_lifetime_budget, campaign_daily_budget=ad_1.campaign_daily_budget, campaign_lifetime_budget=ad_1.campaign_lifetime_budget, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, impressions=ad_2.impressions, actions=ad_2.actions, spend=ad_2.spend, spend_usd=ad_2.spend_usd, clicks=ad_2.clicks, reach=ad_2.reach, estimated_ad_recallers=ad_2.estimated_ad_recallers, views=ad_2.views, views_p25=ad_2.views_p25, purchases=ad_2.purchases, follows=ad_2.follows, likes=ad_2.likes, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ad_set_daily_budget=ad_2.ad_set_daily_budget, ad_set_lifetime_budget=ad_2.ad_set_lifetime_budget, campaign_daily_budget=ad_2.campaign_daily_budget, campaign_lifetime_budget=ad_2.campaign_lifetime_budget, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) summary = response.summary assert summary.actions is None assert summary.action_type is None assert summary.rate_type is None assert summary.cost_per_action_usd is None assert summary.cost_per_action is None assert summary.rate is None assert summary.budget is None assert summary.budget_type == AdReportingBudgetType.UNKNOWN @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_group_common_fields( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_name=campaign.name, ) ad_2 = create_reporting_model( AdReportingAdDbt, name=ad_1.name, campaign_id=campaign.id, campaign_name=campaign.name, currency=ad_1.currency, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, impressions=ad_1.impressions, actions=ad_1.actions, spend=ad_1.spend, spend_usd=ad_1.spend_usd, clicks=ad_1.clicks, reach=ad_1.reach, estimated_ad_recallers=ad_1.estimated_ad_recallers, views=ad_1.views, views_p25=ad_1.views_p25, purchases=ad_1.purchases, follows=ad_1.follows, likes=ad_1.likes, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, impressions=ad_2.impressions, actions=ad_2.actions, spend=ad_2.spend, spend_usd=ad_2.spend_usd, clicks=ad_2.clicks, reach=ad_2.reach, estimated_ad_recallers=ad_2.estimated_ad_recallers, views=ad_2.views, views_p25=ad_2.views_p25, purchases=ad_2.purchases, follows=ad_2.follows, likes=ad_2.likes, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 2 group = response.items[0] assert group.name == ad_1.name assert group.campaign_id == ad_1.campaign_id assert group.campaign_name == ad_1.campaign_name assert set(group.global_participant_ids) == { ad_1.campaign_global_participant_id, ad_2.campaign_global_participant_id, } assert group.platforms == sorted({ad_1.platform, ad_2.platform}) assert group.objectives == sorted( {ad_1.campaign_objective, ad_2.campaign_objective} ) assert group.targeting_countries == sorted( {*ad_1.targeting_countries, *ad_2.targeting_countries} ) assert group.start_at == min(ad_1.ad_set_start_at, ad_2.ad_set_start_at) assert group.end_at == max(ad_1.ad_set_end_at, ad_2.ad_set_end_at) assert group.clicks == ad_1.clicks + ad_2.clicks assert group.impressions == ad_1.impressions + ad_2.impressions assert ad_1.reach is not None assert ad_2.reach is not None assert group.reach == IsApprox(ad_1.reach + ad_2.reach) assert ad_1.estimated_ad_recallers is not None assert ad_2.estimated_ad_recallers is not None assert ( group.estimated_ad_recallers == ad_1.estimated_ad_recallers + ad_2.estimated_ad_recallers ) assert group.views_p25 == ad_1.views_p25 + ad_2.views_p25 assert group.views == ad_1.views + ad_2.views assert ad_1.purchases is not None assert ad_2.purchases is not None assert group.purchases == ad_1.purchases + ad_2.purchases assert ad_1.follows is not None assert ad_2.follows is not None assert group.follows == ad_1.follows + ad_2.follows assert group.currency == ad_1.currency assert group.spend == float(ad_1.spend + ad_2.spend) assert group.spend_usd == float(ad_1.spend_usd + ad_2.spend_usd) assert ad_1.likes is not None assert ad_2.likes is not None assert group.likes == ad_1.likes + ad_2.likes assert group.frequency is not None assert float(group.frequency) == IsApprox( (ad_1.impressions + ad_2.impressions) / (ad_1.reach + ad_2.reach) ) @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_group_computed_fields_same_values( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective="OUTCOME_TRAFFIC", ) ad_2 = create_reporting_model( AdReportingAdDbt, name=ad_1.name, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective=ad_1.campaign_objective, ad_set_id=ad_1.ad_set_id, ad_set_name=ad_1.ad_set_name, effective_status=ad_1.effective_status, action_type=ad_1.action_type, rate_type=ad_1.rate_type, targeting_countries=ad_1.targeting_countries, currency=ad_1.currency, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, impressions=ad_1.impressions, actions=ad_1.actions, spend=ad_1.spend, spend_usd=ad_1.spend_usd, clicks=ad_1.clicks, reach=ad_1.reach, estimated_ad_recallers=ad_1.estimated_ad_recallers, views=ad_1.views, views_p25=ad_1.views_p25, purchases=ad_1.purchases, follows=ad_1.follows, likes=ad_1.likes, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, impressions=ad_2.impressions, actions=ad_2.actions, spend=ad_2.spend, spend_usd=ad_2.spend_usd, clicks=ad_2.clicks, reach=ad_2.reach, estimated_ad_recallers=ad_2.estimated_ad_recallers, views=ad_2.views, views_p25=ad_2.views_p25, purchases=ad_2.purchases, follows=ad_2.follows, likes=ad_2.likes, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 2 group = response.items[0] assert group.ad_set_id == ad_1.ad_set_id assert group.ad_set_name == ad_1.ad_set_name assert group.effective_status == ad_1.effective_status assert group.actions == ad_1.actions + ad_2.actions assert group.action_type == ad_1.action_type assert group.rate_type == ad_1.rate_type assert group.cost_per_action == IsApprox( float((ad_1.spend + ad_2.spend) / (ad_1.actions + ad_2.actions)) ) assert group.cost_per_action_usd == IsApprox( float((ad_1.spend_usd + ad_2.spend_usd) / (ad_1.actions + ad_2.actions)) ) assert group.rate is not None assert float(group.rate) == IsApprox( (ad_1.clicks + ad_2.clicks) / (ad_1.impressions + ad_2.impressions) ) assert group.benchmark is None assert group.vs_benchmark is None assert group.artist_benchmark is None assert group.vs_artist_benchmark is None assert ad_1.actions is not None assert ad_2.actions is not None assert response.summary.actions is not None assert group.total_actions_ratio == IsApprox( (ad_1.actions + ad_2.actions) / response.summary.actions ) @pytest.mark.parametrize("countries", [["US"], None]) @pytest.mark.db def test_get_report_ads_grouped_group_computed_fields_different_values( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, countries: list[str] | None, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective="OUTCOME_AWARENESS", effective_status="META_ACTIVE", action_type="EAR", rate_type="VTR", ) ad_2 = create_reporting_model( AdReportingAdDbt, name=ad_1.name, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective="OUTCOME_SALES", effective_status="META_PAUSED", action_type="PURCHASES", rate_type="CR", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, impressions=ad_1.impressions, actions=ad_1.actions, spend=ad_1.spend, spend_usd=ad_1.spend_usd, clicks=ad_1.clicks, reach=ad_1.reach, estimated_ad_recallers=ad_1.estimated_ad_recallers, views=ad_1.views, views_p25=ad_1.views_p25, purchases=ad_1.purchases, follows=ad_1.follows, likes=ad_1.likes, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, impressions=ad_2.impressions, actions=ad_2.actions, spend=ad_2.spend, spend_usd=ad_2.spend_usd, clicks=ad_2.clicks, reach=ad_2.reach, estimated_ad_recallers=ad_2.estimated_ad_recallers, views=ad_2.views, views_p25=ad_2.views_p25, purchases=ad_2.purchases, follows=ad_2.follows, likes=ad_2.likes, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=countries, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 2 group = response.items[0] assert group.ad_set_id is None assert group.ad_set_name is None assert group.effective_status is None assert group.actions is None assert group.action_type is None assert group.rate_type is None assert group.cost_per_action is None assert group.cost_per_action_usd is None assert group.rate is None assert group.benchmark is None assert group.vs_benchmark is None assert group.artist_benchmark is None assert group.vs_artist_benchmark is None assert group.total_actions_ratio is None @pytest.mark.db def test_get_report_ads_grouped_group_bm( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective="OUTCOME_TRAFFIC", account_id=ad_account.external_id, ) ad_2 = create_reporting_model( AdReportingAdDbt, name=ad_1.name, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective=ad_1.campaign_objective, ad_set_id=ad_1.ad_set_id, ad_set_name=ad_1.ad_set_name, effective_status=ad_1.effective_status, action_type=ad_1.action_type, rate_type=ad_1.rate_type, targeting_countries=ad_1.targeting_countries, platform=ad_1.platform, account_id=ad_account.external_id, campaign_global_participant_id=ad_1.campaign_global_participant_id, ) bm = create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, platform=ad_1.platform, objective=ad_1.campaign_objective, ) artist_bm = create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, platform=ad_1.platform, objective=ad_1.campaign_objective, global_participant_id=ad_1.campaign_global_participant_id, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 2 group = response.items[0] assert group.benchmark == bm.rate assert group.vs_benchmark is not None assert float(group.vs_benchmark) == IsApprox( (ad_1.clicks + ad_2.clicks) / (ad_1.impressions + ad_2.impressions) - float(bm.rate) ) assert group.artist_benchmark == artist_bm.rate assert group.vs_artist_benchmark is not None assert float(group.vs_artist_benchmark) == IsApprox( (ad_1.clicks + ad_2.clicks) / (ad_1.impressions + ad_2.impressions) - float(artist_bm.rate) ) @pytest.mark.db def test_get_report_ads_grouped_group_bm_by_countries( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective="OUTCOME_TRAFFIC", account_id=ad_account.external_id, ) ad_2 = create_reporting_model( AdReportingAdDbt, name=ad_1.name, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective=ad_1.campaign_objective, ad_set_id=ad_1.ad_set_id, ad_set_name=ad_1.ad_set_name, effective_status=ad_1.effective_status, action_type=ad_1.action_type, rate_type=ad_1.rate_type, targeting_countries=ad_1.targeting_countries, platform=ad_1.platform, account_id=ad_account.external_id, campaign_global_participant_id=ad_1.campaign_global_participant_id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_1.external_id, name=ad_1.name, impressions=ad_1.impressions, actions=ad_1.actions, spend=ad_1.spend, spend_usd=ad_1.spend_usd, clicks=ad_1.clicks, reach=ad_1.reach, estimated_ad_recallers=ad_1.estimated_ad_recallers, views=ad_1.views, views_p25=ad_1.views_p25, purchases=ad_1.purchases, follows=ad_1.follows, likes=ad_1.likes, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="US", campaign_global_participant_id=ad_1.campaign_global_participant_id, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=campaign.id, external_id=ad_2.external_id, name=ad_2.name, impressions=ad_2.impressions, actions=ad_2.actions, spend=ad_2.spend, spend_usd=ad_2.spend_usd, clicks=ad_2.clicks, reach=ad_2.reach, estimated_ad_recallers=ad_2.estimated_ad_recallers, views=ad_2.views, views_p25=ad_2.views_p25, purchases=ad_2.purchases, follows=ad_2.follows, likes=ad_2.likes, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", campaign_global_participant_id=ad_1.campaign_global_participant_id, ) bm = create_reporting_model( AdReportingCampaignBenchmarkByAccountCountryDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, platform=ad_1.platform, objective=ad_1.campaign_objective, country_code="US", ) artist_bm = create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistCountryDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, platform=ad_1.platform, objective=ad_1.campaign_objective, global_participant_id=ad_1.campaign_global_participant_id, country_code="US", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, countries=["US"], order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 2 group = response.items[0] assert group.benchmark == bm.rate assert group.vs_benchmark is not None assert float(group.vs_benchmark) == IsApprox( (ad_1.clicks + ad_2.clicks) / (ad_1.impressions + ad_2.impressions) - float(bm.rate) ) assert group.artist_benchmark == artist_bm.rate assert group.vs_artist_benchmark is not None assert float(group.vs_artist_benchmark) == IsApprox( (ad_1.clicks + ad_2.clicks) / (ad_1.impressions + ad_2.impressions) - float(artist_bm.rate) ) @pytest.mark.db def test_get_ad_reporting_report_ads_grouped_single_bm( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, ) ad = create_reporting_model( AdReportingAdDbt, 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.platform, objective=ad.campaign_objective, ) artist_bm = create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account.vendor_id, subaccount_id=user_ad_account.subaccount_id, platform=ad.platform, objective=ad.campaign_objective, global_participant_id=ad.campaign_global_participant_id, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_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].items assert response.items[0].items[0].benchmark == bm.rate assert response.items[0].items[0].vs_benchmark == ad.rate - bm.rate assert response.items[0].items[0].artist_benchmark == artist_bm.rate assert ( response.items[0].items[0].vs_artist_benchmark == ad.rate - artist_bm.rate ) @pytest.mark.db def test_get_ad_reporting_report_ads_grouped_multiple_bm( self, handler: GetAdReportingReportAdsGroupedHandler, 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 = create_reporting_model( AdReportingAdDbt, 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.platform, objective=ad.campaign_objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountDbt, vendor_id=user_ad_account_2.vendor_id, subaccount_id=user_ad_account_2.subaccount_id, platform=ad.platform, objective=ad.campaign_objective, ) create_reporting_model( AdReportingCampaignBenchmarkByAccountArtistDbt, vendor_id=user_ad_account_1.vendor_id, subaccount_id=user_ad_account_1.subaccount_id, platform=ad.platform, objective=ad.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.platform, objective=ad.campaign_objective, global_participant_id=global_participant_id_2, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_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].items assert response.items[0].items[0].benchmark is None assert response.items[0].items[0].vs_benchmark is None assert response.items[0].items[0].artist_benchmark is None assert response.items[0].items[0].vs_artist_benchmark is None @pytest.mark.db def test_get_report_ads_with_country_filter_empty( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) ad = create_reporting_model( AdReportingAdDbt, platform=AdReportingPlatform.META, account_id=ad_account.external_id, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad.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.campaign_id} ) response = handler.handle( GetAdReportingReportAdsRequest( report_id=report.id, identity_id=identity_id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, countries=["US"], ) ) summary = response.summary assert summary.total == 1 assert summary.clicks == 0 assert summary.spend_usd == 0 assert summary.reach is None assert summary.actions is None assert summary.rate is None assert len(response.items) == 1 group = response.items[0] response_ad = group.items[0] assert response_ad.accounts == {user_ad_account.account} assert response_ad.clicks == 0 assert response_ad.spend_usd == 0 assert response_ad.reach is None assert response_ad.frequency is None assert response_ad.artist_benchmark is None assert response_ad.benchmark is None assert response_ad.vs_artist_benchmark is None @pytest.mark.db def test_get_report_ads_grouped_with_country_filter_recalculate_single_ad( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) ad = create_reporting_model( AdReportingAdDbt, name="a", account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, ) ad_2 = create_reporting_model( AdReportingAdDbt, name="b", account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad.campaign_id, external_id=ad.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="GB", ) ad_country_1 = create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad.campaign_id, external_id=ad.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_country_2 = create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad.campaign_id, external_id=ad.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( AdReportingAdCountryDbt, campaign_id=ad_2.campaign_id, external_id=ad_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( AdReportingAdCountryDbt, campaign_id=ad_2.campaign_id, external_id=ad_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.campaign_id}, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_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_country_1.clicks + ad_country_2.clicks assert ad_country_1.reach and ad_country_2.reach assert ad_country_1.estimated_ad_recallers is not None assert ad_country_2.estimated_ad_recallers is not None assert response.summary.reach == ad_country_1.reach + ad_country_2.reach assert ( response.summary.spend_usd == ad_country_1.spend_usd + ad_country_2.spend_usd ) assert response.summary.rate == IsApprox( Decimal( ( ad_country_1.estimated_ad_recallers + ad_country_2.estimated_ad_recallers ) / (ad_country_1.reach + ad_country_2.reach) ) ) assert len(response.items) == 1 assert response.items[0].items[0].accounts == {user_ad_account.account} assert ( response.items[0].items[0].clicks == ad_country_1.clicks + ad_country_2.clicks ) assert ( response.items[0].items[0].reach == ad_country_1.reach + ad_country_2.reach ) assert ( response.items[0].items[0].spend_usd == ad_country_1.spend_usd + ad_country_2.spend_usd ) assert response.items[0].items[0].rate == IsApprox( Decimal( ( ad_country_1.estimated_ad_recallers + ad_country_2.estimated_ad_recallers ) / (ad_country_1.reach + ad_country_2.reach) ), delta=Decimal("0.001"), ) assert response.items[0].items[0].artist_benchmark is None assert response.items[0].items[0].benchmark is None assert response.items[0].items[0].vs_artist_benchmark is None @pytest.mark.db def test_get_report_ads_grouped_with_country_filter_multiple_ads_summary_matching( self, handler: GetAdReportingReportAdsGroupedHandler, 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_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, account_id=ad_account.external_id, platform=campaign.platform, campaign_objective=campaign.objective, action_type=campaign.action_type, ) ad_2 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, account_id=ad_account.external_id, platform=campaign.platform, campaign_objective=campaign.objective, ) ad_country_1 = create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad_1.campaign_id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="GB", action_type=campaign.action_type, ) ad_country_2 = create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad_2.campaign_id, external_id=ad_2.external_id, name=ad_2.name, account_id=ad_account.external_id, platform=ad_2.platform, campaign_objective=ad_2.campaign_objective, country_code="US", action_type=campaign.action_type, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad_1.campaign_id, external_id=ad_1.external_id, name=ad_1.name, account_id=ad_account.external_id, platform=ad_1.platform, campaign_objective=ad_1.campaign_objective, country_code="EE", ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_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_country_1.clicks + ad_country_2.clicks assert ( response.summary.impressions == ad_country_1.impressions + ad_country_2.impressions ) assert ad_country_1.reach and ad_country_2.reach assert response.summary.reach == ad_country_1.reach + ad_country_2.reach assert ( response.summary.estimated_ad_recallers and ad_country_1.estimated_ad_recallers and ad_country_2.estimated_ad_recallers ) assert ( response.summary.estimated_ad_recallers == ad_country_1.estimated_ad_recallers + ad_country_2.estimated_ad_recallers ) assert ( response.summary.views_p25 == ad_country_1.views_p25 + ad_country_2.views_p25 ) assert response.summary.views == ad_country_1.views + ad_country_2.views assert ( response.summary.purchases and ad_country_1.purchases and ad_country_2.purchases ) assert ( response.summary.purchases == int(ad_country_1.purchases) + ad_country_2.purchases ) assert ( response.summary.follows and ad_country_1.follows and ad_country_2.follows ) assert response.summary.follows == ad_country_1.follows + ad_country_2.follows assert ( response.summary.spend_usd == ad_country_1.spend_usd + ad_country_2.spend_usd ) assert ad_country_1.likes and ad_country_2.likes assert response.summary.likes == ad_country_1.likes + ad_country_2.likes assert response.summary.actions == ad_country_1.actions + ad_country_2.actions assert ad_country_1.reach and ad_country_2.reach assert response.summary.rate == IsApprox( Decimal( ( ad_country_1.estimated_ad_recallers + ad_country_2.estimated_ad_recallers ) / (ad_country_1.reach + ad_country_2.reach) ) ) assert response.summary.cost_per_action_usd == IsApprox( (ad_country_1.spend_usd + ad_country_2.spend_usd) / (ad_country_1.actions + ad_country_2.actions) ) assert response.summary.cost_per_action is None assert ad_country_1.reach + ad_country_2.reach assert response.summary.frequency == IsApprox( decimal.Decimal(ad_country_1.impressions + ad_country_2.impressions) / (ad_country_1.reach + ad_country_2.reach) ) assert response.summary.budget is None assert response.summary.budget_type == AdReportingBudgetType.CAMPAIGN_BUDGET assert len(response.items) == 2 @pytest.mark.db def test_get_report_campaigns_with_country_filter_multiple_ads_grouped( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) ad = create_reporting_model( AdReportingAdDbt, name="a", account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, action_type=AdReportingActionType.EAR, rate_type=AdReportingRateType.EARR, ) ad_2 = create_reporting_model( AdReportingAdDbt, name="b", account_id=ad_account.external_id, platform=AdReportingPlatform.TIKTOK, campaign_objective=AdReportingObjective.VIDEO_VIEWS, action_type=AdReportingActionType.VIEWS, rate_type=AdReportingRateType.VTR, ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad.campaign_id, external_id=ad.external_id, name=ad.name, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="GB", ) ad_country_1 = create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad.campaign_id, external_id=ad.external_id, name=ad.name, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="US", action_type=AdReportingActionType.EAR, rate_type=AdReportingRateType.EARR, estimated_ad_recallers=fake.integer(length=6), ) create_reporting_model( AdReportingAdCountryDbt, campaign_id=ad.campaign_id, external_id=ad.external_id, name=ad.name, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, country_code="EE", estimated_ad_recallers=fake.integer(), ) ad_country_2 = create_reporting_model( AdReportingAdCountryDbt, name=ad_2.name, campaign_id=ad_2.campaign_id, external_id=ad_2.external_id, account_id=ad_account.external_id, platform=AdReportingPlatform.TIKTOK, campaign_objective=AdReportingObjective.VIDEO_VIEWS, country_code="US", action_type=AdReportingActionType.VIEWS, rate_type=AdReportingRateType.VTR, estimated_ad_recallers=fake.integer(length=6), ) create_reporting_model( AdReportingAdCountryDbt, name=ad_2.name, campaign_id=ad_2.campaign_id, external_id=ad_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.campaign_id, ad_2.campaign_id}, ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_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_country_1.clicks + ad_country_2.clicks assert ( response.summary.impressions == ad_country_1.impressions + ad_country_2.impressions ) assert ad_country_1.reach and ad_country_2.reach assert response.summary.reach == ad_country_1.reach + ad_country_2.reach assert ( response.summary.estimated_ad_recallers and ad_country_1.estimated_ad_recallers and ad_country_2.estimated_ad_recallers ) assert ( response.summary.estimated_ad_recallers == ad_country_1.estimated_ad_recallers + ad_country_2.estimated_ad_recallers ) assert ( response.summary.views_p25 == ad_country_1.views_p25 + ad_country_2.views_p25 ) assert response.summary.views == ad_country_1.views + ad_country_2.views assert ( response.summary.purchases and ad_country_1.purchases and ad_country_2.purchases ) assert ( response.summary.purchases == int(ad_country_1.purchases) + ad_country_2.purchases ) assert ( response.summary.follows and ad_country_1.follows and ad_country_2.follows ) assert response.summary.follows == ad_country_1.follows + ad_country_2.follows assert ( response.summary.spend_usd == ad_country_1.spend_usd + ad_country_2.spend_usd ) assert ad_country_1.likes and ad_country_2.likes assert response.summary.likes == ad_country_1.likes + ad_country_2.likes 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_country_1.reach and ad_country_2.reach assert response.summary.frequency == IsApprox( decimal.Decimal(ad_country_1.impressions + ad_country_2.impressions) / (ad_country_1.reach + ad_country_2.reach) ) assert response.summary.budget is None assert response.summary.budget_type == AdReportingBudgetType.CAMPAIGN_BUDGET assert len(response.items) == 2 assert response.items[0].items[0].id == ad_2.id assert response.items[0].items[0].account_id == ad_account.external_id assert response.items[0].items[0].accounts == {user_ad_account.account} assert response.items[0].items[0].action_type == ad_2.action_type assert response.items[0].items[0].currency == ad_2.currency assert response.items[0].items[0].effective_status == ad_2.effective_status assert response.items[0].items[0].end_at == ad_2.ad_set_end_at assert response.items[0].items[0].name == ad_2.name assert response.items[0].items[0].objective == ad_2.campaign_objective assert response.items[0].items[0].platform == ad_2.platform assert response.items[0].items[0].rate_type == ad_2.rate_type assert response.items[0].items[0].start_at == ad_2.ad_set_start_at assert response.items[0].items[0].targeting_countries == set( ad_2.targeting_countries ) assert response.items[0].items[0].actions == ad_country_2.actions assert response.items[0].items[0].clicks == ad_country_2.clicks assert response.items[0].items[0].cost_per_action == IsApprox( ad_country_2.spend / ad_country_2.actions ) assert response.items[0].items[0].cost_per_action_usd == IsApprox( ad_country_2.spend_usd / ad_country_2.actions ) assert ( response.items[0].items[0].estimated_ad_recallers == ad_country_2.estimated_ad_recallers ) assert response.items[0].items[0].follows == ad_country_2.follows assert response.items[0].items[0].frequency == IsApprox( decimal.Decimal(ad_country_2.impressions / ad_country_2.reach) ) assert response.items[0].items[0].impressions == ad_country_2.impressions assert response.items[0].items[0].purchases == ad_country_2.purchases assert response.items[0].items[0].rate == IsApprox( Decimal((ad_country_2.views or 0) / ad_country_2.impressions), delta=Decimal("0.001"), ) assert response.items[0].items[0].reach == ad_country_2.reach assert response.items[0].items[0].spend == ad_country_2.spend assert response.items[0].items[0].spend_usd == ad_country_2.spend_usd assert response.items[0].items[0].likes == ad_country_2.likes assert response.items[0].items[0].views == ad_country_2.views assert response.items[0].items[0].views_p25 == ad_country_2.views_p25 assert response.items[0].items[0].artist_benchmark is None assert response.items[0].items[0].benchmark is None assert response.items[0].items[0].vs_artist_benchmark is None assert response.items[0].items[0].vs_artist_benchmark is None assert response.items[1].items[0].id == ad.id assert response.items[1].items[0].account_id == ad_account.external_id assert response.items[1].items[0].accounts == {user_ad_account.account} assert response.items[1].items[0].action_type == ad.action_type assert response.items[1].items[0].currency == ad.currency assert response.items[1].items[0].effective_status == ad.effective_status assert response.items[1].items[0].end_at == ad.ad_set_end_at assert response.items[1].items[0].name == ad.name assert response.items[1].items[0].objective == ad.campaign_objective assert response.items[1].items[0].platform == ad.platform assert response.items[1].items[0].rate_type == ad.rate_type assert response.items[1].items[0].start_at == ad.ad_set_start_at assert response.items[1].items[0].targeting_countries == set( ad.targeting_countries ) assert response.items[1].items[0].actions == ad_country_1.actions assert response.items[1].items[0].clicks == ad_country_1.clicks assert response.items[1].items[0].cost_per_action == IsApprox( ad_country_1.spend / ad_country_1.actions ) assert response.items[1].items[0].cost_per_action_usd == IsApprox( ad_country_1.spend_usd / ad_country_1.actions ) assert ( response.items[1].items[0].estimated_ad_recallers == ad_country_1.estimated_ad_recallers ) assert response.items[1].items[0].follows == ad_country_1.follows assert ad_country_1.reach assert response.items[1].items[0].frequency == IsApprox( decimal.Decimal(ad_country_1.impressions / ad_country_1.reach) ) assert response.items[1].items[0].impressions == ad_country_1.impressions assert response.items[1].items[0].purchases == ad_country_1.purchases assert response.items[1].items[0].rate == IsApprox( Decimal((ad_country_1.estimated_ad_recallers or 0) / ad_country_1.reach), delta=Decimal("0.001"), ) assert response.items[1].items[0].reach == ad_country_1.reach assert response.items[1].items[0].spend == ad_country_1.spend assert response.items[1].items[0].spend_usd == ad_country_1.spend_usd assert response.items[1].items[0].likes == ad_country_1.likes assert response.items[1].items[0].views == ad_country_1.views assert response.items[1].items[0].views_p25 == ad_country_1.views_p25 assert response.items[1].items[0].artist_benchmark is None assert response.items[1].items[0].benchmark is None assert response.items[1].items[0].vs_artist_benchmark is None assert response.items[1].items[0].vs_artist_benchmark is None @pytest.mark.db def test_get_report_ads_grouped_with_country_filter_showing_benchmarks( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, fake: FakerTyped, ) -> 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, vendor_id=account.vendor_id, subaccount_id=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( AdReportingAdDbt, 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( AdReportingAdCountryDbt, 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( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, ad_set_id=None, 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].items[0].benchmark == benchmark.rate assert response.items[0].items[0].artist_benchmark == artist_benchmark.rate @pytest.mark.db def test_get_report_ads_grouped_with_country_filter_not_showing_benchmarks( self, handler: GetAdReportingReportAdsGroupedHandler, 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( AdReportingAdDbt, 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( AdReportingAdCountryDbt, 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( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, ad_set_id=None, 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].items[0].artist_benchmark is None assert response.items[0].items[0].benchmark is None @pytest.mark.db def test_get_report_ads_grouped_country_filter_with_zeros( self, handler: GetAdReportingReportAdsGroupedHandler, 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 = create_reporting_model( AdReportingAdDbt, 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( AdReportingAdCountryDbt, account_id=ad_account.external_id, external_id=ad.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( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_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_report_ads_grouped_different_currencies( self, handler: GetAdReportingReportAdsGroupedHandler, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, ) -> None: ad_account = create_model(MetaAdAccount) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) ad_1 = create_reporting_model( AdReportingAdDbt, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective="OUTCOME_TRAFFIC", currency="USD", ) create_reporting_model( AdReportingAdDbt, name=ad_1.name, campaign_id=campaign.id, campaign_name=campaign.name, campaign_objective=ad_1.campaign_objective, ad_set_id=ad_1.ad_set_id, ad_set_name=ad_1.ad_set_name, effective_status=ad_1.effective_status, action_type=ad_1.action_type, rate_type=ad_1.rate_type, targeting_countries=ad_1.targeting_countries, currency="GBP", ) response = handler.handle( GetAdReportingReportAdsRequest( identity_id=identity_id, report_id=report.id, search=None, campaign_id=None, ad_set_id=None, global_participant_id=None, platform=None, objective=None, order_by=["name.asc"], limit=10, offset=0, ) ) assert len(response.items) == 1 assert len(response.items[0].items) == 2 group = response.items[0] assert group.currency is None assert group.spend is None assert group.items[0].currency is not None assert group.items[0].spend is not None assert group.items[1].currency is not None assert group.items[1].spend is not None