feat: deal product services
This commit is contained in:
		@@ -33,7 +33,6 @@ class Deal(BaseModel):
 | 
			
		||||
    is_completed = Column(Boolean, nullable=False, server_default='0', default=False, comment='Завершена')
 | 
			
		||||
 | 
			
		||||
    services = relationship('DealService', back_populates='deal', cascade="all, delete-orphan")
 | 
			
		||||
    # product_services = relationship('DealProductService', back_populates='deal', cascade="all, delete-orphan")
 | 
			
		||||
 | 
			
		||||
    products = relationship('DealProduct', back_populates='deal', cascade="all, delete-orphan")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,11 +21,20 @@ class DealService(BaseModel):
 | 
			
		||||
 | 
			
		||||
class DealProductService(BaseModel):
 | 
			
		||||
    __tablename__ = 'deal_product_services'
 | 
			
		||||
    deal_id = Column(Integer, nullable=False, primary_key=True, comment='ID Сделки')
 | 
			
		||||
    product_id = Column(Integer, nullable=False, primary_key=True, comment='ID Продукта')
 | 
			
		||||
    service_id = Column(Integer, ForeignKey('services.id'), nullable=False, comment='ID Услуги')
 | 
			
		||||
    deal_id = Column(Integer, primary_key=True, nullable=False, comment='ID Сделки')
 | 
			
		||||
    product_id = Column(Integer, primary_key=True, nullable=False, comment='ID Продукта')
 | 
			
		||||
    service_id = Column(Integer, ForeignKey('services.id'), primary_key=True, nullable=False, comment='ID Услуги')
 | 
			
		||||
    price = Column(Integer, nullable=False, comment='Цена услуги')
 | 
			
		||||
 | 
			
		||||
    deal_product = relationship('DealProduct',
 | 
			
		||||
                                back_populates='services',
 | 
			
		||||
                                primaryjoin="and_(DealProductService.deal_id == DealProduct.deal_id, "
 | 
			
		||||
                                            "DealProductService.product_id == DealProduct.product_id)",
 | 
			
		||||
                                foreign_keys=[deal_id, product_id])
 | 
			
		||||
    service = relationship('Service',
 | 
			
		||||
                           foreign_keys=[service_id],
 | 
			
		||||
                           lazy='joined')
 | 
			
		||||
 | 
			
		||||
    __table_args__ = (
 | 
			
		||||
        ForeignKeyConstraint(
 | 
			
		||||
            ['deal_id', 'product_id'],
 | 
			
		||||
@@ -33,21 +42,28 @@ class DealProductService(BaseModel):
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    deal_product = relationship('DealProduct', back_populates='services')
 | 
			
		||||
    service = relationship('Service', lazy='joined')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealProduct(BaseModel):
 | 
			
		||||
    __tablename__ = 'deal_products'
 | 
			
		||||
    deal_id = Column(Integer, ForeignKey('deals.id'), nullable=False, comment='ID Сделки', primary_key=True)
 | 
			
		||||
    product_id = Column(Integer, ForeignKey('products.id'), nullable=False, comment='ID Продукта', primary_key=True)
 | 
			
		||||
    deal_id = Column(Integer, ForeignKey('deals.id'), primary_key=True, nullable=False, comment='ID Сделки')
 | 
			
		||||
    product_id = Column(Integer, ForeignKey('products.id'), primary_key=True, nullable=False, comment='ID Продукта')
 | 
			
		||||
    quantity = Column(Integer, nullable=False, comment='Кол-во продукта')
 | 
			
		||||
 | 
			
		||||
    deal = relationship('Deal', back_populates='products')
 | 
			
		||||
    product = relationship('Product')
 | 
			
		||||
    deal = relationship('Deal',
 | 
			
		||||
                        back_populates='products',
 | 
			
		||||
                        foreign_keys=[deal_id])
 | 
			
		||||
    product = relationship('Product',
 | 
			
		||||
                           lazy='joined',
 | 
			
		||||
                           foreign_keys=[product_id])
 | 
			
		||||
 | 
			
		||||
    services = relationship('DealProductService', back_populates='deal_product', lazy='joined',
 | 
			
		||||
                            cascade="all, delete-orphan")
 | 
			
		||||
    services = relationship('DealProductService',
 | 
			
		||||
                            back_populates='deal_product',
 | 
			
		||||
                            cascade="all, delete-orphan",
 | 
			
		||||
                            primaryjoin="and_(DealProductService.deal_id == DealProduct.deal_id, "
 | 
			
		||||
                                        "DealProductService.product_id == DealProduct.product_id)",
 | 
			
		||||
                            foreign_keys=[DealProductService.deal_id, DealProductService.product_id],
 | 
			
		||||
                            lazy='joined'
 | 
			
		||||
                            )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
barcode_template_attribute_link = Table(
 | 
			
		||||
 
 | 
			
		||||
@@ -145,13 +145,25 @@ async def services_add(
 | 
			
		||||
    response_model=DealUpdateServiceQuantityResponse,
 | 
			
		||||
    operation_id='updateDealServiceQuantity'
 | 
			
		||||
)
 | 
			
		||||
async def services_update(
 | 
			
		||||
async def services_update_quantity(
 | 
			
		||||
        request: DealUpdateServiceQuantityRequest,
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
			
		||||
):
 | 
			
		||||
    return await DealService(session).update_service_quantity(request)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@deal_router.post(
 | 
			
		||||
    '/services/update',
 | 
			
		||||
    response_model=DealUpdateServiceResponse,
 | 
			
		||||
    operation_id='updateDealService'
 | 
			
		||||
)
 | 
			
		||||
async def services_update(
 | 
			
		||||
        request: DealUpdateServiceRequest,
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
			
		||||
):
 | 
			
		||||
    return await DealService(session).update_service(request)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@deal_router.post(
 | 
			
		||||
    '/services/delete',
 | 
			
		||||
    response_model=DealDeleteServiceResponse,
 | 
			
		||||
@@ -218,4 +230,15 @@ async def products_delete(
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)]):
 | 
			
		||||
    return await DealService(session).delete_products(request)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@deal_router.post(
 | 
			
		||||
    '/product/update',
 | 
			
		||||
    response_model=DealUpdateProductResponse,
 | 
			
		||||
    operation_id='updateDealProduct'
 | 
			
		||||
)
 | 
			
		||||
async def products_update(
 | 
			
		||||
        request: DealUpdateProductRequest,
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
			
		||||
):
 | 
			
		||||
    return await DealService(session).update_product(request)
 | 
			
		||||
# endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -109,10 +109,16 @@ class DealUpdateServiceQuantityRequest(CustomModelCamel):
 | 
			
		||||
    quantity: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealUpdateServiceRequest(CustomModelCamel):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
    service: DealServiceSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealAddServiceRequest(CustomModelCamel):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
    service_id: int
 | 
			
		||||
    quantity: int
 | 
			
		||||
    price: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealDeleteServiceRequest(CustomModelCamel):
 | 
			
		||||
@@ -163,6 +169,11 @@ class DealDeleteRequest(CustomModelCamel):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealUpdateProductRequest(CustomModelCamel):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
    product: DealProductSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# endregion Requests
 | 
			
		||||
 | 
			
		||||
# region Responses
 | 
			
		||||
@@ -204,6 +215,10 @@ class DealUpdateServiceQuantityResponse(CustomModelCamel):
 | 
			
		||||
    message: str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealUpdateServiceResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealAddServiceResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
@@ -234,4 +249,8 @@ class DealSummaryReorderResponse(OkMessageSchema):
 | 
			
		||||
 | 
			
		||||
class DealDeleteResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealUpdateProductResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
# endregion Responses
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								test/test.py
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								test/test.py
									
									
									
									
									
								
							@@ -1,14 +1,46 @@
 | 
			
		||||
import asyncio
 | 
			
		||||
 | 
			
		||||
from sqlalchemy import select, func, union
 | 
			
		||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
			
		||||
from sqlalchemy.orm import joinedload
 | 
			
		||||
 | 
			
		||||
from backend.session import session_maker
 | 
			
		||||
from migrations.env import run_async_migrations
 | 
			
		||||
from models import Product, ProductBarcode
 | 
			
		||||
from models import Deal, DealProduct, Service
 | 
			
		||||
 | 
			
		||||
import models
 | 
			
		||||
import models.secondary
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def main(session: AsyncSession):
 | 
			
		||||
    await run_async_migrations()
 | 
			
		||||
    deal_services_subquery = (
 | 
			
		||||
        select(
 | 
			
		||||
            models.secondary.DealService.deal_id,
 | 
			
		||||
            func.sum(models.secondary.DealService.quantity * Service.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_sum')
 | 
			
		||||
        )
 | 
			
		||||
        .group_by(union_subqueries.c.deal_id)
 | 
			
		||||
        .subquery()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    print(final_subquery)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def preload():
 | 
			
		||||
    async with session_maker() as session:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user