from typing import Optional from dataclasses import dataclass from enum import Enum from db import db from constants.project_statuses import ProjectStatuses from projects.constants import ProjectTargetTypes from projects.schemas import ProjectListQueryParams, ProjectsCountResponseSchema from projects.repositories.projects_repository import ProjectsRepository from shared.query_builders.projects_query_builder import ProjectsQueryBuilder @dataclass class DefaultQueryParams: user_id: int filters: Optional[ProjectListQueryParams] = None external_artist_id: Optional[str] = None class ClaimType(Enum): CLAIMED = 1 UNCLAIMED = 2 ALL = 3 class ProjectsCounterRepository: project_repository: ProjectsRepository def __init__(self, project_repository: ProjectsRepository = ProjectsRepository()): self.project_repository = project_repository def get_projects_count( self, user_id: int, params: ProjectListQueryParams, external_artist_id: Optional[str] = None ) -> ProjectsCountResponseSchema: query_params = DefaultQueryParams(filters=params, user_id=user_id, external_artist_id=external_artist_id) total_params = DefaultQueryParams(user_id=user_id, external_artist_id=external_artist_id) queries = [] queries_dict = { "total_artists": self.count_query(total_params, entity_type=ProjectTargetTypes.ARTIST), "total_playlists": self.count_query(total_params, entity_type=ProjectTargetTypes.PLAYLIST), "total": self.count_query(total_params), "unassigned_total": self.count_query(total_params, claimed=ClaimType.UNCLAIMED), "unassigned_artists": self.count_query( query_params, claimed=ClaimType.UNCLAIMED, entity_type=ProjectTargetTypes.ARTIST ), "in_progress_artist": self.count_query( query_params, claimed=ClaimType.CLAIMED, entity_type=ProjectTargetTypes.ARTIST, status=ProjectStatuses.INPROGRESS.value, ), "in_progress_playlist": self.count_query( query_params, claimed=ClaimType.CLAIMED, entity_type=ProjectTargetTypes.PLAYLIST, status=ProjectStatuses.INPROGRESS.value, ), "in_progress_total": self.count_query( query_params, claimed=ClaimType.CLAIMED, status=ProjectStatuses.INPROGRESS.value ), "completed_artist": self.count_query( query_params, claimed=ClaimType.CLAIMED, entity_type=ProjectTargetTypes.ARTIST, status=ProjectStatuses.COMPLETED.value, ), "completed_playlist": self.count_query( query_params, claimed=ClaimType.CLAIMED, entity_type=ProjectTargetTypes.PLAYLIST, status=ProjectStatuses.COMPLETED.value, ), "completed_total": self.count_query( query_params, claimed=ClaimType.CLAIMED, status=ProjectStatuses.COMPLETED.value ), "scheduled_artist": self.count_query( query_params, claimed=ClaimType.CLAIMED, entity_type=ProjectTargetTypes.ARTIST, status=ProjectStatuses.SCHEDULED.value, ), "scheduled_playlist": self.count_query( query_params, claimed=ClaimType.CLAIMED, entity_type=ProjectTargetTypes.PLAYLIST, status=ProjectStatuses.SCHEDULED.value, ), "scheduled_total": self.count_query( query_params, claimed=ClaimType.CLAIMED, status=ProjectStatuses.SCHEDULED.value ), } for key, value in queries_dict.items(): queries.append(value.label(key)) return ProjectsCountResponseSchema(db.session.query(*queries).one()) def count_query( self, params: DefaultQueryParams, claimed: ClaimType = ClaimType.CLAIMED, status: Optional[int] = None, entity_type: Optional[ProjectTargetTypes] = None, ): query_builder = ProjectsQueryBuilder(params.user_id).only_accessible_projects() self.__apply_counter_filters(query_builder, params.filters, params.external_artist_id, claimed) if claimed == ClaimType.CLAIMED: query_builder.only_claimed() if claimed == ClaimType.UNCLAIMED: query_builder.only_unclaimed() if status is not None: query_builder.filter_by_status(status) if entity_type is not None: query_builder.filtered_by_type(entity_type.value) return query_builder.count_query() def __apply_counter_filters( self, builder: ProjectsQueryBuilder, params: ProjectListQueryParams, artist_external_id: Optional[str] = None, claimed: ClaimType = ClaimType.CLAIMED, ): if params and params.freeText is not None: builder.filtered_by_search(params.freeText) if params and params.earliestStartDate is not None and params.latestEndDate is not None: builder.filtered_by_date_range(params.earliestStartDate, params.latestEndDate) if params and params.labels: builder.filtered_by_labels(params.labels) if artist_external_id: builder.filtered_by_artist(artist_external_id) if params and params.onlyMine and claimed == ClaimType.CLAIMED: builder.only_claimed().only_mine()