from typing import List from db import db from workers.base_worker import BaseWorker from models import Campaign from models.projects import ProjectCampaign from models.campaign_provider import Providers from services.users_repository import UsersRepository from campaigns.schemas import CampaignEditableFields, CampaignMetadata from campaigns.repositories.campaigns_repository import CampaignsRepository from campaigns.services.campaigns_history_service import CampaignHistoryService from projects.repositories.projects_repository import ProjectsRepository from linkfire.linkfire_repository import LinkfireRepository from utils import list_utils from utils.json_encoder import DataclassDictionaryEncoder as Encoder from utils.reporting.worker_logger import WorkerLogger from utils.snowflake.tiktok_data.models import TikTokCampaignModel from utils.snowflake.tiktok_data.utils import TikTokWorkerUtils from workers import helpers class TikTokCampaignsWorker(BaseWorker): campaigns_repository: CampaignsRepository = CampaignsRepository() projects_repository: ProjectsRepository = ProjectsRepository() users_repository: UsersRepository = UsersRepository() linkfire_repository: LinkfireRepository = LinkfireRepository() history_service: CampaignHistoryService = CampaignHistoryService() utils: TikTokWorkerUtils = TikTokWorkerUtils() logger: WorkerLogger = WorkerLogger() def should_log_exceptions(self): return True def execute(self, campaigns: List[TikTokCampaignModel]): mapped_campaigns = [] for campaign in campaigns: mapped_campaigns.append(self.process_campaign(campaign)) db.session.commit() Campaign.index_models(mapped_campaigns) db.session.close() def process_campaign(self, campaign: TikTokCampaignModel) -> Campaign: gras_user_id = self.users_repository.get_gras_user_id() projects = self.get_possible_projects(campaign) tiktok_campaign = self.campaigns_repository.get_campaign_by_external_id(str(campaign.id)) genders = self.utils.build_gender_ids(campaign.genders) fields_object = CampaignEditableFields() fields_object.countries = campaign.country_codes == [self.utils.global_country_code] fields_object.audienceAge = campaign.ages is None fields_object.startDate = campaign.start_date is None fields_object.endDate = campaign.end_date is None fields_object.destinations = True fields_object.budget = not (campaign.planned_budget > 0) fields_object.spend = False fields_object.genders = genders is None fields_object.notes = True fields_object.name = False fields_object.provider = False fields_object.objective = False fields_object.typeId = False fields_object.platforms = False fields_object.gratis = False is_new = False state = None if not tiktok_campaign: tiktok_campaign = Campaign() tiktok_campaign.external_id = campaign.id is_new = True else: state = self.history_service.get_campaign_state(tiktok_campaign) if not tiktok_campaign.project_id: for project in projects: already_assigned = list_utils.exists( project.project_campaigns, lambda x: x.campaign.external_id == str(campaign.id) ) if not already_assigned: project_campaign = ProjectCampaign() project_campaign.project = project project_campaign.campaign = tiktok_campaign project.project_campaigns.append(project_campaign) provider_id = self.campaigns_repository.provider_id_for_account(campaign.marketing_account_id) budget = campaign.planned_budget or 0 tiktok_campaign.name = campaign.name tiktok_campaign.start_date = campaign.start_date tiktok_campaign.end_date = campaign.end_date tiktok_campaign.planned_budget = budget tiktok_campaign.budget_spend = campaign.budget_spend tiktok_campaign.external_marketing_account_id = campaign.marketing_account_id tiktok_campaign.objective_id = self.utils.build_objective(campaign.objective) tiktok_campaign.provider_id = provider_id or Providers.GuptaMedia.value tiktok_campaign.age_range = self.utils.build_age_range(campaign.ages) tiktok_campaign.genders = self.campaigns_repository.get_campaign_genders_by_ids( genders or self.utils.default_genders ) tiktok_campaign.source = self.utils.source_name tiktok_campaign.metainfo = Encoder.convert_to_dict(CampaignMetadata(fields=fields_object)) tiktok_campaign.gratis = False tiktok_campaign.type = self.campaigns_repository.get_campaign_type_by_name(self.utils.default_campaign_type) platform = self.campaigns_repository.get_campaign_platform_by_id(self.utils.platform_id) if platform is not None: tiktok_campaign.platforms.append(platform) self.campaigns_repository.update_campaign_territories( campaign=tiktok_campaign, territories=self.utils.map_territories(campaign.country_codes), budget_spend=budget ) db.session.flush() db.session.refresh(tiktok_campaign) if is_new: self.history_service.log_campaign_created(tiktok_campaign, None, gras_user_id) else: self.history_service.log_campaign_changes(tiktok_campaign, state, gras_user_id) return tiktok_campaign def get_possible_projects(self, campaign: TikTokCampaignModel): projects = [] currency = self.campaigns_repository.get_currency_for_marketing_account(campaign.marketing_account_id) prs_code = helpers.prs_id_from_campaign_name(campaign.name) if prs_code is not None: prs_project = self.projects_repository.get_project_by_PRS_id(prs_code, currency) projects.append(prs_project) elif helpers.is_name_includes_external_id(campaign.name): external_id = helpers.get_campaign_name_first_part(campaign.name) projects = self.projects_repository.get_projects_by_GRAS_id(external_id, currency) if len(projects) == 0: projects = self.projects_repository.get_projects_with_artists( campaign.artists, campaign.start_date, str(campaign.marketing_account_id), currency ) return projects