feat: services kit and copy
This commit is contained in:
		
							
								
								
									
										171
									
								
								services/deal.py
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								services/deal.py
									
									
									
									
									
								
							@@ -13,6 +13,7 @@ from schemas.client import ClientDetailsSchema
 | 
			
		||||
from schemas.deal import *
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
from services.client import ClientService
 | 
			
		||||
from services.service import ServiceService
 | 
			
		||||
from services.shipping_warehouse import ShippingWarehouseService
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -317,6 +318,48 @@ class DealService(BaseService):
 | 
			
		||||
        await self.session.commit()
 | 
			
		||||
        return await self.get_summary()
 | 
			
		||||
 | 
			
		||||
    async def add_kit_to_deal(self, request: DealAddKitRequest) -> DealAddKitResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            deal = await self._get_deal_by_id(request.deal_id)
 | 
			
		||||
            if not deal:
 | 
			
		||||
                return DealAddKitResponse(ok=False, message="Указанная сделка не найдена")
 | 
			
		||||
            kit = await ServiceService(self.session).get_kit_by_id(request.kit_id)
 | 
			
		||||
            if not kit:
 | 
			
		||||
                return DealAddKitResponse(ok=False, message="Указанный набор услуг не найден")
 | 
			
		||||
            services: list[models.Service] = kit.services
 | 
			
		||||
            insert_data = []
 | 
			
		||||
            for service in services:
 | 
			
		||||
                price = self.get_service_price(service, 1)
 | 
			
		||||
                insert_data.append({
 | 
			
		||||
                    'deal_id': deal.id,
 | 
			
		||||
                    'service_id': service.id,
 | 
			
		||||
                    'quantity': 1,
 | 
			
		||||
                    'price': price
 | 
			
		||||
                })
 | 
			
		||||
            if not insert_data:
 | 
			
		||||
                return DealAddKitResponse(ok=True, message="Набор услуг успешно добавлен к сделке")
 | 
			
		||||
            # Deleting previous services
 | 
			
		||||
            delete_stmt = (
 | 
			
		||||
                delete(
 | 
			
		||||
                    models.DealService
 | 
			
		||||
                )
 | 
			
		||||
                .where(
 | 
			
		||||
                    models.DealService.deal_id == request.deal_id
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.execute(delete_stmt)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
 | 
			
		||||
            await self.session.execute(
 | 
			
		||||
                insert(models.DealService),
 | 
			
		||||
                insert_data
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return DealAddKitResponse(ok=True, message="Набор услуг успешно добавлен к сделке")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            return DealAddKitResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    # endregion
 | 
			
		||||
 | 
			
		||||
    # region Deal services
 | 
			
		||||
@@ -492,6 +535,82 @@ class DealService(BaseService):
 | 
			
		||||
            await self.session.rollback()
 | 
			
		||||
            return DealUpdateServiceQuantityResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def copy_services(self, request: DealServicesCopyRequest) -> DealServicesCopyResponse:
 | 
			
		||||
        try:
 | 
			
		||||
 | 
			
		||||
            source_services_stmt = (
 | 
			
		||||
                select(
 | 
			
		||||
                    models.DealProductService
 | 
			
		||||
                )
 | 
			
		||||
                .where(
 | 
			
		||||
                    models.DealProductService.product_id == request.source_product_id,
 | 
			
		||||
                    models.DealProductService.deal_id == request.deal_id,
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            deal_product_services: list[models.DealProductService] = (
 | 
			
		||||
                await self.session.scalars(source_services_stmt)).all()
 | 
			
		||||
            source_services: list[models.Service] = [dpc.service for dpc in deal_product_services]
 | 
			
		||||
 | 
			
		||||
            destination_deal_products_stmt = (
 | 
			
		||||
                select(
 | 
			
		||||
                    models.DealProduct
 | 
			
		||||
                )
 | 
			
		||||
                .where(
 | 
			
		||||
                    models.DealProduct.product_id.in_(request.destination_product_ids),
 | 
			
		||||
                    models.DealProduct.deal_id == request.deal_id
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            destination_deal_products = (await self.session.scalars(destination_deal_products_stmt)).all()
 | 
			
		||||
            insert_data = []
 | 
			
		||||
            for deal_product in destination_deal_products:
 | 
			
		||||
                for service in source_services:
 | 
			
		||||
                    service_price = self.get_service_price(service, deal_product.quantity)
 | 
			
		||||
                    insert_data.append({
 | 
			
		||||
                        'deal_id': request.deal_id,
 | 
			
		||||
                        'product_id': deal_product.product_id,
 | 
			
		||||
                        'service_id': service.id,
 | 
			
		||||
                        'price': service_price
 | 
			
		||||
                    })
 | 
			
		||||
            if not insert_data:
 | 
			
		||||
                return DealServicesCopyResponse(ok=True, message='Услуги успешно перенесены')
 | 
			
		||||
            # Deleting previous DealProductService-s
 | 
			
		||||
            delete_stmt = (
 | 
			
		||||
                delete(
 | 
			
		||||
                    models.DealProductService
 | 
			
		||||
                )
 | 
			
		||||
                .where(
 | 
			
		||||
                    models.DealProductService.product_id.in_(request.destination_product_ids),
 | 
			
		||||
                    models.DealProductService.deal_id == request.deal_id
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.execute(delete_stmt)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
 | 
			
		||||
            await self.session.execute(
 | 
			
		||||
                insert(models.DealProductService),
 | 
			
		||||
                insert_data
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return DealServicesCopyResponse(ok=True, message='Услуги успешно перенесены')
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            return DealServicesCopyResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_service_price(service: models.Service, quantity: int):
 | 
			
		||||
        price = 0
 | 
			
		||||
        price_ranges: list[models.ServicePriceRange] = service.price_ranges
 | 
			
		||||
        for price_range in price_ranges:
 | 
			
		||||
            if price_range.from_quantity <= quantity <= price_range.to_quantity:
 | 
			
		||||
                price = price_range.price
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        if not price and len(price_ranges) > 0:
 | 
			
		||||
            price = price_ranges[0].price
 | 
			
		||||
        if not price:
 | 
			
		||||
            price = service.price
 | 
			
		||||
        return price
 | 
			
		||||
 | 
			
		||||
    # endregion
 | 
			
		||||
 | 
			
		||||
    # region Deal products
 | 
			
		||||
@@ -662,4 +781,56 @@ class DealService(BaseService):
 | 
			
		||||
            await self.session.rollback()
 | 
			
		||||
            return DealUpdateProductResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def add_kit_to_deal_product(self, request: DealProductAddKitRequest) -> DealProductAddKitResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            service_service = ServiceService(self.session)
 | 
			
		||||
            kit = await service_service.get_kit_by_id(request.kit_id)
 | 
			
		||||
            if not kit:
 | 
			
		||||
                return DealProductAddKitResponse(ok=False, message='Указанный набор услуг не найден')
 | 
			
		||||
            services: list[models.Service] = kit.services
 | 
			
		||||
            deal_product_stmt = (
 | 
			
		||||
                select(
 | 
			
		||||
                    models.DealProduct
 | 
			
		||||
                )
 | 
			
		||||
                .where(
 | 
			
		||||
                    models.DealProduct.deal_id == request.deal_id,
 | 
			
		||||
                    models.DealProduct.product_id == request.product_id
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            deal_product: Optional[models.DealProduct] = await self.session.scalar(deal_product_stmt)
 | 
			
		||||
            if not deal_product:
 | 
			
		||||
                return DealProductAddKitResponse(ok=False, message='Указанный товар не найден')
 | 
			
		||||
            insert_data = []
 | 
			
		||||
            for service in services:
 | 
			
		||||
                service_price = self.get_service_price(service, deal_product.quantity)
 | 
			
		||||
                insert_data.append({
 | 
			
		||||
                    'deal_id': request.deal_id,
 | 
			
		||||
                    'product_id': deal_product.product_id,
 | 
			
		||||
                    'service_id': service.id,
 | 
			
		||||
                    'price': service_price
 | 
			
		||||
                })
 | 
			
		||||
            if not insert_data:
 | 
			
		||||
                return DealProductAddKitResponse(ok=True, message='Набор услуг успешно добавлен к товару')
 | 
			
		||||
            # Deleting previous DealProductService-s
 | 
			
		||||
            delete_stmt = (
 | 
			
		||||
                delete(
 | 
			
		||||
                    models.DealProductService
 | 
			
		||||
                )
 | 
			
		||||
                .where(
 | 
			
		||||
                    models.DealProductService.product_id == deal_product.product_id,
 | 
			
		||||
                    models.DealProductService.deal_id == request.deal_id
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.execute(delete_stmt)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
 | 
			
		||||
            await self.session.execute(
 | 
			
		||||
                insert(models.DealProductService),
 | 
			
		||||
                insert_data
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return DealProductAddKitResponse(ok=True, message='Набор услуг успешно добавлен к товару')
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            return DealProductAddKitResponse(ok=False, message=str(e))
 | 
			
		||||
    # endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,11 @@
 | 
			
		||||
from sqlalchemy import select, update
 | 
			
		||||
from typing import Union
 | 
			
		||||
 | 
			
		||||
from sqlalchemy import select, update, insert, delete
 | 
			
		||||
from sqlalchemy.orm import joinedload
 | 
			
		||||
 | 
			
		||||
from models import Service, ServiceCategory, ServicePriceRange
 | 
			
		||||
from models import Service, ServiceCategory, ServicePriceRange, ServicesKit, services_kit_services
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
from schemas.service import ServiceGetAllResponse, ServiceSchema, ServiceGetAllCategoriesResponse, \
 | 
			
		||||
    ServiceCategorySchema, ServiceCreateRequest, ServiceCreateResponse, ServiceCreateCategoryRequest, \
 | 
			
		||||
    ServiceCreateCategoryResponse, ServiceUpdateRequest, ServiceUpdateResponse, ServiceDeleteResponse, \
 | 
			
		||||
    ServiceDeleteRequest
 | 
			
		||||
from schemas.service import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ServiceService(BaseService):
 | 
			
		||||
@@ -121,3 +120,88 @@ class ServiceService(BaseService):
 | 
			
		||||
        for category in query.all():
 | 
			
		||||
            categories.append(ServiceCategorySchema.model_validate(category))
 | 
			
		||||
        return ServiceGetAllCategoriesResponse(categories=categories)
 | 
			
		||||
 | 
			
		||||
    async def get_kit_by_name(self, name: str) -> Optional[ServicesKit]:
 | 
			
		||||
        return await self.session.scalar(select(ServicesKit).where(ServicesKit.name == name))
 | 
			
		||||
 | 
			
		||||
    async def get_kit_by_id(self, kit_id: int) -> Optional[ServicesKit]:
 | 
			
		||||
        return await self.session.scalar(select(ServicesKit).where(ServicesKit.id == kit_id))
 | 
			
		||||
 | 
			
		||||
    async def get_all_kits(self) -> GetAllServicesKitsResponse:
 | 
			
		||||
        stmt = (
 | 
			
		||||
            select(
 | 
			
		||||
                ServicesKit
 | 
			
		||||
            )
 | 
			
		||||
            .order_by(
 | 
			
		||||
                ServicesKit.id.desc()
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        kits = (await self.session.scalars(stmt)).all()
 | 
			
		||||
        kits_schemas = GetServiceKitSchema.from_orm_list(kits)
 | 
			
		||||
        return GetAllServicesKitsResponse(services_kits=kits_schemas)
 | 
			
		||||
 | 
			
		||||
    async def create_kit(self, request: CreateServicesKitRequest) -> CreateServicesKitResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            if await self.get_kit_by_name(request.data.name):
 | 
			
		||||
                return CreateServicesKitResponse(ok=False, message='Набор услуг с таким названием уже существует')
 | 
			
		||||
            base_fields = request.data.model_dump_parent()
 | 
			
		||||
            kit = ServicesKit(**base_fields)
 | 
			
		||||
            self.session.add(kit)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
            # Appending services
 | 
			
		||||
            insert_data = []
 | 
			
		||||
            for service_id in request.data.services_ids:
 | 
			
		||||
                insert_data.append({
 | 
			
		||||
                    'service_id': service_id,
 | 
			
		||||
                    'services_kit_id': kit.id
 | 
			
		||||
                })
 | 
			
		||||
            if insert_data:
 | 
			
		||||
                await self.session.execute(
 | 
			
		||||
                    insert(services_kit_services),
 | 
			
		||||
                    insert_data
 | 
			
		||||
                )
 | 
			
		||||
                await self.session.flush()
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return CreateServicesKitResponse(ok=True, message='Набор услуг успешно создан')
 | 
			
		||||
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            return CreateServicesKitResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def update_kit(self, request: UpdateServicesKitRequest) -> UpdateServicesKitResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            kit = await self.get_kit_by_id(request.data.id)
 | 
			
		||||
            if not kit:
 | 
			
		||||
                return UpdateServicesKitResponse(ok=False, message='Указанный набор услуг не существует')
 | 
			
		||||
            base_fields = request.data.model_dump_parent()
 | 
			
		||||
            stmt = update(ServicesKit).values(**base_fields).where(ServicesKit.id == request.data.id)
 | 
			
		||||
            await self.session.execute(stmt)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
 | 
			
		||||
            # Deleting previous services
 | 
			
		||||
            stmt = (
 | 
			
		||||
                delete(
 | 
			
		||||
                    services_kit_services
 | 
			
		||||
                ).where(
 | 
			
		||||
                    services_kit_services.c.services_kit_id == kit.id
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.execute(stmt)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
 | 
			
		||||
            insert_data = []
 | 
			
		||||
            for service_id in request.data.services_ids:
 | 
			
		||||
                insert_data.append({
 | 
			
		||||
                    'service_id': service_id,
 | 
			
		||||
                    'services_kit_id': kit.id
 | 
			
		||||
                })
 | 
			
		||||
            if insert_data:
 | 
			
		||||
                await self.session.execute(
 | 
			
		||||
                    insert(services_kit_services),
 | 
			
		||||
                    insert_data
 | 
			
		||||
                )
 | 
			
		||||
                await self.session.flush()
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return UpdateServicesKitResponse(ok=True, message='Набор услуг успешно обновлен')
 | 
			
		||||
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            return UpdateServicesKitResponse(ok=False, message=str(e))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user