from typing import Any, List from marshmallow import ValidationError from campaigns.exceptions import CampaignNotFound from campaigns.repositories.campaigns_repository import CampaignsRepository from media_plan.campaigns_repository import MediaPlanCampaignsRepository from media_plan.exceptions import PhaseOrderError, SingleCampaignInPhaseDeletionError, PhaseNotFound from media_plan.phases_repository import MediaPlanPhasesRepository from models.campaign import Campaign from handlers.enums import CampaignWorkflowStatus from models.media_plans import DEFAULT_MEDIA_PLAN_NAME from projects.repositories.projects_repository import ProjectsRepository from services.permissions.exceptions import ( ProjectNotFound, MediaPlanNotFound, MediaPlanSameNameError, ) from utils.exceptions import BadRequest class PhaseValidator: def validate_user_order(self, new_free_order, user_order): if user_order > new_free_order: raise PhaseOrderError() class CampaignsValidator: campaigns_repository = MediaPlanCampaignsRepository() def validate_delete_campaign(self, campaign: Campaign): if not campaign or campaign.is_deleted: raise CampaignNotFound() if len(self.campaigns_repository.get_manual_campaigns_in_phase(campaign.media_plan_phase_id)) == 1: raise SingleCampaignInPhaseDeletionError() class CampaignExistsValidator: campaigns_repository = CampaignsRepository() def __call__(self, value) -> Any: if isinstance(value, list): for campaign_uuid in value: campaign = self.campaigns_repository.get_campaign_by_uuid(campaign_uuid) if not campaign or campaign.is_deleted: raise ValidationError(f"Campaign with uuid: {campaign_uuid} not found.") else: campaign = self.campaigns_repository.get_campaign_by_uuid(value) if not campaign or campaign.is_deleted: raise ValidationError(f"Campaign with uuid: {value} not found.") return value class RequestApprovalValidator: campaigns_repository = CampaignsRepository() def __call__(self, value: List) -> Any: if len(value) != len(set(value)): raise BadRequest(f"Campaign uuids are repeated in the list: {value}") for campaign_uuid in value: campaign = self.campaigns_repository.get_campaign_by_uuid(campaign_uuid) if (campaign and not campaign.is_deleted and campaign.workflow_status not in [CampaignWorkflowStatus.DRAFT.value, CampaignWorkflowStatus.DISAPPROVED.value]): raise BadRequest( f"You can't create approval request for campaign in {campaign.workflow_status} workflow_status" ) return value class SubmitApprovalValidator: campaigns_repository = CampaignsRepository() def __call__(self, value) -> Any: campaign = self.campaigns_repository.get_campaign_by_uuid(value) if (campaign and not campaign.is_deleted and campaign.workflow_status != CampaignWorkflowStatus.PENDING_APPROVAL.value): raise BadRequest(f"You can't submit approval for campaign in {campaign.workflow_status} workflow_status") return value class ProjectMediaPlanValidator: projects_repository = ProjectsRepository() phases_repository = MediaPlanPhasesRepository() def validate_project_media_plan(self, project_id: int, media_plan_id: int): if not self.projects_repository.project_by_id_exist(project_id): raise ProjectNotFound() if not self.projects_repository.media_plan_exist(project_id, media_plan_id): raise MediaPlanNotFound() def validate_phase(self, phase_id: int): if not self.phases_repository.phase_exist(phase_id): raise PhaseNotFound() def validate_name(self, project_id: int, params_name: str, media_plan_except_id: int = None): if params_name is None: params_name = DEFAULT_MEDIA_PLAN_NAME if self.projects_repository.media_plan_with_name_exist( project_id=project_id, name=params_name, except_id=media_plan_except_id ): raise MediaPlanSameNameError()