feat: deal product services
This commit is contained in:
140
services/deal.py
140
services/deal.py
@@ -4,7 +4,7 @@ import models.secondary
|
||||
from typing import Union
|
||||
import models.deal
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import select, func
|
||||
from sqlalchemy import select, func, update
|
||||
from sqlalchemy.orm import joinedload, selectinload
|
||||
|
||||
from models import User, Service, Client
|
||||
@@ -118,20 +118,42 @@ class DealService(BaseService):
|
||||
await self.session.commit()
|
||||
return DealChangeStatusResponse(ok=True)
|
||||
|
||||
async def get_summary(self) -> DealSummaryResponse:
|
||||
service_subquery = (
|
||||
def _get_price_subquery(self):
|
||||
deal_services_subquery = (
|
||||
select(
|
||||
models.secondary.DealService.deal_id,
|
||||
func.sum(models.secondary.DealService.quantity * Service.price).label('total_price')
|
||||
func.sum(models.secondary.DealService.quantity * models.secondary.DealService.price).label(
|
||||
'total_price')
|
||||
)
|
||||
.join(Service)
|
||||
.group_by(models.secondary.DealService.deal_id)
|
||||
)
|
||||
product_services_subquery = select(
|
||||
select(
|
||||
models.secondary.DealProductService.deal_id,
|
||||
func.sum(models.DealProduct.quantity * models.secondary.DealProductService.price).label('total_price')
|
||||
)
|
||||
.join(models.secondary.DealProduct)
|
||||
.group_by(models.secondary.DealProductService.deal_id)
|
||||
.subquery()
|
||||
)
|
||||
union_subqueries = deal_services_subquery.union(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
|
||||
|
||||
async def get_summary(self) -> DealSummaryResponse:
|
||||
price_subquery = self._get_price_subquery()
|
||||
q = (
|
||||
select(
|
||||
Deal,
|
||||
func.coalesce(service_subquery.c.total_price, 0),
|
||||
func.coalesce(price_subquery.c.total_price, 0),
|
||||
func.row_number().over(
|
||||
partition_by=Deal.current_status,
|
||||
order_by=Deal.lexorank
|
||||
@@ -142,7 +164,7 @@ class DealService(BaseService):
|
||||
joinedload(Deal.client)
|
||||
)
|
||||
.outerjoin(
|
||||
service_subquery, Deal.id == service_subquery.c.deal_id)
|
||||
price_subquery, Deal.id == price_subquery.c.deal_id)
|
||||
.where(
|
||||
Deal.is_deleted == False,
|
||||
Deal.is_completed == False
|
||||
@@ -177,6 +199,7 @@ class DealService(BaseService):
|
||||
return DealGetAllResponse(deals=result)
|
||||
|
||||
async def get_by_id(self, deal_id: int) -> DealSchema:
|
||||
|
||||
deal = await self.session.scalar(
|
||||
select(Deal)
|
||||
.options(
|
||||
@@ -190,13 +213,17 @@ class DealService(BaseService):
|
||||
selectinload(Deal.products)
|
||||
.joinedload(models.secondary.DealProduct.product)
|
||||
.joinedload(models.Product.barcodes),
|
||||
selectinload(Deal.products)
|
||||
.joinedload(models.secondary.DealProduct.services)
|
||||
.joinedload(models.secondary.DealProductService.service),
|
||||
selectinload(Deal.status_history)
|
||||
.joinedload(DealStatusHistory.user),
|
||||
selectinload(Deal.status_history)
|
||||
.noload(DealStatusHistory.deal)
|
||||
.noload(DealStatusHistory.deal),
|
||||
)
|
||||
.where(Deal.id == deal_id)
|
||||
)
|
||||
|
||||
if not deal:
|
||||
raise HTTPException(status_code=404, detail="Сделка не найдена")
|
||||
return DealSchema.model_validate(deal)
|
||||
@@ -328,7 +355,7 @@ class DealService(BaseService):
|
||||
deal = await self.session.scalar(select(Deal).where(Deal.id == request.deal_id))
|
||||
if not deal:
|
||||
raise HTTPException(status_code=404, detail="Сделка не найдена")
|
||||
service = await self.session.scalar(select(Service).where(Service.id == request.service_id))
|
||||
service: models.Service = await self.session.scalar(select(Service).where(Service.id == request.service_id))
|
||||
if not service:
|
||||
raise HTTPException(status_code=404, detail="Услуга не найдена")
|
||||
# Preventing duplicates
|
||||
@@ -342,7 +369,8 @@ class DealService(BaseService):
|
||||
deal_service = models.secondary.DealService(
|
||||
deal_id=request.deal_id,
|
||||
service_id=request.service_id,
|
||||
quantity=request.quantity
|
||||
quantity=request.quantity,
|
||||
price=request.price
|
||||
)
|
||||
self.session.add(deal_service)
|
||||
await self.session.commit()
|
||||
@@ -382,6 +410,30 @@ class DealService(BaseService):
|
||||
await self.session.rollback()
|
||||
return DealDeleteServicesResponse(ok=False, message=str(e))
|
||||
|
||||
async def update_service(self, request: DealUpdateServiceRequest) -> DealUpdateServiceResponse:
|
||||
try:
|
||||
deal_service = await self.session.scalar(
|
||||
select(models.secondary.DealService)
|
||||
.where(models.secondary.DealService.deal_id == request.deal_id,
|
||||
models.secondary.DealService.service_id == request.service.service.id)
|
||||
)
|
||||
if not deal_service:
|
||||
raise HTTPException(status_code=404, detail="Сделка не найдена")
|
||||
service_dict = request.service.dict()
|
||||
del service_dict['service']
|
||||
service_dict['service_id'] = request.service.service.id
|
||||
await self.session.execute(
|
||||
update(models.secondary.DealService)
|
||||
.where(models.secondary.DealService.deal_id == request.deal_id,
|
||||
models.secondary.DealService.service_id == request.service.service.id)
|
||||
.values(**service_dict)
|
||||
)
|
||||
await self.session.commit()
|
||||
return DealUpdateServiceQuantityResponse(ok=True, message='Количество успешно обновлено')
|
||||
except Exception as e:
|
||||
await self.session.rollback()
|
||||
return DealUpdateServiceQuantityResponse(ok=False, message=str(e))
|
||||
|
||||
# endregion
|
||||
|
||||
# region Deal products
|
||||
@@ -408,23 +460,33 @@ class DealService(BaseService):
|
||||
deal = await self.session.scalar(select(Deal).where(Deal.id == request.deal_id))
|
||||
if not deal:
|
||||
raise HTTPException(status_code=404, detail="Сделка не найдена")
|
||||
product = await self.session.scalar(select(models.Product).where(models.Product.id == request.product_id))
|
||||
product = await self.session.scalar(
|
||||
select(models.Product).where(models.Product.id == request.product.product.id))
|
||||
if not product:
|
||||
raise HTTPException(status_code=404, detail="Товар не найден")
|
||||
# Preventing duplicates
|
||||
deal_product = await self.session.scalar(
|
||||
select(models.secondary.DealProduct)
|
||||
.where(models.secondary.DealProduct.deal_id == request.deal_id,
|
||||
models.secondary.DealProduct.product_id == request.product_id)
|
||||
models.secondary.DealProduct.product_id == request.product.product.id)
|
||||
)
|
||||
if deal_product:
|
||||
raise HTTPException(status_code=400, detail="Товар уже добавлен")
|
||||
deal_product = models.secondary.DealProduct(
|
||||
deal_id=request.deal_id,
|
||||
product_id=request.product_id,
|
||||
quantity=request.quantity
|
||||
product_id=request.product.product.id,
|
||||
quantity=request.product.quantity
|
||||
)
|
||||
self.session.add(deal_product)
|
||||
await self.session.flush()
|
||||
for service in request.product.services:
|
||||
deal_product_service = models.secondary.DealProductService(
|
||||
deal_id=request.deal_id,
|
||||
product_id=request.product.product.id,
|
||||
service_id=service.service.id,
|
||||
price=service.price
|
||||
)
|
||||
self.session.add(deal_product_service)
|
||||
await self.session.commit()
|
||||
return DealAddProductResponse(ok=True, message='Товар успешно добавлен')
|
||||
except Exception as e:
|
||||
@@ -461,4 +523,56 @@ class DealService(BaseService):
|
||||
except Exception as e:
|
||||
await self.session.rollback()
|
||||
return DealDeleteProductsResponse(ok=False, message=str(e))
|
||||
|
||||
async def update_product(self, request: DealUpdateProductRequest):
|
||||
try:
|
||||
deal_product: models.DealProduct = await self.session.scalar(
|
||||
select(models.secondary.DealProduct)
|
||||
.where(models.secondary.DealProduct.deal_id == request.deal_id,
|
||||
models.secondary.DealProduct.product_id == request.product.product.id)
|
||||
)
|
||||
if not deal_product:
|
||||
raise HTTPException(status_code=404, detail="Указанный товар не найден")
|
||||
# getting new services and deleted
|
||||
database_services = set([service.service_id for service in deal_product.services])
|
||||
request_services = set([service.service.id for service in request.product.services])
|
||||
|
||||
new_services = request_services.difference(database_services)
|
||||
deleted_services = database_services.difference(request_services)
|
||||
services_dict = {service.service.id: service for service in request.product.services}
|
||||
|
||||
# Deleting and updating existing services
|
||||
for service in deal_product.services:
|
||||
service: models.DealProductService
|
||||
if service.service_id in deleted_services:
|
||||
await self.session.delete(service)
|
||||
await self.session.flush()
|
||||
continue
|
||||
request_service = services_dict[service.service_id]
|
||||
service.price = request_service.price
|
||||
await self.session.flush()
|
||||
|
||||
# Creating services
|
||||
for service in request.product.services:
|
||||
if service.service.id not in new_services:
|
||||
continue
|
||||
deal_product_service = models.DealProductService(
|
||||
deal_id=request.deal_id,
|
||||
product_id=request.product.product.id,
|
||||
service_id=service.service.id,
|
||||
price=service.price
|
||||
)
|
||||
self.session.add(deal_product_service)
|
||||
await self.session.flush()
|
||||
|
||||
# Updating product
|
||||
deal_product.quantity = request.product.quantity
|
||||
|
||||
await self.session.commit()
|
||||
return DealUpdateProductResponse(ok=True, message='Товар успешно обновлен')
|
||||
|
||||
except Exception as e:
|
||||
await self.session.rollback()
|
||||
return DealUpdateProductResponse(ok=False, message=str(e))
|
||||
|
||||
# endregion
|
||||
|
||||
Reference in New Issue
Block a user