feat: added tags for cards, aligned status headers
This commit is contained in:
		@@ -5,7 +5,7 @@ from sqlalchemy import select, and_, union_all, func, Subquery, literal
 | 
			
		||||
 | 
			
		||||
from enums.profit_table_group_by import ProfitTableGroupBy
 | 
			
		||||
from models import CardService, Card, CardStatusHistory, CardProductService, CardProduct, Service, Client, \
 | 
			
		||||
    ShippingWarehouse, BaseMarketplace, User, Project, Board
 | 
			
		||||
    ShippingWarehouse, BaseMarketplace, User, Project, Board, CardTag, cards_card_tags, user_position
 | 
			
		||||
from schemas.statistics import GetProfitChartDataResponse, GetProfitChartDataRequest, ProfitChartDataItem, \
 | 
			
		||||
    GetProfitTableDataResponse, GetProfitTableDataRequest, ProfitTableDataItem, CommonProfitFilters
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
@@ -112,13 +112,11 @@ class ProfitStatisticsService(BaseService):
 | 
			
		||||
            .join(Service, CardService.service_id == Service.id)
 | 
			
		||||
            .join(sub_filtered_status_history, Card.id == sub_filtered_status_history.c.card_id)
 | 
			
		||||
            .where(
 | 
			
		||||
                and_(
 | 
			
		||||
                    Card.is_deleted == False,
 | 
			
		||||
                    Card.is_services_profit_accounted == True,
 | 
			
		||||
                    Card.is_completed == True if self.is_completed_only else True
 | 
			
		||||
                )
 | 
			
		||||
                Card.is_deleted == False,
 | 
			
		||||
                Card.is_services_profit_accounted == True,
 | 
			
		||||
                Card.is_completed == True if self.is_completed_only else True,
 | 
			
		||||
            )
 | 
			
		||||
            .group_by(Card.id, "date")
 | 
			
		||||
            .group_by(Card.id, sub_filtered_status_history.c.date)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
@@ -129,6 +127,14 @@ class ProfitStatisticsService(BaseService):
 | 
			
		||||
        )
 | 
			
		||||
        return stmt.where(Card.board_id.in_(board_ids_stmt))
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _apply_tag_filter(tag_id: int, stmt):
 | 
			
		||||
        sub_card_ids = (
 | 
			
		||||
            select(cards_card_tags.c.card_id)
 | 
			
		||||
            .where(cards_card_tags.c.card_tag_id == tag_id)
 | 
			
		||||
        )
 | 
			
		||||
        return stmt.where(Card.id.in_(sub_card_ids))
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _apply_filters(request: CommonProfitFilters, stmt_card_services, stmt_card_product_services):
 | 
			
		||||
        if request.client_id != -1:
 | 
			
		||||
@@ -156,6 +162,13 @@ class ProfitStatisticsService(BaseService):
 | 
			
		||||
                    stmt_card_product_services = stmt_card_product_services.where(
 | 
			
		||||
                        Card.current_status_id == request.card_status_id)
 | 
			
		||||
 | 
			
		||||
            if request.card_tag_id != -1:
 | 
			
		||||
                stmt_card_services = ProfitStatisticsService._apply_tag_filter(request.card_tag_id, stmt_card_services)
 | 
			
		||||
                stmt_card_product_services = ProfitStatisticsService._apply_tag_filter(
 | 
			
		||||
                    request.card_tag_id,
 | 
			
		||||
                    stmt_card_product_services
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
        if request.manager_id != -1:
 | 
			
		||||
            stmt_card_services = stmt_card_services.where(Card.manager_id == request.manager_id)
 | 
			
		||||
            stmt_card_product_services = stmt_card_product_services.where(Card.manager_id == request.manager_id)
 | 
			
		||||
@@ -334,7 +347,8 @@ class ProfitStatisticsService(BaseService):
 | 
			
		||||
    def _join_and_group_by_managers(stmt):
 | 
			
		||||
        managers = (
 | 
			
		||||
            select(User)
 | 
			
		||||
            .where(User.role_key == "employee")
 | 
			
		||||
            .join(user_position)
 | 
			
		||||
            .where(and_(User.is_deleted == False, user_position.c.position_key == "sales_manager"))
 | 
			
		||||
            .subquery()
 | 
			
		||||
        )
 | 
			
		||||
        return (
 | 
			
		||||
@@ -350,6 +364,23 @@ class ProfitStatisticsService(BaseService):
 | 
			
		||||
            .group_by(managers.c.id, "grouped_value")
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _join_and_group_by_tags(stmt):
 | 
			
		||||
        return (
 | 
			
		||||
            select(
 | 
			
		||||
                CardTag.id,
 | 
			
		||||
                CardTag.name.label("grouped_value"),
 | 
			
		||||
                CardTag.is_deleted,
 | 
			
		||||
                func.count(stmt.c.card_id).label("cards_count"),
 | 
			
		||||
                func.sum(stmt.c.revenue).label("revenue"),
 | 
			
		||||
                func.sum(stmt.c.profit).label("profit"),
 | 
			
		||||
            )
 | 
			
		||||
            .join(cards_card_tags, cards_card_tags.c.card_id == stmt.c.card_id)
 | 
			
		||||
            .join(CardTag, cards_card_tags.c.card_tag_id == CardTag.id)
 | 
			
		||||
            .where(CardTag.is_deleted == False)
 | 
			
		||||
            .group_by(CardTag.is_deleted, CardTag.id, CardTag.name)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    async def _get_data_rows_grouped_by_date(
 | 
			
		||||
            self,
 | 
			
		||||
            stmt_card_services,
 | 
			
		||||
@@ -476,6 +507,7 @@ class ProfitStatisticsService(BaseService):
 | 
			
		||||
 | 
			
		||||
    async def _get_table_grouped_by_statuses(self, request: GetProfitTableDataRequest) -> GetProfitTableDataResponse:
 | 
			
		||||
        date_from, date_to = request.date_range
 | 
			
		||||
        self.is_completed_only = request.is_completed_only
 | 
			
		||||
 | 
			
		||||
        sub_cards_dates = self._get_filtered_sub_status_history(date_from, date_to)
 | 
			
		||||
 | 
			
		||||
@@ -518,6 +550,12 @@ class ProfitStatisticsService(BaseService):
 | 
			
		||||
 | 
			
		||||
        return await self._table_data_from_stmt(stmt_grouped_by_managers)
 | 
			
		||||
 | 
			
		||||
    async def _get_table_grouped_by_tags(self, request: GetProfitTableDataRequest) -> GetProfitTableDataResponse:
 | 
			
		||||
        sub_grouped_by_cards = self._get_common_table_grouped(request)
 | 
			
		||||
        stmt_grouped_by_tags = self._join_and_group_by_tags(sub_grouped_by_cards)
 | 
			
		||||
 | 
			
		||||
        return await self._table_data_from_stmt(stmt_grouped_by_tags)
 | 
			
		||||
 | 
			
		||||
    async def get_profit_table_data(self, request: GetProfitTableDataRequest) -> GetProfitTableDataResponse:
 | 
			
		||||
        match request.group_table_by:
 | 
			
		||||
            case ProfitTableGroupBy.BY_DATES:
 | 
			
		||||
@@ -536,5 +574,7 @@ class ProfitStatisticsService(BaseService):
 | 
			
		||||
                return await self._get_table_grouped_by_marketplace(request)
 | 
			
		||||
            case ProfitTableGroupBy.BY_MANAGERS:
 | 
			
		||||
                return await self._get_table_grouped_by_managers(request)
 | 
			
		||||
            case ProfitTableGroupBy.BY_TAGS:
 | 
			
		||||
                return await self._get_table_grouped_by_tags(request)
 | 
			
		||||
 | 
			
		||||
        raise HTTPException(status_code=400, detail='Указана некорректная группировка')
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user