fix: cards fetch optimization
This commit is contained in:
		@@ -5,7 +5,7 @@ from typing import Annotated
 | 
				
			|||||||
from fastapi import APIRouter, Depends, Response, UploadFile
 | 
					from fastapi import APIRouter, Depends, Response, UploadFile
 | 
				
			||||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
					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 backend.session import get_session
 | 
				
			||||||
from generators.deal_pdf_generator.generator import DealTechSpecPdfGenerator
 | 
					from generators.deal_pdf_generator.generator import DealTechSpecPdfGenerator
 | 
				
			||||||
from models import User
 | 
					from models import User
 | 
				
			||||||
@@ -78,7 +78,7 @@ async def change_status(
 | 
				
			|||||||
    return await CardsService(session).change_status_manual(request, user)
 | 
					    return await CardsService(session).change_status_manual(request, user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@card_router.get(
 | 
					@card_router.post(
 | 
				
			||||||
    '/summaries',
 | 
					    '/summaries',
 | 
				
			||||||
    response_model=CardSummaryResponse,
 | 
					    response_model=CardSummaryResponse,
 | 
				
			||||||
    operation_id='getCardSummaries',
 | 
					    operation_id='getCardSummaries',
 | 
				
			||||||
@@ -86,9 +86,10 @@ async def change_status(
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
async def get_summary(
 | 
					async def get_summary(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        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(
 | 
					@card_router.post(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ from typing import List, Optional, Union
 | 
				
			|||||||
from pydantic import constr
 | 
					from pydantic import constr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from schemas.attribute import CardAttributeSchema
 | 
					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.billing import CardBillRequestSchema
 | 
				
			||||||
from schemas.board import BoardSchema
 | 
					from schemas.board import BoardSchema
 | 
				
			||||||
from schemas.card_tag import CardTagSchema
 | 
					from schemas.card_tag import CardTagSchema
 | 
				
			||||||
@@ -164,6 +164,18 @@ class CardChangeStatusRequest(BaseSchema):
 | 
				
			|||||||
    new_status: int
 | 
					    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):
 | 
					class CardCreateRequest(BaseSchema):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    status_id: int
 | 
					    status_id: int
 | 
				
			||||||
@@ -345,6 +357,7 @@ class CardQuickCreateResponse(BaseSchema):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class CardSummaryResponse(BaseSchema):
 | 
					class CardSummaryResponse(BaseSchema):
 | 
				
			||||||
    summaries: List[CardSummary]
 | 
					    summaries: List[CardSummary]
 | 
				
			||||||
 | 
					    pagination_info: PaginationInfoSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CardAddServicesResponse(BaseSchema):
 | 
					class CardAddServicesResponse(BaseSchema):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,16 @@
 | 
				
			|||||||
from collections import defaultdict
 | 
					from collections import defaultdict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import lexorank
 | 
					import lexorank
 | 
				
			||||||
 | 
					import math
 | 
				
			||||||
from fastapi import HTTPException
 | 
					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 sqlalchemy.orm import joinedload, selectinload
 | 
				
			||||||
from starlette import status
 | 
					from starlette import status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from card_attributes import CardAttributesCommandHandler
 | 
					from card_attributes import CardAttributesCommandHandler
 | 
				
			||||||
from card_attributes.exceptions import CardAttributeException
 | 
					from card_attributes.exceptions import CardAttributeException
 | 
				
			||||||
from models import *
 | 
					from models import *
 | 
				
			||||||
 | 
					from schemas.base import PaginationSchema
 | 
				
			||||||
from schemas.card import *
 | 
					from schemas.card import *
 | 
				
			||||||
from schemas.client import ClientDetailsSchema
 | 
					from schemas.client import ClientDetailsSchema
 | 
				
			||||||
from services import card_group
 | 
					from services import card_group
 | 
				
			||||||
@@ -179,7 +181,61 @@ class CardsService(BaseService):
 | 
				
			|||||||
            .subquery()
 | 
					            .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()
 | 
					        price_subquery = self._get_price_subquery()
 | 
				
			||||||
        products_quantity_subquery = self._get_products_quantity_subquery()
 | 
					        products_quantity_subquery = self._get_products_quantity_subquery()
 | 
				
			||||||
        q = (
 | 
					        q = (
 | 
				
			||||||
@@ -210,13 +266,14 @@ class CardsService(BaseService):
 | 
				
			|||||||
                Card.is_deleted == False,
 | 
					                Card.is_deleted == False,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        if not full:
 | 
					
 | 
				
			||||||
            q = q.where(
 | 
					        q = self._apply_summary_filters(q, request)
 | 
				
			||||||
                Card.is_completed == False,
 | 
					
 | 
				
			||||||
                # Card.current_status != CardStatus.COMPLETED
 | 
					        pagination_info = await self._summaries_pagination_info(q, pagination)
 | 
				
			||||||
            )
 | 
					
 | 
				
			||||||
        else:
 | 
					        if pagination.page and pagination.items_per_page:
 | 
				
			||||||
            q = q.order_by(Card.created_at.desc())
 | 
					            q = CardsService._apply_pagination(q, pagination)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cards_query = await self.session.execute(q)
 | 
					        cards_query = await self.session.execute(q)
 | 
				
			||||||
        summaries = []
 | 
					        summaries = []
 | 
				
			||||||
        for card, total_price, rank, products_count in cards_query.all():
 | 
					        for card, total_price, rank, products_count in cards_query.all():
 | 
				
			||||||
@@ -247,7 +304,7 @@ class CardsService(BaseService):
 | 
				
			|||||||
                    attributes=attributes,
 | 
					                    attributes=attributes,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        return CardSummaryResponse(summaries=summaries)
 | 
					        return CardSummaryResponse(summaries=summaries, pagination_info=pagination_info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def get_all(self) -> CardGetAllResponse:
 | 
					    async def get_all(self) -> CardGetAllResponse:
 | 
				
			||||||
        cards_stmt = (
 | 
					        cards_stmt = (
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user