# type: ignore from unittest import mock import pytest from dirty_equals import IsApprox, IsDatetime, IsNumber, IsStr from fansifter_common.auth.account import Account, AccountAccess from starlette.testclient import TestClient from dmp.ad_reporting.enums import ( AdReportingActionType, AdReportingBudgetType, AdReportingCreativeType, AdReportingObjective, AdReportingPlatform, AdReportingRateType, ) from dmp.ad_reporting.models import ( AdReportingAdCountryDbt, AdReportingAdDbt, AdReportingAdSetCountryDbt, AdReportingAdSetDbt, AdReportingCampaignCountryDbt, AdReportingCampaignDbt, AdReportingReport, ) from dmp.meta.models import MetaAdAccount, MetaUserAdAccount from dmp.tiktok.models import TikTokAdAccount, TikTokUserAdAccount from tests.unit.equals import IsISODatetime from tests.unit.faker import FakerTyped from tests.unit.types import CreateModel, CreateReportingModel @pytest.mark.db def test_get_ad_reporting_campaigns( client: TestClient, 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, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, global_participant_id=fake.uuid4_string(), objective=AdReportingObjective.OUTCOME_AWARENESS, daily_budget=fake.integer(), lifetime_budget=None, ad_set_daily_budget=None, ad_set_lifetime_budget=None, ) response = client.get("/ad-reporting/campaigns") assert response.status_code == 200 assert campaign.daily_budget assert response.json() == { "items": [ { "id": campaign.id, "externalId": campaign.external_id, "name": campaign.name, "accountId": campaign.account_id, "globalParticipantIds": list(campaign.global_participant_ids), "platform": campaign.platform, "objective": campaign.objective, "targetingCountries": campaign.targeting_countries, "reportingUrl": campaign.reporting_url, "effectiveStatus": campaign.effective_status, "startAt": IsISODatetime(campaign.start_at), "endAt": IsISODatetime(campaign.end_at), "clicks": campaign.clicks, "impressions": campaign.impressions, "reach": campaign.reach, "estimatedAdRecallers": campaign.estimated_ad_recallers, "viewsP25": campaign.views_p25, "views": campaign.views, "purchases": campaign.purchases, "follows": campaign.follows, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "currency": campaign.currency, "frequency": float(campaign.frequency), "costPerAction": IsApprox(float(campaign.cost_per_action)), "costPerActionUSD": IsApprox(float(campaign.cost_per_action_usd)), "actions": campaign.actions, "actionType": campaign.action_type, "rate": float(campaign.rate), "rateType": campaign.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "isIncludedInReport": False, "budget": campaign.daily_budget, "budgetUSD": campaign.daily_budget_usd, "budgetType": AdReportingBudgetType.DAILY_BUDGET, "reportId": None, "reportName": None, } ], "summary": { "total": 1, "clicks": campaign.clicks, "impressions": campaign.impressions, "reach": campaign.reach, "estimatedAdRecallers": campaign.estimated_ad_recallers, "viewsP25": campaign.views_p25, "views": campaign.views, "purchases": campaign.purchases, "follows": campaign.follows, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "actions": campaign.actions, "actionType": campaign.action_type, "rate": IsApprox( float(campaign.estimated_ad_recallers or 0) / campaign.reach ), "rateType": campaign.rate_type, "costPerAction": IsApprox(float(campaign.spend / campaign.actions)), "costPerActionUSD": IsApprox(float(campaign.spend_usd / campaign.actions)), "frequency": IsApprox(float(campaign.impressions / campaign.reach)), "budget": campaign.daily_budget, "budgetUSD": campaign.daily_budget_usd, "currency": campaign.currency, "budgetType": AdReportingBudgetType.DAILY_BUDGET, }, "limit": 25, "offset": 0, "total": 1, # deprecated } @pytest.mark.db def test_get_ad_reporting_campaigns_names( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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 ) response = client.get("/ad-reporting/campaigns-names", params={"limit": 1}) assert response.status_code == 200 assert response.json() == { "items": [ { "id": campaign.id, "name": campaign.name, } ], "total": 1, "limit": 1, "offset": 0, } @pytest.mark.db def test_get_ad_reporting_campaigns_artists( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, fake: FakerTyped, ) -> None: global_participant_id = fake.uuid4_string() ad_account = create_model(MetaAdAccount) create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, _global_participant_ids=[global_participant_id], ) response = client.get("/ad-reporting/campaigns-artists") assert response.status_code == 200 assert response.json() == [ { "id": global_participant_id, } ] @pytest.mark.db def test_get_ad_reporting_reports_artists( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, fake: FakerTyped, ) -> None: global_participant_id = fake.uuid4_string() ad_account = create_model(MetaAdAccount) 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, _global_participant_ids={global_participant_id}, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get( "/ad-reporting/reports-artists", params={ "reportId": report.id, }, ) assert response.status_code == 200 assert response.json() == [ { "id": global_participant_id, } ] @pytest.mark.db def test_get_ad_reporting_campaign( client: TestClient, 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, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, global_participant_id=fake.uuid4_string(), daily_budget=None, lifetime_budget=fake.integer(), ad_set_daily_budget=None, ad_set_lifetime_budget=None, daily_budget_usd=None, ) response = client.get(f"/ad-reporting/campaigns/{campaign.id}") assert response.status_code == 200 assert campaign.lifetime_budget assert response.json() == { "id": campaign.id, "externalId": campaign.external_id, "name": campaign.name, "accountId": campaign.account_id, "globalParticipantIds": list(campaign.global_participant_ids), "platform": campaign.platform, "objective": campaign.objective, "targetingCountries": campaign.targeting_countries, "reportingUrl": campaign.reporting_url, "effectiveStatus": campaign.effective_status, "startAt": IsISODatetime(campaign.start_at), "endAt": IsISODatetime(campaign.end_at), "clicks": campaign.clicks, "impressions": campaign.impressions, "reach": campaign.reach, "estimatedAdRecallers": campaign.estimated_ad_recallers, "viewsP25": campaign.views_p25, "views": campaign.views, "purchases": campaign.purchases, "follows": campaign.follows, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "currency": campaign.currency, "frequency": float(campaign.frequency), "costPerAction": IsApprox(float(campaign.cost_per_action)), "costPerActionUSD": IsApprox(float(campaign.cost_per_action_usd)), "actions": campaign.actions, "actionType": campaign.action_type, "rate": float(campaign.rate), "rateType": campaign.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "isIncludedInReport": False, "budget": campaign.lifetime_budget, "budgetUSD": campaign.lifetime_budget_usd, "budgetType": "LIFETIME_BUDGET", "reportId": None, "reportName": None, } @pytest.mark.db def test_assign_artist_to_ad_reporting_campaign( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) global_participant_id = fake.uuid4_string() response = client.put( f"/ad-reporting/campaigns/{campaign.id}/assign-artist", json={"globalParticipantId": global_participant_id}, ) assert response.status_code == 204 @pytest.mark.db def test_get_ad_reporting_campaign_reports( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = client.get(f"/ad-reporting/campaigns/{campaign.id}/reports") assert response.status_code == 200 assert response.json() == [ { "reportId": report.id, "reportName": report.name, "hasCampaignIncluded": True, } ] @pytest.mark.db def test_add_ad_reporting_campaign_to_reports( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) report = create_reporting_model(AdReportingReport, identity_id=identity_id) response = client.post( f"/ad-reporting/campaigns/{campaign.id}/reports", json={"reportIds": [report.id]}, ) assert response.status_code == 204 @pytest.mark.db def test_get_ad_reporting_reports( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) 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, global_participant_id=fake.uuid4_string(), ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get("/ad-reporting/reports") assert response.status_code == 200 assert response.json() == { "total": 1, "limit": 25, "offset": 0, "items": [ { "id": report.id, "name": report.name, "globalParticipantIds": [campaign.first_global_participant_id], "startAt": IsISODatetime(campaign.start_at), "endAt": IsISODatetime(campaign.end_at), "clicks": campaign.clicks, "impressions": campaign.impressions, "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "viewsP25": campaign.views_p25, "views": campaign.views, "spend": float(campaign.spend_usd), "createdAt": IsISODatetime(report.created_at), "createdBy": report.created_by, }, ], } @pytest.mark.db def test_create_ad_reporting_report( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) name = fake.name() response = client.post( "/ad-reporting/reports", json={ "name": name, "campaignIds": [campaign.id], }, ) assert response.status_code == 201 assert response.json() == { "id": IsStr(), "name": name, "createdAt": IsDatetime(iso_string=True), "createdBy": identity_id, "updatedAt": IsDatetime(iso_string=True), } @pytest.mark.db def test_get_ad_reporting_report_overview( client: TestClient, create_reporting_model: CreateReportingModel, identity_id: str, ) -> None: campaign = create_reporting_model( AdReportingCampaignDbt, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, action_type=AdReportingActionType.EAR, rate_type=AdReportingRateType.EARR, ) country_campaign = create_reporting_model( AdReportingCampaignCountryDbt, country_code="US", campaign_id=campaign.id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, action_type=AdReportingActionType.EAR, rate_type=AdReportingRateType.EARR, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}") assert response.status_code == 200 assert response.json() == { "id": report.id, "name": report.name, "campaignsCount": 1, "startAt": IsISODatetime(campaign.start_at), "endAt": IsISODatetime(campaign.end_at), "impressions": campaign.impressions, "clicks": campaign.clicks, "viewsP25": campaign.views_p25, "views": campaign.views, "currency": campaign.currency, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "createdAt": IsISODatetime(report.created_at), "createdBy": report.created_by, "toplinePerformance": [ { "platform": campaign.platform, "objective": campaign.objective, "clicks": campaign.clicks, "impressions": campaign.impressions, "reach": campaign.reach, "estimatedAdRecallers": campaign.estimated_ad_recallers, "viewsP25": campaign.views_p25, "views": campaign.views, "purchases": campaign.purchases, "follows": campaign.follows, "currency": campaign.currency, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "actionType": campaign.action_type, "actions": campaign.actions, "rateType": campaign.rate_type, "rate": IsNumber( approx=float( (campaign.estimated_ad_recallers or 0) / campaign.reach ) ), "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "costPerAction": IsNumber( approx=float(campaign.spend / campaign.actions) ), "costPerActionUSD": IsNumber( approx=float(campaign.spend_usd / campaign.actions) ), "frequency": IsNumber( approx=float(campaign.impressions / campaign.reach) ), } ], "toplineCountryPerformance": [ { "platform": country_campaign.platform, "objective": country_campaign.objective, "countryCode": country_campaign.country_code, "clicks": country_campaign.clicks, "impressions": country_campaign.impressions, "reach": country_campaign.reach, "estimatedAdRecallers": country_campaign.estimated_ad_recallers, "viewsP25": country_campaign.views_p25, "views": country_campaign.views, "purchases": country_campaign.purchases, "follows": country_campaign.follows, "currency": country_campaign.currency, "spend": float(country_campaign.spend), "spendUSD": float(country_campaign.spend_usd), "likes": country_campaign.likes, "completePayment": country_campaign.complete_payment, "checkout": country_campaign.checkout, "actionType": country_campaign.action_type, "actions": country_campaign.actions, "rateType": country_campaign.rate_type, "rate": IsNumber( approx=float( (country_campaign.estimated_ad_recallers or 0) / country_campaign.reach ) ), "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "costPerAction": IsNumber( approx=float(country_campaign.spend / country_campaign.actions) ), "costPerActionUSD": IsNumber( approx=float(country_campaign.spend_usd / country_campaign.actions) ), "frequency": IsNumber( approx=float(country_campaign.impressions / country_campaign.reach) ), } ], } @pytest.mark.db def test_edit_ad_reporting_report( client: TestClient, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, ) -> None: report = create_reporting_model(AdReportingReport, identity_id=identity_id) name = fake.name() response = client.put( f"/ad-reporting/reports/{report.id}", json={ "name": name, }, ) assert response.status_code == 200 assert response.json() == { "id": report.id, "name": name, "createdAt": IsISODatetime(report.created_at), "createdBy": report.created_by, "updatedAt": IsISODatetime(report.updated_at), } @pytest.mark.db def test_delete_ad_reporting_report( client: TestClient, create_reporting_model: CreateReportingModel, identity_id: str ) -> None: report = create_reporting_model(AdReportingReport, identity_id=identity_id) response = client.delete(f"/ad-reporting/reports/{report.id}") assert response.status_code == 204 @pytest.mark.db def test_edit_ad_reporting_report_unique_name( client: TestClient, create_reporting_model: CreateReportingModel, identity_id: str ) -> None: report_1 = create_reporting_model(AdReportingReport, identity_id=identity_id) report_2 = create_reporting_model(AdReportingReport, identity_id=identity_id) response = client.put( f"/ad-reporting/reports/{report_2.id}", json={ "name": report_1.name, }, ) assert response.status_code == 400 assert response.json() == { "code": "ad_reporting_report_unique_name", "message": "Report with this name already exists", } @pytest.mark.db def test_get_ad_reporting_report_campaigns( client: TestClient, 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, ) ] ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, global_participant_id=fake.uuid4_string(), objective=AdReportingObjective.OUTCOME_AWARENESS, daily_budget=None, lifetime_budget=None, ad_set_daily_budget=fake.integer(), ad_set_lifetime_budget=None, daily_budget_usd=None, lifetime_budget_usd=None, ad_set_daily_budget_usd=fake.integer(), ad_set_lifetime_budget_usd=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}/campaigns") assert response.status_code == 200 assert response.json() == { "total": 1, "summary": { "total": 1, "clicks": campaign.clicks, "impressions": campaign.impressions, "reach": campaign.reach, "estimatedAdRecallers": campaign.estimated_ad_recallers, "viewsP25": campaign.views_p25, "views": campaign.views, "purchases": campaign.purchases, "follows": campaign.follows, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "actions": campaign.actions, "actionType": campaign.action_type, "rate": IsApprox( float((campaign.estimated_ad_recallers or 0) / campaign.reach) ), "rateType": campaign.rate_type, "costPerAction": IsApprox(float(campaign.spend / campaign.actions)), "costPerActionUSD": IsApprox(float(campaign.spend_usd / campaign.actions)), "frequency": IsApprox(float(campaign.impressions / campaign.reach)), "budget": None, "budgetUSD": None, "currency": campaign.currency, "budgetType": AdReportingBudgetType.AD_SET_BUDGET, }, "items": [ { "id": campaign.id, "externalId": campaign.external_id, "name": campaign.name, "accountId": campaign.account_id, "globalParticipantIds": list(campaign.global_participant_ids), "platform": campaign.platform, "objective": campaign.objective, "targetingCountries": campaign.targeting_countries, "reportingUrl": campaign.reporting_url, "effectiveStatus": campaign.effective_status, "startAt": IsISODatetime(campaign.start_at), "endAt": IsISODatetime(campaign.end_at), "clicks": campaign.clicks, "impressions": campaign.impressions, "reach": campaign.reach, "estimatedAdRecallers": campaign.estimated_ad_recallers, "viewsP25": campaign.views_p25, "views": campaign.views, "purchases": campaign.purchases, "follows": campaign.follows, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "currency": campaign.currency, "frequency": float(campaign.frequency), "costPerAction": IsApprox(float(campaign.cost_per_action)), "costPerActionUSD": IsApprox(float(campaign.cost_per_action_usd)), "actions": campaign.actions, "actionType": campaign.action_type, "rate": float(campaign.rate), "rateType": campaign.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "isIncludedInReport": False, "budget": None, "budgetUSD": None, "budgetType": "AD_SET_BUDGET", "reportId": report.id, "reportName": report.name, } ], "limit": 25, "offset": 0, } @pytest.mark.db def test_get_ad_reporting_report_campaign( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) 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=AdReportingPlatform.META, global_participant_id=fake.uuid4_string(), daily_budget=None, lifetime_budget=None, ad_set_daily_budget=None, ad_set_lifetime_budget=fake.integer(), daily_budget_usd=None, lifetime_budget_usd=None, ad_set_daily_budget_usd=None, ad_set_lifetime_budget_usd=fake.integer(), ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}/campaigns/{campaign.id}") assert response.status_code == 200 assert response.json() == { "id": campaign.id, "externalId": campaign.external_id, "name": campaign.name, "accountId": campaign.account_id, "globalParticipantIds": list(campaign.global_participant_ids), "platform": campaign.platform, "objective": campaign.objective, "targetingCountries": campaign.targeting_countries, "reportingUrl": campaign.reporting_url, "effectiveStatus": campaign.effective_status, "startAt": IsISODatetime(campaign.start_at), "endAt": IsISODatetime(campaign.end_at), "clicks": campaign.clicks, "impressions": campaign.impressions, "reach": campaign.reach, "estimatedAdRecallers": campaign.estimated_ad_recallers, "viewsP25": campaign.views_p25, "views": campaign.views, "purchases": campaign.purchases, "follows": campaign.follows, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "currency": campaign.currency, "frequency": float(campaign.frequency), "costPerAction": IsApprox(float(campaign.cost_per_action)), "costPerActionUSD": IsApprox(float(campaign.cost_per_action_usd)), "actions": campaign.actions, "actionType": campaign.action_type, "rate": float(campaign.rate), "rateType": campaign.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "isIncludedInReport": False, "budget": None, "budgetUSD": None, "budgetType": "AD_SET_BUDGET", "reportId": report.id, "reportName": report.name, } @pytest.mark.db def test_get_ad_reporting_report_campaign_tiktok( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, ) -> None: ad_account = create_model(TikTokAdAccount) user_ad_account = create_model( TikTokUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.TIKTOK, global_participant_id=fake.uuid4_string(), daily_budget=None, daily_budget_usd=None, lifetime_budget=fake.integer(length=8), lifetime_budget_usd=fake.integer(length=8), ad_set_daily_budget=None, ad_set_lifetime_budget=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}/campaigns/{campaign.id}") assert response.status_code == 200 assert response.json() == { "id": campaign.id, "externalId": campaign.external_id, "name": campaign.name, "accountId": campaign.account_id, "globalParticipantIds": list(campaign.global_participant_ids), "platform": campaign.platform, "objective": campaign.objective, "targetingCountries": campaign.targeting_countries, "reportingUrl": campaign.reporting_url, "effectiveStatus": campaign.effective_status, "startAt": IsISODatetime(campaign.start_at), "endAt": IsISODatetime(campaign.end_at), "clicks": campaign.clicks, "impressions": campaign.impressions, "reach": campaign.reach, "estimatedAdRecallers": campaign.estimated_ad_recallers, "viewsP25": campaign.views_p25, "views": campaign.views, "purchases": campaign.purchases, "follows": campaign.follows, "spend": float(campaign.spend), "spendUSD": float(campaign.spend_usd), "likes": campaign.likes, "completePayment": campaign.complete_payment, "checkout": campaign.checkout, "currency": campaign.currency, "frequency": float(campaign.frequency), "costPerAction": IsApprox(float(campaign.cost_per_action)), "costPerActionUSD": IsApprox(float(campaign.cost_per_action_usd)), "actions": campaign.actions, "actionType": campaign.action_type, "rate": float(campaign.rate), "rateType": campaign.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "isIncludedInReport": False, "budget": campaign.lifetime_budget, "budgetUSD": campaign.lifetime_budget_usd, "budgetType": "LIFETIME_BUDGET", "reportId": report.id, "reportName": report.name, } @pytest.mark.db def test_remove_ad_reporting_report_campaign( client: TestClient, 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, ) campaign_2 = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account_2.external_id, platform=AdReportingPlatform.META, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign_1.id, campaign_2.id}, ) response = client.delete( f"/ad-reporting/reports/{report.id}/campaigns/{campaign_1.id}", ) assert response.status_code == 204 assert report.campaign_ids == [campaign_2.id] @pytest.mark.db def test_remove_ad_reporting_report_last_campaign( client: TestClient, 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, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = client.delete( f"/ad-reporting/reports/{report.id}/campaigns/{campaign.id}", ) assert response.status_code == 400 assert response.json() == { "code": "ad_reporting_report_last_campaign_delete_error", "message": "Cannot delete the last campaign from the report", } @pytest.mark.db def test_remove_ad_reporting_report_campaign_not_found( client: TestClient, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, ) -> None: campaign_id = fake.pystr() report = create_reporting_model( AdReportingReport, # campaign_ids=[], identity_id=identity_id, ) response = client.delete( f"/ad-reporting/reports/{report.id}/campaigns/{campaign_id}", ) assert response.status_code == 404 assert response.json() == { "code": "ad_reporting_campaign_not_found", "message": "Ad reporting campaign not found", } @pytest.mark.db def test_get_ad_reporting_ad_sets( client: TestClient, 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_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, daily_budget=None, daily_budget_usd=None, lifetime_budget=fake.integer(), lifetime_budget_usd=fake.integer(), campaign_daily_budget=None, campaign_lifetime_budget=None, ) response = client.get("/ad-reporting/ad-sets") assert response.status_code == 200 assert ad_set.lifetime_budget assert response.json() == { "summary": { "total": 1, "clicks": ad_set.clicks, "impressions": ad_set.impressions, "reach": ad_set.reach, "estimatedAdRecallers": ad_set.estimated_ad_recallers, "viewsP25": ad_set.views_p25, "views": ad_set.views, "purchases": ad_set.purchases, "follows": ad_set.follows, "spend": float(ad_set.spend), "spendUSD": float(ad_set.spend_usd), "likes": ad_set.likes, "completePayment": ad_set.complete_payment, "checkout": ad_set.checkout, "actions": ad_set.actions, "actionType": ad_set.action_type, "rate": IsApprox( float((ad_set.estimated_ad_recallers or 0) / ad_set.reach) ), "rateType": ad_set.rate_type, "costPerAction": IsApprox(float(ad_set.spend / ad_set.actions)), "costPerActionUSD": IsApprox(float(ad_set.spend_usd / ad_set.actions)), "frequency": IsApprox(float(ad_set.impressions / ad_set.reach)), "budget": IsApprox(ad_set.lifetime_budget), "budgetUSD": IsApprox(ad_set.lifetime_budget_usd), "currency": ad_set.currency, "budgetType": AdReportingBudgetType.LIFETIME_BUDGET, }, "items": [ { "id": ad_set.id, "name": ad_set.name, "campaignId": ad_set.campaign_id, "campaignName": ad_set.campaign_name, "accountId": ad_set.account_id, "globalParticipantIds": [ad_set.campaign_global_participant_id], "platform": ad_set.platform, "objective": ad_set.campaign_objective, "targetingCountries": ad_set.targeting_countries, "reportingUrl": ad_set.reporting_url, "effectiveStatus": ad_set.effective_status, "startAt": IsISODatetime(ad_set.start_at), "endAt": IsISODatetime(ad_set.end_at), "clicks": ad_set.clicks, "impressions": ad_set.impressions, "reach": ad_set.reach, "estimatedAdRecallers": ad_set.estimated_ad_recallers, "viewsP25": ad_set.views_p25, "views": ad_set.views, "purchases": ad_set.purchases, "follows": ad_set.follows, "spend": float(ad_set.spend), "currency": ad_set.currency, "spendUSD": float(ad_set.spend_usd), "likes": ad_set.likes, "completePayment": ad_set.complete_payment, "checkout": ad_set.checkout, "frequency": float(ad_set.frequency), "costPerAction": IsApprox(float(ad_set.cost_per_action)), "costPerActionUSD": IsApprox(float(ad_set.cost_per_action_usd)), "actions": ad_set.actions, "actionType": ad_set.action_type, "rate": float(ad_set.rate), "rateType": ad_set.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budget": ad_set.lifetime_budget, "budgetUSD": ad_set.lifetime_budget_usd, "budgetType": "LIFETIME_BUDGET", "reportId": None, "reportName": None, } ], "limit": 25, "offset": 0, "total": 1, # deprecated } @pytest.mark.db def test_get_ad_reporting_ad_sets_with_country_filter( client: TestClient, 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, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, global_participant_id=fake.uuid4_string(), ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, campaign_id=campaign.id, platform=campaign.platform, campaign_objective=campaign.objective, campaign_name=campaign.name, campaign_global_participant_id=campaign.global_participant_id, daily_budget=None, lifetime_budget=fake.integer(), campaign_daily_budget=None, campaign_lifetime_budget=None, daily_budget_usd=None, ) ad_set_country = create_reporting_model( AdReportingAdSetCountryDbt, account_id=ad_account.external_id, external_id=ad_set.external_id, campaign_id=campaign.id, platform=campaign.platform, campaign_objective=campaign.objective, country_code="US", daily_budget=None, lifetime_budget=None, campaign_daily_budget=fake.integer(), campaign_lifetime_budget=None, daily_budget_usd=None, lifetime_budget_usd=None, ) response = client.get("/ad-reporting/ad-sets", params={"countries": ["US"]}) assert response.status_code == 200 assert response.json() == { "summary": { "total": 1, "clicks": ad_set_country.clicks, "impressions": ad_set_country.impressions, "reach": ad_set_country.reach, "estimatedAdRecallers": ad_set_country.estimated_ad_recallers, "viewsP25": ad_set_country.views_p25, "views": ad_set_country.views, "purchases": ad_set_country.purchases, "follows": ad_set_country.follows, "spend": float(ad_set_country.spend), "spendUSD": float(ad_set_country.spend_usd), "likes": ad_set_country.likes, "completePayment": ad_set_country.complete_payment, "checkout": ad_set_country.checkout, "actions": ad_set_country.actions, "actionType": ad_set.action_type.value, "rate": IsNumber( approx=float( (ad_set_country.estimated_ad_recallers or 0) / ad_set_country.reach ) ), "rateType": ad_set.rate_type.value, "costPerAction": IsNumber( approx=float(ad_set_country.spend / ad_set_country.actions) ), "costPerActionUSD": IsNumber( approx=float(ad_set_country.spend_usd / ad_set_country.actions) ), "frequency": IsNumber( approx=float(ad_set_country.impressions / ad_set_country.reach) ), "budget": ad_set.lifetime_budget, "budgetUSD": ad_set.lifetime_budget_usd, "currency": ad_set.currency, "budgetType": AdReportingBudgetType.LIFETIME_BUDGET, }, "items": [ { "id": ad_set.id, "name": ad_set.name, "campaignId": campaign.id, "campaignName": campaign.name, "accountId": ad_account.external_id, "globalParticipantIds": [campaign.global_participant_id], "platform": ad_set.platform.value, "objective": ad_set.campaign_objective.value, "targetingCountries": ad_set.targeting_countries, "reportingUrl": ad_set.reporting_url, "effectiveStatus": ad_set.effective_status.value, "startAt": IsISODatetime(ad_set.start_at), "endAt": IsISODatetime(ad_set.end_at), "clicks": ad_set_country.clicks, "impressions": ad_set_country.impressions, "reach": ad_set_country.reach, "estimatedAdRecallers": ad_set_country.estimated_ad_recallers, "viewsP25": ad_set_country.views_p25, "views": ad_set_country.views, "purchases": ad_set_country.purchases, "follows": ad_set_country.follows, "spend": float(ad_set_country.spend), "currency": ad_set.currency, "spendUSD": float(ad_set_country.spend_usd), "likes": ad_set_country.likes, "completePayment": ad_set_country.complete_payment, "checkout": ad_set_country.checkout, "frequency": IsApprox( approx=float(ad_set_country.impressions / ad_set_country.reach) ), "costPerAction": IsApprox( approx=float(ad_set_country.spend / ad_set_country.actions) ), "costPerActionUSD": IsApprox( approx=float(ad_set_country.spend_usd / ad_set_country.actions) ), "actions": ad_set_country.actions, "actionType": ad_set.action_type.value, "rate": IsApprox( approx=float( (ad_set_country.estimated_ad_recallers or 0) / ad_set_country.reach ), delta=0.001, ), "rateType": ad_set.rate_type.value, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budget": None, "budgetUSD": None, "budgetType": "CAMPAIGN_BUDGET", "reportId": None, "reportName": None, } ], "limit": 25, "offset": 0, "total": 1, # deprecated } @pytest.mark.db def test_get_ad_reporting_report_ad_sets_with_country_filter( client: TestClient, 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, ) ] ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, global_participant_id=fake.uuid4_string(), ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, campaign_id=campaign.id, platform=campaign.platform, campaign_objective=campaign.objective, campaign_name=campaign.name, campaign_global_participant_id=campaign.global_participant_id, daily_budget=None, lifetime_budget=None, campaign_daily_budget=None, campaign_lifetime_budget=fake.integer(), daily_budget_usd=None, lifetime_budget_usd=None, campaign_daily_budget_usd=None, campaign_lifetime_budget_usd=fake.integer(), ) ad_set_country = create_reporting_model( AdReportingAdSetCountryDbt, account_id=ad_account.external_id, external_id=ad_set.external_id, campaign_id=campaign.id, platform=campaign.platform, campaign_objective=campaign.objective, country_code="US", daily_budget=None, lifetime_budget=fake.integer(), campaign_daily_budget=None, campaign_lifetime_budget=None, daily_budget_usd=None, lifetime_budget_usd=fake.integer(), campaign_daily_budget_usd=None, campaign_lifetime_budget_usd=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = client.get( f"/ad-reporting/reports/{report.id}/ad-sets", params={"countries": ["US"], "reportId": report.id}, ) assert response.status_code == 200 assert ad_set_country.lifetime_budget assert response.json() == { "summary": { "total": 1, "clicks": ad_set_country.clicks, "impressions": ad_set_country.impressions, "reach": ad_set_country.reach, "estimatedAdRecallers": ad_set_country.estimated_ad_recallers, "viewsP25": ad_set_country.views_p25, "views": ad_set_country.views, "purchases": ad_set_country.purchases, "follows": ad_set_country.follows, "spend": float(ad_set_country.spend), "spendUSD": float(ad_set_country.spend_usd), "likes": ad_set_country.likes, "completePayment": ad_set_country.complete_payment, "checkout": ad_set_country.checkout, "actions": ad_set_country.actions, "actionType": ad_set.action_type.value, "rate": IsNumber( approx=float( (ad_set_country.estimated_ad_recallers or 0) / ad_set_country.reach ), delta=10, ), "rateType": ad_set.rate_type.value, "costPerAction": IsApprox( approx=float(ad_set_country.spend / ad_set_country.actions) ), "costPerActionUSD": IsApprox( approx=float(ad_set_country.spend_usd / ad_set_country.actions) ), "frequency": IsNumber( approx=float(ad_set_country.impressions / ad_set_country.reach) ), "budget": None, "budgetUSD": None, "currency": ad_set.currency, "budgetType": AdReportingBudgetType.CAMPAIGN_BUDGET, }, "items": [ { "id": ad_set.id, "name": ad_set.name, "campaignId": campaign.id, "campaignName": campaign.name, "accountId": ad_account.external_id, "globalParticipantIds": [campaign.global_participant_id], "platform": ad_set.platform.value, "objective": ad_set.campaign_objective.value, "targetingCountries": ad_set.targeting_countries, "reportingUrl": ad_set.reporting_url, "effectiveStatus": ad_set.effective_status.value, "startAt": IsISODatetime(ad_set.start_at), "endAt": IsISODatetime(ad_set.end_at), "clicks": ad_set_country.clicks, "impressions": ad_set_country.impressions, "reach": ad_set_country.reach, "estimatedAdRecallers": ad_set_country.estimated_ad_recallers, "viewsP25": ad_set_country.views_p25, "views": ad_set_country.views, "purchases": ad_set_country.purchases, "follows": ad_set_country.follows, "spend": float(ad_set_country.spend), "currency": ad_set.currency, "spendUSD": float(ad_set_country.spend_usd), "likes": ad_set_country.likes, "completePayment": ad_set_country.complete_payment, "checkout": ad_set_country.checkout, "frequency": IsApprox( approx=float(ad_set_country.impressions / ad_set_country.reach) ), "costPerAction": IsApprox( float(ad_set_country.spend / ad_set_country.actions) ), "costPerActionUSD": IsApprox( float(ad_set_country.spend_usd / ad_set_country.actions) ), "actions": ad_set_country.actions, "actionType": ad_set.action_type.value, "rate": IsApprox( approx=float( (ad_set_country.estimated_ad_recallers or 0) / ad_set_country.reach ), delta=0.001, ), "rateType": ad_set.rate_type.value, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budget": ad_set_country.lifetime_budget, "budgetUSD": ad_set_country.lifetime_budget_usd, "budgetType": "LIFETIME_BUDGET", "reportId": report.id, "reportName": report.name, } ], "limit": 25, "offset": 0, "total": 1, # deprecated } @pytest.mark.db def test_get_ad_reporting_ads_with_country_filter( client: TestClient, 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, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, global_participant_id=fake.uuid4_string(), ) ad = create_reporting_model( AdReportingAdDbt, account_id=ad_account.external_id, campaign_id=campaign.id, platform=campaign.platform, campaign_objective=campaign.objective, campaign_name=campaign.name, campaign_global_participant_id=campaign.global_participant_id, campaign_daily_budget=None, campaign_lifetime_budget=None, ad_set_daily_budget=fake.integer(), ad_set_lifetime_budget=None, ) ad_country = create_reporting_model( AdReportingAdCountryDbt, account_id=ad_account.external_id, external_id=ad.external_id, campaign_id=campaign.id, platform=campaign.platform, campaign_objective=campaign.objective, country_code="US", campaign_daily_budget=None, campaign_lifetime_budget=fake.integer(), ad_set_daily_budget=None, ad_set_lifetime_budget=None, ) response = client.get("/ad-reporting/ads", params={"countries": ["US"]}) assert response.status_code == 200 assert response.json() == { "summary": { "total": 1, "clicks": ad_country.clicks, "impressions": ad_country.impressions, "reach": ad_country.reach, "estimatedAdRecallers": ad_country.estimated_ad_recallers, "viewsP25": ad_country.views_p25, "views": ad_country.views, "purchases": ad_country.purchases, "follows": ad_country.follows, "spend": float(ad_country.spend), "spendUSD": float(ad_country.spend_usd), "likes": ad_country.likes, "completePayment": ad_country.complete_payment, "checkout": ad_country.checkout, "actions": ad_country.actions, "actionType": ad.action_type.value, "rate": IsNumber( approx=float( (ad_country.estimated_ad_recallers or 0) / ad_country.reach ), delta=10, ), "rateType": ad.rate_type.value, "costPerAction": IsApprox( approx=float(ad_country.spend / ad_country.actions) ), "costPerActionUSD": IsApprox( approx=float(ad_country.spend_usd / ad_country.actions) ), "frequency": IsNumber( approx=float(ad_country.impressions / ad_country.reach) ), "budget": None, "budgetUSD": None, "currency": ad.currency, "budgetType": AdReportingBudgetType.AD_SET_BUDGET, }, "items": [ { "id": ad.id, "name": ad.name, "campaignId": ad.campaign_id, "campaignName": ad.campaign_name, "adSetId": ad.ad_set_id, "adSetName": ad.ad_set_name, "accountId": ad.account_id, "globalParticipantIds": [ad.campaign_global_participant_id], "platform": ad.platform.value, "objective": ad.campaign_objective.value, "targetingCountries": ad.targeting_countries, "reportingUrl": ad.reporting_url, "effectiveStatus": ad.effective_status.value, "startAt": IsISODatetime(ad.ad_set_start_at), "endAt": IsISODatetime(ad.ad_set_end_at), "clicks": ad_country.clicks, "impressions": ad_country.impressions, "reach": ad_country.reach, "estimatedAdRecallers": ad_country.estimated_ad_recallers, "viewsP25": ad_country.views_p25, "views": ad_country.views, "purchases": ad_country.purchases, "follows": ad_country.follows, "spend": float(ad_country.spend), "currency": ad.currency, "spendUSD": float(ad_country.spend_usd), "likes": ad_country.likes, "completePayment": ad_country.complete_payment, "checkout": ad_country.checkout, "frequency": IsApprox( approx=float(ad_country.impressions / ad_country.reach) ), "costPerAction": IsApprox( approx=float(ad_country.spend / ad_country.actions) ), "costPerActionUSD": IsApprox( float(ad_country.spend_usd / ad_country.actions) ), "actions": ad_country.actions, "actionType": ad.action_type.value, "rate": IsApprox( approx=float( (ad_country.estimated_ad_recallers or 0) / ad_country.reach ), delta=0.001, ), "rateType": ad.rate_type.value, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "creativeUrl": ad.creative_image_url, "creativeType": AdReportingCreativeType.IMAGE.value, "thumbnailUrl": None, "creativeThumbnail": None, "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budgetType": "CAMPAIGN_BUDGET", "reportId": None, "reportName": None, } ], "limit": 25, "offset": 0, "total": 1, # deprecated } @pytest.mark.db def test_get_ad_reporting_report_ads_with_country_filter( client: TestClient, 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, ) campaign = create_reporting_model( AdReportingCampaignDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_AWARENESS, global_participant_id=fake.uuid4_string(), ) ad = create_reporting_model( AdReportingAdDbt, account_id=ad_account.external_id, campaign_id=campaign.id, platform=campaign.platform, campaign_objective=campaign.objective, campaign_name=campaign.name, campaign_global_participant_id=campaign.global_participant_id, campaign_daily_budget=None, campaign_lifetime_budget=None, ad_set_daily_budget=None, ad_set_lifetime_budget=fake.integer(), ) ad_country = create_reporting_model( AdReportingAdCountryDbt, account_id=ad_account.external_id, external_id=ad.external_id, campaign_id=campaign.id, platform=campaign.platform, campaign_objective=campaign.objective, country_code="US", campaign_daily_budget=None, campaign_lifetime_budget=fake.integer(), ad_set_daily_budget=None, ad_set_lifetime_budget=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id}, ) response = client.get( f"/ad-reporting/reports/{report.id}/ads", params={"countries": ["US"], "reportId": report.id}, ) assert response.status_code == 200 assert response.json() == { "summary": { "total": 1, "clicks": ad_country.clicks, "impressions": ad_country.impressions, "reach": ad_country.reach, "estimatedAdRecallers": ad_country.estimated_ad_recallers, "viewsP25": ad_country.views_p25, "views": ad_country.views, "purchases": ad_country.purchases, "follows": ad_country.follows, "spend": float(ad_country.spend), "spendUSD": float(ad_country.spend_usd), "likes": ad_country.likes, "completePayment": ad_country.complete_payment, "checkout": ad_country.checkout, "actions": ad_country.actions, "actionType": ad.action_type.value, "rate": IsNumber( approx=float( (ad_country.estimated_ad_recallers or 0) / ad_country.reach ) ), "rateType": ad.rate_type.value, "costPerAction": IsApprox(float(ad_country.spend / ad_country.actions)), "costPerActionUSD": IsApprox( float(ad_country.spend_usd / ad_country.actions) ), "frequency": IsNumber( approx=float(ad_country.impressions / ad_country.reach) ), "budget": None, "budgetUSD": None, "currency": ad.currency, "budgetType": AdReportingBudgetType.AD_SET_BUDGET, }, "items": [ { "id": ad.id, "name": ad.name, "campaignId": ad.campaign_id, "campaignName": ad.campaign_name, "adSetId": ad.ad_set_id, "adSetName": ad.ad_set_name, "accountId": ad.account_id, "globalParticipantIds": [ad.campaign_global_participant_id], "platform": ad.platform.value, "objective": ad.campaign_objective.value, "targetingCountries": ad.targeting_countries, "reportingUrl": ad.reporting_url, "effectiveStatus": ad.effective_status.value, "startAt": IsISODatetime(ad.ad_set_start_at), "endAt": IsISODatetime(ad.ad_set_end_at), "clicks": ad_country.clicks, "impressions": ad_country.impressions, "reach": ad_country.reach, "estimatedAdRecallers": ad_country.estimated_ad_recallers, "viewsP25": ad_country.views_p25, "views": ad_country.views, "purchases": ad_country.purchases, "follows": ad_country.follows, "spend": float(ad_country.spend), "currency": ad.currency, "spendUSD": float(ad_country.spend_usd), "likes": ad_country.likes, "completePayment": ad_country.complete_payment, "checkout": ad_country.checkout, "frequency": IsApprox( approx=float(ad_country.impressions / ad_country.reach) ), "costPerAction": IsApprox( approx=float(ad_country.spend / ad_country.actions) ), "costPerActionUSD": IsApprox( float(ad_country.spend_usd / ad_country.actions) ), "actions": ad_country.actions, "actionType": ad.action_type.value, "rate": IsApprox( approx=float( (ad_country.estimated_ad_recallers or 0) / ad_country.reach, ), delta=0.001, ), "rateType": ad.rate_type.value, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "creativeUrl": ad.creative_image_url, "creativeType": AdReportingCreativeType.IMAGE.value, "thumbnailUrl": None, "creativeThumbnail": None, "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budgetType": "CAMPAIGN_BUDGET", "reportId": report.id, "reportName": report.name, } ], "limit": 25, "offset": 0, "total": 1, # deprecated } @pytest.mark.db def test_get_ad_reporting_ad_sets_names( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) create_model( MetaUserAdAccount, ad_account_id=ad_account.id, identity_id=identity_id, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, ) response = client.get("/ad-reporting/ad-sets-names", params={"limit": 1}) assert response.status_code == 200 assert response.json() == { "items": [ { "id": ad_set.id, "name": ad_set.name, } ], "total": 1, "limit": 1, "offset": 0, } @pytest.mark.db def test_get_ad_reporting_ad_set( client: TestClient, 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_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, daily_budget=fake.integer(), lifetime_budget=None, campaign_daily_budget=None, campaign_lifetime_budget=None, daily_budget_usd=fake.integer(), lifetime_budget_usd=None, campaign_daily_budget_usd=None, campaign_lifetime_budget_usd=None, ) response = client.get(f"/ad-reporting/ad-sets/{ad_set.id}") assert response.status_code == 200 assert response.json() == { "id": ad_set.id, "name": ad_set.name, "campaignId": ad_set.campaign_id, "campaignName": ad_set.campaign_name, "accountId": ad_set.account_id, "globalParticipantIds": [ad_set.campaign_global_participant_id], "platform": ad_set.platform, "objective": ad_set.campaign_objective, "targetingCountries": ad_set.targeting_countries, "reportingUrl": ad_set.reporting_url, "effectiveStatus": ad_set.effective_status, "startAt": IsISODatetime(ad_set.start_at), "endAt": IsISODatetime(ad_set.end_at), "clicks": ad_set.clicks, "impressions": ad_set.impressions, "reach": ad_set.reach, "estimatedAdRecallers": ad_set.estimated_ad_recallers, "viewsP25": ad_set.views_p25, "views": ad_set.views, "purchases": ad_set.purchases, "follows": ad_set.follows, "spend": float(ad_set.spend), "currency": ad_set.currency, "spendUSD": float(ad_set.spend_usd), "likes": ad_set.likes, "completePayment": ad_set.complete_payment, "checkout": ad_set.checkout, "frequency": float(ad_set.frequency), "costPerAction": IsApprox(float(ad_set.cost_per_action)), "costPerActionUSD": IsApprox(float(ad_set.cost_per_action_usd)), "actions": ad_set.actions, "actionType": ad_set.action_type, "rate": float(ad_set.rate), "rateType": ad_set.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budget": ad_set.daily_budget, "budgetUSD": ad_set.daily_budget_usd, "budgetType": "DAILY_BUDGET", "reportId": None, "reportName": None, } @pytest.mark.db def test_get_ad_reporting_ads( client: TestClient, 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, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_objective=AdReportingObjective.OUTCOME_AWARENESS, campaign_daily_budget=None, campaign_lifetime_budget=fake.integer(), ad_set_daily_budget=None, ad_set_lifetime_budget=None, ) response = client.get("/ad-reporting/ads") assert response.status_code == 200 assert response.json() == { "summary": { "total": 1, "clicks": ad.clicks, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "spend": float(ad.spend), "spendUSD": float(ad.spend_usd), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "actions": ad.actions, "actionType": ad.action_type, "rate": IsApprox(float((ad.estimated_ad_recallers or 0) / ad.reach)), "rateType": ad.rate_type, "costPerAction": IsApprox(float(ad.spend / ad.actions)), "costPerActionUSD": IsApprox(float(ad.spend_usd / ad.actions)), "frequency": IsApprox(float(ad.impressions / ad.reach)), "budget": None, "budgetUSD": None, "currency": ad.currency, "budgetType": AdReportingBudgetType.CAMPAIGN_BUDGET, }, "items": [ { "id": ad.id, "name": ad.name, "campaignId": ad.campaign_id, "campaignName": ad.campaign_name, "adSetId": ad.ad_set_id, "adSetName": ad.ad_set_name, "accountId": ad.account_id, "globalParticipantIds": [ad.campaign_global_participant_id], "platform": ad.platform, "objective": ad.campaign_objective, "targetingCountries": ad.targeting_countries, "reportingUrl": ad.reporting_url, "effectiveStatus": ad.effective_status, "startAt": IsISODatetime(ad.ad_set_start_at), "endAt": IsISODatetime(ad.ad_set_end_at), "clicks": ad.clicks, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "spend": float(ad.spend), "currency": ad.currency, "spendUSD": float(ad.spend_usd), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "frequency": float(ad.frequency), "costPerAction": IsApprox(float(ad.cost_per_action)), "costPerActionUSD": IsApprox(float(ad.cost_per_action_usd)), "actions": ad.actions, "actionType": ad.action_type, "rate": float(ad.rate), "rateType": ad.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "creativeUrl": ad.creative_image_url, "creativeType": AdReportingCreativeType.IMAGE, "thumbnailUrl": None, "creativeThumbnail": None, "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budgetType": "CAMPAIGN_BUDGET", "reportId": None, "reportName": None, } ], "limit": 25, "offset": 0, "total": 1, # deprecated } @pytest.mark.db def test_get_ad_reporting_ad( client: TestClient, 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, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_daily_budget=None, campaign_lifetime_budget=fake.integer(), ad_set_daily_budget=None, ad_set_lifetime_budget=None, ) response = client.get(f"/ad-reporting/ads/{ad.id}") assert response.status_code == 200 assert response.json() == { "id": ad.id, "name": ad.name, "campaignId": ad.campaign_id, "campaignName": ad.campaign_name, "adSetId": ad.ad_set_id, "adSetName": ad.ad_set_name, "accountId": ad.account_id, "globalParticipantIds": [ad.campaign_global_participant_id], "platform": ad.platform, "objective": ad.campaign_objective, "targetingCountries": ad.targeting_countries, "reportingUrl": ad.reporting_url, "effectiveStatus": ad.effective_status, "startAt": IsISODatetime(ad.ad_set_start_at), "endAt": IsISODatetime(ad.ad_set_end_at), "clicks": ad.clicks, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "spend": float(ad.spend), "currency": ad.currency, "spendUSD": float(ad.spend_usd), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "frequency": float(ad.frequency), "costPerAction": IsApprox(float(ad.cost_per_action)), "costPerActionUSD": IsApprox(float(ad.cost_per_action_usd)), "actions": ad.actions, "actionType": ad.action_type, "rate": float(ad.rate), "rateType": ad.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "creativeUrl": ad.creative_image_url, "creativeType": AdReportingCreativeType.IMAGE, "thumbnailUrl": None, "creativeThumbnail": None, "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budgetType": "CAMPAIGN_BUDGET", "reportId": None, "reportName": None, } @pytest.mark.db def test_get_ad_reporting_report_ad_sets( client: TestClient, 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, ) ] ) 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, daily_budget=None, lifetime_budget=fake.integer(), campaign_daily_budget=None, campaign_lifetime_budget=None, daily_budget_usd=None, lifetime_budget_usd=fake.integer(), campaign_daily_budget_usd=None, campaign_lifetime_budget_usd=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}/ad-sets") assert response.status_code == 200 assert ad_set.lifetime_budget assert response.json() == { "total": 1, "summary": { "total": 1, "clicks": ad_set.clicks, "impressions": ad_set.impressions, "reach": ad_set.reach, "estimatedAdRecallers": ad_set.estimated_ad_recallers, "viewsP25": ad_set.views_p25, "views": ad_set.views, "purchases": ad_set.purchases, "follows": ad_set.follows, "spend": float(ad_set.spend), "spendUSD": float(ad_set.spend_usd), "likes": ad_set.likes, "completePayment": ad_set.complete_payment, "checkout": ad_set.checkout, "actions": ad_set.actions, "actionType": ad_set.action_type, "rate": IsNumber( approx=float((ad_set.estimated_ad_recallers or 0) / ad_set.reach) ), "rateType": ad_set.rate_type, "costPerAction": IsNumber(approx=float(ad_set.spend / ad_set.actions)), "costPerActionUSD": IsNumber( approx=float(ad_set.spend_usd / ad_set.actions) ), "frequency": IsNumber(approx=float(ad_set.impressions / ad_set.reach)), "budget": ad_set.lifetime_budget, "budgetUSD": ad_set.lifetime_budget_usd, "budgetType": AdReportingBudgetType.LIFETIME_BUDGET, "currency": ad_set.currency, }, "items": [ { "id": ad_set.id, "name": ad_set.name, "accountId": ad_set.account_id, "campaignId": ad_set.campaign_id, "campaignName": ad_set.campaign_name, "globalParticipantIds": [ad_set.campaign_global_participant_id], "platform": ad_set.platform, "objective": ad_set.campaign_objective, "targetingCountries": ad_set.targeting_countries, "reportingUrl": ad_set.reporting_url, "effectiveStatus": ad_set.effective_status, "startAt": IsISODatetime(ad_set.start_at), "endAt": IsISODatetime(ad_set.end_at), "clicks": ad_set.clicks, "impressions": ad_set.impressions, "reach": ad_set.reach, "estimatedAdRecallers": ad_set.estimated_ad_recallers, "viewsP25": ad_set.views_p25, "views": ad_set.views, "purchases": ad_set.purchases, "follows": ad_set.follows, "spend": float(ad_set.spend), "spendUSD": float(ad_set.spend_usd), "likes": ad_set.likes, "completePayment": ad_set.complete_payment, "checkout": ad_set.checkout, "currency": ad_set.currency, "frequency": float(ad_set.frequency), "costPerAction": IsApprox(float(ad_set.cost_per_action)), "costPerActionUSD": IsApprox(float(ad_set.cost_per_action_usd)), "actions": ad_set.actions, "actionType": ad_set.action_type, "rate": float(ad_set.rate), "rateType": ad_set.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budget": ad_set.lifetime_budget, "budgetUSD": ad_set.lifetime_budget_usd, "budgetType": "LIFETIME_BUDGET", "reportId": report.id, "reportName": report.name, } ], "limit": 25, "offset": 0, } @pytest.mark.db def test_get_ad_reporting_report_ad_set( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, fake: FakerTyped, ) -> None: ad_account = create_model(MetaAdAccount) 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=AdReportingPlatform.META, ) ad_set = create_reporting_model( AdReportingAdSetDbt, account_id=ad_account.external_id, platform=AdReportingPlatform.META, campaign_id=campaign.id, daily_budget=None, lifetime_budget=None, campaign_daily_budget=fake.integer(), campaign_lifetime_budget=None, daily_budget_usd=None, lifetime_budget_usd=None, campaign_daily_budget_usd=fake.integer(), campaign_lifetime_budget_usd=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}/ad-sets/{ad_set.id}") assert response.status_code == 200 assert response.json() == { "id": ad_set.id, "name": ad_set.name, "accountId": ad_set.account_id, "campaignId": ad_set.campaign_id, "campaignName": ad_set.campaign_name, "globalParticipantIds": [ad_set.campaign_global_participant_id], "platform": ad_set.platform, "objective": ad_set.campaign_objective, "targetingCountries": ad_set.targeting_countries, "reportingUrl": ad_set.reporting_url, "effectiveStatus": ad_set.effective_status, "startAt": IsISODatetime(ad_set.start_at), "endAt": IsISODatetime(ad_set.end_at), "clicks": ad_set.clicks, "impressions": ad_set.impressions, "reach": ad_set.reach, "estimatedAdRecallers": ad_set.estimated_ad_recallers, "viewsP25": ad_set.views_p25, "views": ad_set.views, "purchases": ad_set.purchases, "follows": ad_set.follows, "spend": float(ad_set.spend), "spendUSD": float(ad_set.spend_usd), "likes": ad_set.likes, "completePayment": ad_set.complete_payment, "checkout": ad_set.checkout, "currency": ad_set.currency, "frequency": float(ad_set.frequency), "costPerAction": IsApprox(float(ad_set.cost_per_action)), "costPerActionUSD": IsApprox(float(ad_set.cost_per_action_usd)), "actions": ad_set.actions, "actionType": ad_set.action_type, "rate": float(ad_set.rate), "rateType": ad_set.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budget": None, "budgetUSD": None, "budgetType": "CAMPAIGN_BUDGET", "reportId": report.id, "reportName": report.name, } @pytest.mark.db def test_get_ad_reporting_report_ads( client: TestClient, 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, ) 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, campaign_daily_budget=None, campaign_lifetime_budget=None, ad_set_daily_budget=fake.integer(), ad_set_lifetime_budget=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}/ads") assert response.status_code == 200 assert response.json() == { "total": 1, "summary": { "total": 1, "clicks": ad.clicks, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "spend": float(ad.spend), "spendUSD": float(ad.spend_usd), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "actions": ad.actions, "actionType": ad.action_type, "rate": IsNumber(approx=float((ad.estimated_ad_recallers or 0) / ad.reach)), "rateType": ad.rate_type, "costPerAction": IsNumber(approx=float(ad.spend / ad.actions)), "costPerActionUSD": IsNumber(approx=float(ad.spend_usd / ad.actions)), "frequency": IsNumber(approx=float(ad.impressions / ad.reach)), "budget": None, "budgetUSD": None, "currency": ad.currency, "budgetType": AdReportingBudgetType.AD_SET_BUDGET, }, "items": [ { "id": ad.id, "name": ad.name, "accountId": ad.account_id, "campaignId": ad.campaign_id, "campaignName": ad.campaign_name, "adSetId": ad.ad_set_id, "adSetName": ad.ad_set_name, "globalParticipantIds": [ad.campaign_global_participant_id], "platform": ad.platform, "objective": ad.campaign_objective, "targetingCountries": ad.targeting_countries, "reportingUrl": ad.reporting_url, "effectiveStatus": ad.effective_status, "startAt": IsISODatetime(ad.ad_set_start_at), "endAt": IsISODatetime(ad.ad_set_end_at), "clicks": ad.clicks, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "spend": IsApprox(float(ad.spend)), "spendUSD": IsApprox(float(ad.spend_usd)), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "currency": ad.currency, "frequency": float(ad.frequency), "costPerAction": IsApprox(float(ad.cost_per_action)), "costPerActionUSD": IsApprox(float(ad.cost_per_action_usd)), "actions": ad.actions, "actionType": ad.action_type, "rate": float(ad.rate), "rateType": ad.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "creativeUrl": ad.creative_image_url, "creativeType": AdReportingCreativeType.IMAGE, "thumbnailUrl": None, "creativeThumbnail": None, "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budgetType": "AD_SET_BUDGET", "reportId": report.id, "reportName": report.name, } ], "limit": 25, "offset": 0, } @pytest.mark.db def test_get_ad_reporting_report_ads_grouped( client: TestClient, 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, ) 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, campaign_daily_budget=None, campaign_lifetime_budget=None, ad_set_daily_budget=fake.integer(), ad_set_lifetime_budget=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}/ads/grouped") assert response.status_code == 200 assert response.json() == { "total": 1, "summary": { "total": 1, "clicks": ad.clicks, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "spend": float(ad.spend), "spendUSD": float(ad.spend_usd), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "actions": ad.actions, "actionType": ad.action_type, "rate": IsNumber(approx=float((ad.estimated_ad_recallers or 0) / ad.reach)), "rateType": ad.rate_type, "costPerAction": IsNumber(approx=float(ad.spend / ad.actions)), "costPerActionUSD": IsNumber(approx=float(ad.spend_usd / ad.actions)), "frequency": IsNumber(approx=float(ad.impressions / ad.reach)), "budget": None, "budgetUSD": None, "currency": ad.currency, "budgetType": AdReportingBudgetType.AD_SET_BUDGET, }, "items": [ { "name": ad.name, "clicks": ad.clicks, "campaignId": ad.campaign_id, "campaignName": ad.campaign_name, "adSetId": ad.ad_set_id, "adSetName": ad.ad_set_name, "effectiveStatus": ad.effective_status, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "currency": ad.currency, "spend": IsApprox(float(ad.spend)), "spendUSD": IsApprox(float(ad.spend_usd)), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "actions": ad.actions, "rate": IsNumber( approx=float((ad.estimated_ad_recallers or 0) / ad.reach) ), "costPerAction": IsNumber(approx=float(ad.spend / ad.actions)), "costPerActionUSD": IsNumber(approx=float(ad.spend_usd / ad.actions)), "frequency": IsNumber(approx=float(ad.impressions / ad.reach)), "globalParticipantIds": [ad.campaign_global_participant_id], "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "platforms": [ad.platform], "objectives": [ad.campaign_objective], "targetingCountries": ad.targeting_countries, "startAt": IsISODatetime(ad.ad_set_start_at), "endAt": IsISODatetime(ad.ad_set_end_at), "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "thumbnailUrl": None, "actionType": ad.action_type, "totalActionsRatio": IsApprox(float(ad.actions / ad.actions)), "rateType": ad.rate_type, "items": [ { "id": ad.id, "name": ad.name, "accountId": ad.account_id, "campaignId": ad.campaign_id, "campaignName": ad.campaign_name, "adSetId": ad.ad_set_id, "adSetName": ad.ad_set_name, "globalParticipantIds": [ad.campaign_global_participant_id], "platform": ad.platform, "objective": ad.campaign_objective, "targetingCountries": ad.targeting_countries, "reportingUrl": ad.reporting_url, "effectiveStatus": ad.effective_status, "startAt": IsISODatetime(ad.ad_set_start_at), "endAt": IsISODatetime(ad.ad_set_end_at), "clicks": ad.clicks, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "spend": IsApprox(float(ad.spend)), "spendUSD": IsApprox(float(ad.spend_usd)), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "currency": ad.currency, "frequency": float(ad.frequency), "costPerAction": IsApprox(float(ad.cost_per_action)), "costPerActionUSD": IsApprox(float(ad.cost_per_action_usd)), "actions": ad.actions, "actionType": ad.action_type, "rate": float(ad.rate), "rateType": ad.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "creativeUrl": ad.creative_image_url, "creativeType": AdReportingCreativeType.IMAGE, "thumbnailUrl": None, "creativeThumbnail": None, "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budgetType": "AD_SET_BUDGET", "reportId": report.id, "reportName": report.name, } ], } ], "limit": 25, "offset": 0, } @pytest.mark.db def test_get_ad_reporting_report_ads_grouped_not_found(client: TestClient) -> None: response = client.get("/ad-reporting/reports/test/ads/grouped") assert response.status_code == 404 @pytest.mark.db def test_get_ad_reporting_report_ad( client: TestClient, 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, ) 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, campaign_daily_budget=None, campaign_lifetime_budget=None, ad_set_daily_budget=fake.integer(), ad_set_lifetime_budget=None, ) report = create_reporting_model( AdReportingReport, identity_id=identity_id, campaign_ids={campaign.id} ) response = client.get(f"/ad-reporting/reports/{report.id}/ads/{ad.id}") assert response.status_code == 200 assert response.json() == { "id": ad.id, "name": ad.name, "accountId": ad.account_id, "campaignId": ad.campaign_id, "campaignName": ad.campaign_name, "adSetId": ad.ad_set_id, "adSetName": ad.ad_set_name, "globalParticipantIds": [ad.campaign_global_participant_id], "platform": ad.platform, "objective": ad.campaign_objective, "targetingCountries": ad.targeting_countries, "reportingUrl": ad.reporting_url, "effectiveStatus": ad.effective_status, "startAt": IsISODatetime(ad.ad_set_start_at), "endAt": IsISODatetime(ad.ad_set_end_at), "clicks": ad.clicks, "impressions": ad.impressions, "reach": ad.reach, "estimatedAdRecallers": ad.estimated_ad_recallers, "viewsP25": ad.views_p25, "views": ad.views, "purchases": ad.purchases, "follows": ad.follows, "spend": IsApprox(float(ad.spend)), "spendUSD": IsApprox(float(ad.spend_usd)), "likes": ad.likes, "completePayment": ad.complete_payment, "checkout": ad.checkout, "currency": ad.currency, "frequency": float(ad.frequency), "costPerAction": IsApprox(float(ad.cost_per_action)), "costPerActionUSD": IsApprox(float(ad.cost_per_action_usd)), "actions": ad.actions, "actionType": ad.action_type, "rate": float(ad.rate), "rateType": ad.rate_type, "accounts": [ { "vendorId": user_ad_account.vendor_id, "subaccountId": user_ad_account.subaccount_id, } ], "creativeUrl": ad.creative_image_url, "creativeType": AdReportingCreativeType.IMAGE, "thumbnailUrl": None, "creativeThumbnail": None, "benchmark": None, "vsBenchmark": None, "artistBenchmark": None, "vsArtistBenchmark": None, "budgetType": "AD_SET_BUDGET", "reportId": report.id, "reportName": report.name, } @pytest.mark.db def test_get_ad_reporting_campaigns_objectives_empty(client: TestClient) -> None: response = client.get("/ad-reporting/campaigns-objectives") assert response.status_code == 200 assert response.json() == [] @pytest.mark.db def test_get_ad_reporting_campaigns_objectives( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) response = client.get("/ad-reporting/campaigns-objectives") assert response.status_code == 200 assert response.json() == [ { "platform": campaign.platform, "objective": campaign.objective, } ] @pytest.mark.db def test_add_ad_reporting_report_to_campaigns( client: TestClient, create_model: CreateModel, create_reporting_model: CreateReportingModel, identity_id: str, account: Account, ) -> None: ad_account = create_model(MetaAdAccount) 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, ) report = create_reporting_model(AdReportingReport, identity_id=identity_id) response = client.post( f"/ad-reporting/reports/{report.id}/campaigns", json={"campaignIds": [campaign.id]}, ) assert response.status_code == 200 assert response.json() == {"campaignsAdded": 1}