feat: added tags for cards, aligned status headers

This commit is contained in:
2025-03-09 19:30:52 +04:00
parent 487174c4ff
commit 6030591e3c
17 changed files with 375 additions and 23 deletions

View File

@@ -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='Указана некорректная группировка')