fix: cards fetch optimization

This commit is contained in:
2025-04-15 10:59:41 +04:00
parent c08c2c04c4
commit 68f94cc9a4
3 changed files with 86 additions and 15 deletions

View File

@@ -5,7 +5,7 @@ from typing import Annotated
from fastapi import APIRouter, Depends, Response, UploadFile
from sqlalchemy.ext.asyncio import AsyncSession
from backend.dependecies import SessionDependency, CurrentUserDependency
from backend.dependecies import SessionDependency, CurrentUserDependency, PaginationDependency
from backend.session import get_session
from generators.deal_pdf_generator.generator import DealTechSpecPdfGenerator
from models import User
@@ -78,7 +78,7 @@ async def change_status(
return await CardsService(session).change_status_manual(request, user)
@card_router.get(
@card_router.post(
'/summaries',
response_model=CardSummaryResponse,
operation_id='getCardSummaries',
@@ -86,9 +86,10 @@ async def change_status(
)
async def get_summary(
session: Annotated[AsyncSession, Depends(get_session)],
full: Optional[bool]
request: GetCardSummariesRequest,
pagination: PaginationDependency,
):
return await CardsService(session).get_summary(full)
return await CardsService(session).get_summary(request, pagination)
@card_router.post(

View File

@@ -4,7 +4,7 @@ from typing import List, Optional, Union
from pydantic import constr
from schemas.attribute import CardAttributeSchema
from schemas.base import BaseSchema, OkMessageSchema
from schemas.base import BaseSchema, OkMessageSchema, PaginationInfoSchema
from schemas.billing import CardBillRequestSchema
from schemas.board import BoardSchema
from schemas.card_tag import CardTagSchema
@@ -164,6 +164,18 @@ class CardChangeStatusRequest(BaseSchema):
new_status: int
class GetCardSummariesRequest(BaseSchema):
full: bool
card_id: Optional[int | str] = None
card_name: Optional[str] = None
marketplace_key: Optional[str] = None
shipping_warehouse_id: Optional[int] = None
client_id: Optional[int] = None
project_id: Optional[int] = None
board_id: Optional[int] = None
status_id: Optional[int] = None
class CardCreateRequest(BaseSchema):
name: str
status_id: int
@@ -345,6 +357,7 @@ class CardQuickCreateResponse(BaseSchema):
class CardSummaryResponse(BaseSchema):
summaries: List[CardSummary]
pagination_info: PaginationInfoSchema
class CardAddServicesResponse(BaseSchema):

View File

@@ -1,14 +1,16 @@
from collections import defaultdict
import lexorank
import math
from fastapi import HTTPException
from sqlalchemy import select, func, update, delete, insert, and_
from sqlalchemy import select, func, update, delete, insert, and_, Select
from sqlalchemy.orm import joinedload, selectinload
from starlette import status
from card_attributes import CardAttributesCommandHandler
from card_attributes.exceptions import CardAttributeException
from models import *
from schemas.base import PaginationSchema
from schemas.card import *
from schemas.client import ClientDetailsSchema
from services import card_group
@@ -179,7 +181,61 @@ class CardsService(BaseService):
.subquery()
)
async def get_summary(self, full: bool = False) -> CardSummaryResponse:
@staticmethod
def _apply_pagination(query: Select, pagination: PaginationSchema) -> Select:
offset = (pagination.page - 1) * pagination.items_per_page
query = (
query
.offset(offset)
.limit(pagination.items_per_page)
)
return query
@staticmethod
def _apply_summary_filters(query: Select, request: GetCardSummariesRequest) -> Select:
if not request.full:
return query.where(Card.is_completed == False)
if request.card_id:
query = query.where(Card.id == request.card_id)
if request.card_name:
query = query.where(Card.name.like(f"%{request.card_name}%"))
if request.status_id:
query = query.where(Card.current_status_id == request.status_id)
elif request.board_id:
query = query.where(Card.board_id == request.board_id)
elif request.project_id:
query = (
query
.join(Board)
.where(Board.project_id == request.project_id)
)
if request.client_id:
query = query.where(Card.client_id == request.client_id)
if request.marketplace_key:
query = query.where(Card.base_marketplace_key == request.marketplace_key)
if request.shipping_warehouse_id:
query = query.where(Card.shipping_warehouse_id == request.shipping_warehouse_id)
query = query.order_by(Card.created_at.desc())
return query
async def _summaries_pagination_info(self, query: Select, pagination: PaginationSchema) -> PaginationInfoSchema:
if not pagination.items_per_page:
return PaginationInfoSchema(total_pages=0, total_items=0)
summaries = (await self.session.scalars(query)).all()
total_items = len(summaries)
return PaginationInfoSchema(
total_pages=math.ceil(total_items / pagination.items_per_page),
total_items=total_items,
)
async def get_summary(self, request: GetCardSummariesRequest, pagination: PaginationSchema) -> CardSummaryResponse:
price_subquery = self._get_price_subquery()
products_quantity_subquery = self._get_products_quantity_subquery()
q = (
@@ -210,13 +266,14 @@ class CardsService(BaseService):
Card.is_deleted == False,
)
)
if not full:
q = q.where(
Card.is_completed == False,
# Card.current_status != CardStatus.COMPLETED
)
else:
q = q.order_by(Card.created_at.desc())
q = self._apply_summary_filters(q, request)
pagination_info = await self._summaries_pagination_info(q, pagination)
if pagination.page and pagination.items_per_page:
q = CardsService._apply_pagination(q, pagination)
cards_query = await self.session.execute(q)
summaries = []
for card, total_price, rank, products_count in cards_query.all():
@@ -247,7 +304,7 @@ class CardsService(BaseService):
attributes=attributes,
)
)
return CardSummaryResponse(summaries=summaries)
return CardSummaryResponse(summaries=summaries, pagination_info=pagination_info)
async def get_all(self) -> CardGetAllResponse:
cards_stmt = (