feat: products quantity and total price in deal schemas
This commit is contained in:
@ -1,9 +1,16 @@
|
|||||||
|
from sqlalchemy import func
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
|
|
||||||
from models import Deal, Board, DealStatusHistory
|
from models import Deal, Board, DealStatusHistory
|
||||||
|
from modules.fulfillment_base.models import (
|
||||||
|
DealService,
|
||||||
|
Service,
|
||||||
|
DealProductService,
|
||||||
|
DealProduct,
|
||||||
|
)
|
||||||
from repositories.mixins import *
|
from repositories.mixins import *
|
||||||
from schemas.base import SortDir
|
from schemas.base import SortDir
|
||||||
from schemas.deal import UpdateDealSchema, CreateDealSchema
|
from schemas.deal import UpdateDealSchema, CreateDealSchema, DealSchema
|
||||||
from utils.sorting import apply_sorting
|
from utils.sorting import apply_sorting
|
||||||
|
|
||||||
|
|
||||||
@ -17,6 +24,49 @@ class DealRepository(
|
|||||||
entity_class = Deal
|
entity_class = Deal
|
||||||
entity_not_found_msg = "Сделка не найдена"
|
entity_not_found_msg = "Сделка не найдена"
|
||||||
|
|
||||||
|
def _get_price_subquery(self):
|
||||||
|
deal_services_subquery = (
|
||||||
|
select(
|
||||||
|
DealService.deal_id,
|
||||||
|
func.sum(DealService.quantity * DealService.price).label("total_price"),
|
||||||
|
)
|
||||||
|
.join(Service)
|
||||||
|
.group_by(DealService.deal_id)
|
||||||
|
)
|
||||||
|
product_services_subquery = select(
|
||||||
|
select(
|
||||||
|
DealProductService.deal_id,
|
||||||
|
func.sum(DealProduct.quantity * DealProductService.price).label(
|
||||||
|
"total_price"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.join(DealProduct)
|
||||||
|
.group_by(DealProductService.deal_id)
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
union_subqueries = deal_services_subquery.union_all(
|
||||||
|
product_services_subquery
|
||||||
|
).subquery()
|
||||||
|
final_subquery = (
|
||||||
|
select(
|
||||||
|
union_subqueries.c.deal_id,
|
||||||
|
func.sum(union_subqueries.c.total_price).label("total_price"),
|
||||||
|
)
|
||||||
|
.group_by(union_subqueries.c.deal_id)
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
return final_subquery
|
||||||
|
|
||||||
|
def _get_products_quantity_subquery(self):
|
||||||
|
return (
|
||||||
|
select(
|
||||||
|
DealProduct.deal_id,
|
||||||
|
func.sum(DealProduct.quantity).label("products_quantity"),
|
||||||
|
)
|
||||||
|
.group_by(DealProduct.deal_id)
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
|
||||||
async def get_all(
|
async def get_all(
|
||||||
self,
|
self,
|
||||||
page: Optional[int],
|
page: Optional[int],
|
||||||
@ -28,9 +78,23 @@ class DealRepository(
|
|||||||
status_id: Optional[int],
|
status_id: Optional[int],
|
||||||
id: Optional[int],
|
id: Optional[int],
|
||||||
name: Optional[str],
|
name: Optional[str],
|
||||||
) -> tuple[list[Deal], int]:
|
) -> tuple[list[tuple[Deal, int, int]], int]:
|
||||||
|
price_subquery = self._get_price_subquery()
|
||||||
|
products_quantity_subquery = self._get_products_quantity_subquery()
|
||||||
stmt = (
|
stmt = (
|
||||||
select(Deal)
|
select(
|
||||||
|
Deal,
|
||||||
|
func.coalesce(price_subquery.c.total_price, 0),
|
||||||
|
func.coalesce(products_quantity_subquery.c.products_quantity, 0),
|
||||||
|
)
|
||||||
|
.outerjoin(
|
||||||
|
price_subquery,
|
||||||
|
Deal.id == price_subquery.c.deal_id,
|
||||||
|
)
|
||||||
|
.outerjoin(
|
||||||
|
products_quantity_subquery,
|
||||||
|
Deal.id == products_quantity_subquery.c.deal_id,
|
||||||
|
)
|
||||||
.options(joinedload(Deal.status), joinedload(Deal.board))
|
.options(joinedload(Deal.status), joinedload(Deal.board))
|
||||||
.where(Deal.is_deleted.is_(False))
|
.where(Deal.is_deleted.is_(False))
|
||||||
)
|
)
|
||||||
@ -56,8 +120,8 @@ class DealRepository(
|
|||||||
if page and items_per_page:
|
if page and items_per_page:
|
||||||
stmt = self._apply_pagination(stmt, page, items_per_page)
|
stmt = self._apply_pagination(stmt, page, items_per_page)
|
||||||
|
|
||||||
result = await self.session.execute(stmt)
|
rows: list[tuple[Deal, int, int]] = (await self.session.execute(stmt)).all()
|
||||||
return list(result.scalars().all()), total_items
|
return rows, total_items
|
||||||
|
|
||||||
def _process_get_by_id_stmt(self, stmt: Select) -> Select:
|
def _process_get_by_id_stmt(self, stmt: Select) -> Select:
|
||||||
return stmt.options(joinedload(Deal.status), joinedload(Deal.board))
|
return stmt.options(joinedload(Deal.status), joinedload(Deal.board))
|
||||||
|
|||||||
@ -17,6 +17,10 @@ class DealSchema(BaseSchema):
|
|||||||
status: StatusSchema
|
status: StatusSchema
|
||||||
board: BoardSchema
|
board: BoardSchema
|
||||||
created_at: datetime
|
created_at: datetime
|
||||||
|
# FF module
|
||||||
|
products_quantity: int = 0
|
||||||
|
total_price: float = 0
|
||||||
|
# clients module
|
||||||
client: Optional[ClientSchema] = None
|
client: Optional[ClientSchema] = None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class DealService(
|
|||||||
sorting: SortingSchema,
|
sorting: SortingSchema,
|
||||||
*filters,
|
*filters,
|
||||||
) -> GetDealsResponse:
|
) -> GetDealsResponse:
|
||||||
deals, total_items = await self.repository.get_all(
|
rows, total_items = await self.repository.get_all(
|
||||||
pagination.page,
|
pagination.page,
|
||||||
pagination.items_per_page,
|
pagination.items_per_page,
|
||||||
sorting.field,
|
sorting.field,
|
||||||
@ -38,8 +38,17 @@ class DealService(
|
|||||||
if pagination.items_per_page:
|
if pagination.items_per_page:
|
||||||
total_pages = math.ceil(total_items / pagination.items_per_page)
|
total_pages = math.ceil(total_items / pagination.items_per_page)
|
||||||
|
|
||||||
|
deals = [
|
||||||
|
DealSchema(
|
||||||
|
**deal.__dict__,
|
||||||
|
products_quantity=products_quantity,
|
||||||
|
total_price=total_price,
|
||||||
|
)
|
||||||
|
for deal, total_price, products_quantity in rows
|
||||||
|
]
|
||||||
|
|
||||||
return GetDealsResponse(
|
return GetDealsResponse(
|
||||||
items=[DealSchema.model_validate(deal) for deal in deals],
|
items=deals,
|
||||||
pagination_info=PaginationInfoSchema(
|
pagination_info=PaginationInfoSchema(
|
||||||
total_pages=total_pages, total_items=total_items
|
total_pages=total_pages, total_items=total_items
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user