from db import db from typing import List, Optional from sqlalchemy import or_, and_ from models.projects import Project from models.projects import ProjectCampaign, ProjectCampaignStatus from models.campaign import Campaign from models.marketing_accounts import MarketingAccount from campaigns.constants import MAX_ASSIGNABLE_PROJECT_LIMIT from shared.query_builders.recent_projects_query_builder import RecentProjectsQueryBuilder from shared.query_builders.projects_query_builder import BuilderJoin, DynamicFields class CampaignsAssignableProjectsRepository: def __filter_assignable_projects(self, builder: RecentProjectsQueryBuilder, query: Optional[str], currency: str): builder.only_claimed().only_accessible_projects().with_currency(currency) if query: builder.filtered_by_search(query) not_assigned = ProjectCampaign.status.is_(None) is_rejected = ProjectCampaign.status == ProjectCampaignStatus.REJECTED.value builder.filter_items.append(or_(not_assigned, is_rejected)) def get_assignable_projects(self, campaign_uuid: str, user_id: int, params) -> List[Project]: builder = RecentProjectsQueryBuilder(user_id) builder.dynamic_fields = [DynamicFields.USER_ROLE] builder.additional_joins = [ BuilderJoin(Campaign, Campaign.uuid == campaign_uuid, inner=False), BuilderJoin( ProjectCampaign, and_(Project.id == ProjectCampaign.project_id, ProjectCampaign.campaign_id == Campaign.id), inner=False, ) ] currency = self.__get_campaign_currency(campaign_uuid) self.__filter_assignable_projects(builder, params.query, currency) builder.limit_to(MAX_ASSIGNABLE_PROJECT_LIMIT) return list(map(lambda x: x.Project, builder.items_query().all())) def __get_campaign_currency(self, campaign_uuid: str) -> Optional[str]: return ( db.session.query(MarketingAccount.currency) .join(Campaign, Campaign.external_marketing_account_id == MarketingAccount.external_id) .filter(Campaign.uuid == campaign_uuid) .scalar() )