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