feat: total services amount and recalculating
This commit is contained in:
@@ -3,7 +3,10 @@ from sqlalchemy.orm import declarative_base, DeclarativeBase
|
|||||||
|
|
||||||
|
|
||||||
class BaseModel(DeclarativeBase, AsyncAttrs):
|
class BaseModel(DeclarativeBase, AsyncAttrs):
|
||||||
pass
|
def __repr__(self):
|
||||||
|
if hasattr(self, 'id'):
|
||||||
|
return f'<{self.__class__.__name__} id={self.id}>'
|
||||||
|
return super().__repr__()
|
||||||
|
|
||||||
|
|
||||||
metadata = BaseModel.metadata
|
metadata = BaseModel.metadata
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from sqlalchemy import Table, Column, Integer, ForeignKey, ForeignKeyConstraint, UniqueConstraint
|
from sqlalchemy import Table, Column, Integer, ForeignKey, ForeignKeyConstraint, UniqueConstraint
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship, mapped_column, Mapped
|
||||||
|
|
||||||
from models.base import BaseModel
|
from models.base import BaseModel
|
||||||
|
|
||||||
@@ -41,6 +41,7 @@ class DealService(BaseModel):
|
|||||||
|
|
||||||
quantity = Column(Integer, nullable=False, comment='Кол-во услуги')
|
quantity = Column(Integer, nullable=False, comment='Кол-во услуги')
|
||||||
price = Column(Integer, nullable=False, server_default='0', comment='Цена услуги')
|
price = Column(Integer, nullable=False, server_default='0', comment='Цена услуги')
|
||||||
|
is_fixed_price: Mapped[bool] = mapped_column(default=False, server_default='0', comment='Фиксированная цена')
|
||||||
|
|
||||||
employees = relationship('User', secondary=deal_service_employees)
|
employees = relationship('User', secondary=deal_service_employees)
|
||||||
|
|
||||||
@@ -59,6 +60,8 @@ class DealProductService(BaseModel):
|
|||||||
|
|
||||||
price = Column(Integer, nullable=False, comment='Цена услуги')
|
price = Column(Integer, nullable=False, comment='Цена услуги')
|
||||||
|
|
||||||
|
is_fixed_price: Mapped[bool] = mapped_column(default=False, server_default='0', comment='Фиксированная цена')
|
||||||
|
|
||||||
deal_product = relationship('DealProduct',
|
deal_product = relationship('DealProduct',
|
||||||
back_populates='services',
|
back_populates='services',
|
||||||
primaryjoin="and_(DealProductService.deal_id == DealProduct.deal_id, "
|
primaryjoin="and_(DealProductService.deal_id == DealProduct.deal_id, "
|
||||||
@@ -114,4 +117,3 @@ barcode_template_attribute_link = Table(
|
|||||||
Column('barcode_template_id', ForeignKey('barcode_templates.id')),
|
Column('barcode_template_id', ForeignKey('barcode_templates.id')),
|
||||||
Column('attribute_id', ForeignKey('barcode_template_attributes.id'))
|
Column('attribute_id', ForeignKey('barcode_template_attributes.id'))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ async def complete(
|
|||||||
session: SessionDependency,
|
session: SessionDependency,
|
||||||
user: CurrentUserDependency
|
user: CurrentUserDependency
|
||||||
):
|
):
|
||||||
return await DealService(session).complete(user,request)
|
return await DealService(session).complete(user, request)
|
||||||
|
|
||||||
|
|
||||||
@deal_router.post(
|
@deal_router.post(
|
||||||
'/quickCreate',
|
'/quickCreate',
|
||||||
@@ -221,6 +222,18 @@ async def post_prefill_deal(
|
|||||||
return await DealService(session).prefill_deal(user, request)
|
return await DealService(session).prefill_deal(user, request)
|
||||||
|
|
||||||
|
|
||||||
|
@deal_router.post(
|
||||||
|
'/recalculate-price',
|
||||||
|
response_model=DealRecalculatePriceResponse,
|
||||||
|
operation_id='recalculate_deal_price',
|
||||||
|
)
|
||||||
|
async def recalculate_deal_price(
|
||||||
|
session: SessionDependency,
|
||||||
|
request: DealRecalculatePriceRequest,
|
||||||
|
):
|
||||||
|
return await DealService(session).recalculate_price(request)
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Deal services
|
# region Deal services
|
||||||
|
|||||||
@@ -56,12 +56,13 @@ class DealServiceSchema(BaseSchema):
|
|||||||
quantity: int
|
quantity: int
|
||||||
price: int
|
price: int
|
||||||
employees: List[UserSchema]
|
employees: List[UserSchema]
|
||||||
|
is_fixed_price: bool
|
||||||
|
|
||||||
class DealProductServiceSchema(BaseSchema):
|
class DealProductServiceSchema(BaseSchema):
|
||||||
service: ServiceSchema
|
service: ServiceSchema
|
||||||
price: int
|
price: int
|
||||||
employees: List[UserSchema]
|
employees: List[UserSchema]
|
||||||
|
is_fixed_price: bool
|
||||||
|
|
||||||
|
|
||||||
class DealProductSchema(BaseSchema):
|
class DealProductSchema(BaseSchema):
|
||||||
@@ -243,6 +244,10 @@ class DealPrefillRequest(BaseSchema):
|
|||||||
new_deal_id: int
|
new_deal_id: int
|
||||||
|
|
||||||
|
|
||||||
|
class DealRecalculatePriceRequest(BaseSchema):
|
||||||
|
deal_id: int
|
||||||
|
|
||||||
|
|
||||||
# endregion Requests
|
# endregion Requests
|
||||||
|
|
||||||
# region Responses
|
# region Responses
|
||||||
@@ -347,4 +352,7 @@ class DealCompleteResponse(OkMessageSchema):
|
|||||||
class DealPrefillResponse(OkMessageSchema):
|
class DealPrefillResponse(OkMessageSchema):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DealRecalculatePriceResponse(OkMessageSchema):
|
||||||
|
pass
|
||||||
# endregion Responses
|
# endregion Responses
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from starlette import status
|
|||||||
|
|
||||||
import models.deal
|
import models.deal
|
||||||
import models.secondary
|
import models.secondary
|
||||||
from models import User, Service, Client
|
from models import User, Service, Client, DealProductService
|
||||||
from models.deal import *
|
from models.deal import *
|
||||||
from schemas.client import ClientDetailsSchema
|
from schemas.client import ClientDetailsSchema
|
||||||
from schemas.deal import *
|
from schemas.deal import *
|
||||||
@@ -732,7 +732,8 @@ class DealService(BaseService):
|
|||||||
'deal_id': request.deal_id,
|
'deal_id': request.deal_id,
|
||||||
'product_id': deal_product.product_id,
|
'product_id': deal_product.product_id,
|
||||||
'service_id': service.service.id,
|
'service_id': service.service.id,
|
||||||
'price': service.price
|
'price': service.price,
|
||||||
|
'is_fixed_price': service.is_fixed_price
|
||||||
})
|
})
|
||||||
if not insert_data:
|
if not insert_data:
|
||||||
return DealServicesCopyResponse(ok=True, message='Услуги успешно перенесены')
|
return DealServicesCopyResponse(ok=True, message='Услуги успешно перенесены')
|
||||||
@@ -916,6 +917,7 @@ class DealService(BaseService):
|
|||||||
continue
|
continue
|
||||||
request_service = services_dict[service.service_id]
|
request_service = services_dict[service.service_id]
|
||||||
service.price = request_service.price
|
service.price = request_service.price
|
||||||
|
service.is_fixed_price = request_service.is_fixed_price
|
||||||
await self.session.flush()
|
await self.session.flush()
|
||||||
|
|
||||||
# Creating services
|
# Creating services
|
||||||
@@ -1001,7 +1003,7 @@ class DealService(BaseService):
|
|||||||
'deal_id': request.deal_id,
|
'deal_id': request.deal_id,
|
||||||
'product_id': deal_product.product_id,
|
'product_id': deal_product.product_id,
|
||||||
'service_id': service.id,
|
'service_id': service.id,
|
||||||
'price': service_price
|
'price': service_price,
|
||||||
})
|
})
|
||||||
if not insert_data:
|
if not insert_data:
|
||||||
return DealProductAddKitResponse(ok=True, message='Набор услуг успешно добавлен к товару')
|
return DealProductAddKitResponse(ok=True, message='Набор услуг успешно добавлен к товару')
|
||||||
@@ -1029,6 +1031,7 @@ class DealService(BaseService):
|
|||||||
return DealProductAddKitResponse(ok=False, message=str(e))
|
return DealProductAddKitResponse(ok=False, message=str(e))
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
async def complete(self, user: User, request: DealCompleteRequest) -> DealCompleteResponse:
|
async def complete(self, user: User, request: DealCompleteRequest) -> DealCompleteResponse:
|
||||||
try:
|
try:
|
||||||
# check for admin
|
# check for admin
|
||||||
@@ -1044,3 +1047,59 @@ class DealService(BaseService):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
await self.session.rollback()
|
await self.session.rollback()
|
||||||
return DealCompleteResponse(ok=False, message=str(e))
|
return DealCompleteResponse(ok=False, message=str(e))
|
||||||
|
|
||||||
|
async def recalculate_price(self, request: DealRecalculatePriceRequest) -> DealRecalculatePriceResponse:
|
||||||
|
try:
|
||||||
|
deal_stmt = (
|
||||||
|
select(
|
||||||
|
Deal
|
||||||
|
)
|
||||||
|
.options(
|
||||||
|
selectinload(Deal.services)
|
||||||
|
.joinedload(models.DealService.service),
|
||||||
|
selectinload(Deal.products)
|
||||||
|
.selectinload(DealProduct.services)
|
||||||
|
.joinedload(DealProductService.service),
|
||||||
|
)
|
||||||
|
.where(Deal.id == request.deal_id)
|
||||||
|
)
|
||||||
|
deal: Deal = await self.session.scalar(deal_stmt)
|
||||||
|
services_quantity = defaultdict(lambda: 0)
|
||||||
|
for product in deal.products:
|
||||||
|
product: DealProduct
|
||||||
|
for service in product.services:
|
||||||
|
service: DealProductService
|
||||||
|
if service.is_fixed_price:
|
||||||
|
continue
|
||||||
|
services_quantity[service.service_id] += product.quantity
|
||||||
|
|
||||||
|
services_prices = {}
|
||||||
|
for product in deal.products:
|
||||||
|
for service in product.services:
|
||||||
|
if service.is_fixed_price:
|
||||||
|
continue
|
||||||
|
quantity = services_quantity[service.service_id]
|
||||||
|
print(service.service_id, quantity)
|
||||||
|
if service.service_id in services_prices:
|
||||||
|
service.price = services_prices[service.service_id]
|
||||||
|
continue
|
||||||
|
price = self.get_service_price(
|
||||||
|
service=service.service,
|
||||||
|
quantity=quantity
|
||||||
|
)
|
||||||
|
print(service.service_id, price)
|
||||||
|
service.price = price
|
||||||
|
services_prices[service.service_id] = price
|
||||||
|
for service in deal.services:
|
||||||
|
service: models.DealService
|
||||||
|
if service.is_fixed_price:
|
||||||
|
continue
|
||||||
|
price = self.get_service_price(
|
||||||
|
service=service.service,
|
||||||
|
quantity=service.quantity
|
||||||
|
)
|
||||||
|
service.price = price
|
||||||
|
await self.session.commit()
|
||||||
|
return DealRecalculatePriceResponse(ok=True, message="Цены успешно пересчитаны")
|
||||||
|
except Exception as e:
|
||||||
|
return DealRecalculatePriceResponse(ok=False, message=str(e))
|
||||||
|
|||||||
Reference in New Issue
Block a user