feat: deal group
This commit is contained in:
		@@ -12,6 +12,6 @@ from .marketplace import *
 | 
			
		||||
from .payroll import *
 | 
			
		||||
from .billing import *
 | 
			
		||||
from .marketplace_products import *
 | 
			
		||||
# from .deal_group import *
 | 
			
		||||
from .deal_group import *
 | 
			
		||||
 | 
			
		||||
configure_mappers()
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ from .shipping_warehouse import ShippingWarehouse
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from . import (DealBillRequest, ServicePriceCategory,
 | 
			
		||||
                   # DealGroup
 | 
			
		||||
                   DealGroup
 | 
			
		||||
                   )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -91,13 +91,12 @@ class Deal(BaseModel):
 | 
			
		||||
    category: Mapped[Optional["ServicePriceCategory"]] = relationship('ServicePriceCategory',
 | 
			
		||||
                                                                      secondary=DealPriceCategory.__table__,
 | 
			
		||||
                                                                      lazy='joined')
 | 
			
		||||
    # group: Mapped[Optional["DealGroup"]] = relationship(
 | 
			
		||||
    #     'DealGroup',
 | 
			
		||||
    #     secondary='deal_relations',
 | 
			
		||||
    #     lazy='joined',
 | 
			
		||||
    #     uselist=False,
 | 
			
		||||
    #     back_populates='deals'
 | 
			
		||||
    # )
 | 
			
		||||
    group: Mapped[Optional["DealGroup"]] = relationship(
 | 
			
		||||
        'DealGroup',
 | 
			
		||||
        secondary='deal_relations',
 | 
			
		||||
        lazy='joined',
 | 
			
		||||
        back_populates='deals'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealStatusHistory(BaseModel):
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								models/deal_group.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								models/deal_group.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
from typing import TYPE_CHECKING, Optional
 | 
			
		||||
 | 
			
		||||
from sqlalchemy import ForeignKey, Table, Column
 | 
			
		||||
from sqlalchemy.orm import mapped_column, Mapped, relationship
 | 
			
		||||
 | 
			
		||||
from models import BaseModel
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from models import Deal
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealGroup(BaseModel):
 | 
			
		||||
    __tablename__ = 'deal_groups'
 | 
			
		||||
    id: Mapped[int] = mapped_column(
 | 
			
		||||
        primary_key=True
 | 
			
		||||
    )
 | 
			
		||||
    name: Mapped[Optional[str]] = mapped_column(
 | 
			
		||||
        nullable=True
 | 
			
		||||
    )
 | 
			
		||||
    lexorank: Mapped[str] = mapped_column(
 | 
			
		||||
        nullable=False
 | 
			
		||||
    )
 | 
			
		||||
    deals: Mapped["Deal"] = relationship(
 | 
			
		||||
        back_populates='group',
 | 
			
		||||
        secondary='deal_relations'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
deal_relations = Table(
 | 
			
		||||
    'deal_relations',
 | 
			
		||||
    BaseModel.metadata,
 | 
			
		||||
    Column('deal_id', ForeignKey('deals.id'), primary_key=True, unique=True),
 | 
			
		||||
    Column('group_id', ForeignKey('deal_groups.id'), primary_key=True)
 | 
			
		||||
)
 | 
			
		||||
@@ -42,7 +42,7 @@ async def create_deal_bill(
 | 
			
		||||
    operation_id='cancel_deal_bill',
 | 
			
		||||
    response_model=CancelDealBillResponse
 | 
			
		||||
)
 | 
			
		||||
async def create_deal_bill(
 | 
			
		||||
async def cancel_deal_billing(
 | 
			
		||||
        session: SessionDependency,
 | 
			
		||||
        request: CancelDealBillRequest,
 | 
			
		||||
        user: CurrentUserDependency
 | 
			
		||||
 
 | 
			
		||||
@@ -442,4 +442,73 @@ async def get_deal_products_barcodes_pdf(
 | 
			
		||||
        mime_type='application/pdf'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# endregion
 | 
			
		||||
 | 
			
		||||
# region Deal groups
 | 
			
		||||
@deal_router.post(
 | 
			
		||||
    '/add-to-group',
 | 
			
		||||
    response_model=DealAddToGroupResponse,
 | 
			
		||||
    operation_id='add_deal_to_group',
 | 
			
		||||
    dependencies=[Depends(authorized_user)]
 | 
			
		||||
)
 | 
			
		||||
async def add_to_group(
 | 
			
		||||
        request: DealAddToGroupRequest,
 | 
			
		||||
        session: SessionDependency,
 | 
			
		||||
        user: CurrentUserDependency
 | 
			
		||||
):
 | 
			
		||||
    return await DealService(session).add_to_group(user, request)
 | 
			
		||||
 | 
			
		||||
@deal_router.post(
 | 
			
		||||
    '/create-group',
 | 
			
		||||
    response_model=DealCreateGroupResponse,
 | 
			
		||||
    operation_id='create_deal_group',
 | 
			
		||||
    dependencies=[Depends(authorized_user)]
 | 
			
		||||
)
 | 
			
		||||
async def create_group(
 | 
			
		||||
        request: DealCreateGroupRequest,
 | 
			
		||||
        session: SessionDependency,
 | 
			
		||||
        user: CurrentUserDependency
 | 
			
		||||
):
 | 
			
		||||
    return await DealService(session).create_group(user, request)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@deal_router.post(
 | 
			
		||||
    '/remove-from-group',
 | 
			
		||||
    response_model=DealRemoveFromGroupResponse,
 | 
			
		||||
    operation_id='remove_deal_from_group',
 | 
			
		||||
    dependencies=[Depends(authorized_user)]
 | 
			
		||||
)
 | 
			
		||||
async def remove_from_group(
 | 
			
		||||
        request: DealRemoveFromGroupRequest,
 | 
			
		||||
        session: SessionDependency,
 | 
			
		||||
):
 | 
			
		||||
    return await DealService(session).remove_from_group( request)
 | 
			
		||||
 | 
			
		||||
# route to update group name
 | 
			
		||||
@deal_router.post(
 | 
			
		||||
    '/group/update',
 | 
			
		||||
    response_model=DealGroupUpdateResponse,
 | 
			
		||||
    operation_id='update_deal_group',
 | 
			
		||||
    dependencies=[Depends(authorized_user)]
 | 
			
		||||
)
 | 
			
		||||
async def update_group(
 | 
			
		||||
        request: DealGroupUpdateRequest,
 | 
			
		||||
        session: SessionDependency,
 | 
			
		||||
):
 | 
			
		||||
    return await DealService(session).update_group(request)
 | 
			
		||||
 | 
			
		||||
# route to change group status
 | 
			
		||||
@deal_router.post(
 | 
			
		||||
    '/group/change-status',
 | 
			
		||||
    response_model=DealGroupChangeStatusResponse,
 | 
			
		||||
    operation_id='change_deal_group_status',
 | 
			
		||||
    dependencies=[Depends(authorized_user)]
 | 
			
		||||
)
 | 
			
		||||
async def change_group_status(
 | 
			
		||||
        request: DealGroupChangeStatusRequest,
 | 
			
		||||
        session: SessionDependency,
 | 
			
		||||
        user: CurrentUserDependency
 | 
			
		||||
):
 | 
			
		||||
    return await DealService(session).change_group_status(user,request)
 | 
			
		||||
# endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ class DealSummary(BaseSchema):
 | 
			
		||||
    delivery_date: Optional[datetime.datetime] = None
 | 
			
		||||
    receiving_slot_date: Optional[datetime.datetime] = None
 | 
			
		||||
    bill_request: Optional[DealBillRequestSchema] = None
 | 
			
		||||
    # group: Optional[DealGroupSchema] = None
 | 
			
		||||
    group: Optional[DealGroupSchema] = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealServiceSchema(BaseSchema):
 | 
			
		||||
@@ -249,6 +249,29 @@ class DealRecalculatePriceRequest(BaseSchema):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealAddToGroupRequest(BaseSchema):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
    group_id: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealCreateGroupRequest(BaseSchema):
 | 
			
		||||
    dragging_deal_id: int
 | 
			
		||||
    hovered_deal_id: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealRemoveFromGroupRequest(BaseSchema):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealGroupUpdateRequest(BaseSchema):
 | 
			
		||||
    data: DealGroupSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealGroupChangeStatusRequest(BaseSchema):
 | 
			
		||||
    group_id: int
 | 
			
		||||
    new_status: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# endregion Requests
 | 
			
		||||
 | 
			
		||||
# region Responses
 | 
			
		||||
@@ -356,4 +379,25 @@ class DealPrefillResponse(OkMessageSchema):
 | 
			
		||||
 | 
			
		||||
class DealRecalculatePriceResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealAddToGroupResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealCreateGroupResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealRemoveFromGroupResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealGroupUpdateResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealGroupChangeStatusResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
# endregion Responses
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from io import BytesIO
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
@@ -10,11 +11,12 @@ from weasyprint import HTML, CSS
 | 
			
		||||
 | 
			
		||||
import backend.config
 | 
			
		||||
import constants
 | 
			
		||||
import models
 | 
			
		||||
from constants import MONTHS, ENV
 | 
			
		||||
from external.billing import BillingClient, CreateBillingRequestValue, CreateBillRequestSchema, CreateBillRequestItems, \
 | 
			
		||||
    BillStatusUpdateRequest, NotificationChannel, NotifyReceivedBillRequestSchema, DeleteBillRequestSchema, \
 | 
			
		||||
    ProductBillingDocumentPdf, ServiceBillingDocumentPdf
 | 
			
		||||
from models import DealBillRequest, Deal, DealProduct, DealService as DealServiceModel
 | 
			
		||||
from models import DealBillRequest, Deal, DealProduct, DealService as DealServiceModel, DealProductService
 | 
			
		||||
from schemas.billing import *
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
from services.deal import DealService
 | 
			
		||||
@@ -73,25 +75,54 @@ class BillingService(BaseService):
 | 
			
		||||
            deal_service = DealService(self.session)
 | 
			
		||||
            billing_client = BillingClient(backend.config.BILLING_API_KEY)
 | 
			
		||||
 | 
			
		||||
            deal: Deal = await deal_service.get_by_id(user, request.deal_id)
 | 
			
		||||
            basic_deal: Deal = await deal_service.get_by_id(user, request.deal_id, return_raw=True)
 | 
			
		||||
            deals = await deal_service.get_deals_grouped(basic_deal)
 | 
			
		||||
 | 
			
		||||
            billing_request_values: List[CreateBillingRequestValue] = []
 | 
			
		||||
 | 
			
		||||
            psq = defaultdict(lambda: defaultdict(lambda: 0))
 | 
			
		||||
            sq = defaultdict(lambda: 0)
 | 
			
		||||
 | 
			
		||||
            services_dict = {}
 | 
			
		||||
            products_dict = {}
 | 
			
		||||
            for deal in deals:
 | 
			
		||||
                for product in deal.products:
 | 
			
		||||
                    product: DealProduct
 | 
			
		||||
                    for service in product.services:
 | 
			
		||||
                    billing_request_values.append(
 | 
			
		||||
                        CreateBillingRequestValue(
 | 
			
		||||
                            name=f'[{product.product.name}] - {service.service.name}',
 | 
			
		||||
                            price=service.price,
 | 
			
		||||
                            amount=product.quantity
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                        service: DealProductService
 | 
			
		||||
                        psq[product.product_id][service.service_id] += product.quantity
 | 
			
		||||
                        products_dict[product.product_id] = product.product
 | 
			
		||||
                        services_dict[service.service_id] = service.service
 | 
			
		||||
 | 
			
		||||
            for deal in deals:
 | 
			
		||||
                for service in deal.services:
 | 
			
		||||
                    service: models.DealService
 | 
			
		||||
                    services_dict[service.service_id] = service.service
 | 
			
		||||
                    sq[service.service_id] += service.quantity
 | 
			
		||||
 | 
			
		||||
            for product_id, services_ids in psq.items():
 | 
			
		||||
                product: models.Product = products_dict[product_id]
 | 
			
		||||
                for service_id in services_ids:
 | 
			
		||||
                    service = services_dict[service_id]
 | 
			
		||||
                    service: models.Service
 | 
			
		||||
                    quantity = psq[product_id][service_id]
 | 
			
		||||
                    billing_request_values.append(
 | 
			
		||||
                        CreateBillingRequestValue(
 | 
			
		||||
                        name=f'{service.service.name}',
 | 
			
		||||
                            name=f'[{product.name}] - {service.name}',
 | 
			
		||||
                            price=service.price,
 | 
			
		||||
                        amount=service.quantity
 | 
			
		||||
                            amount=quantity
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
            for service_id, quantity in sq.items():
 | 
			
		||||
                service: models.Service = services_dict[service_id]
 | 
			
		||||
                billing_request_values.append(
 | 
			
		||||
                    CreateBillingRequestValue(
 | 
			
		||||
                        name=f'{service.name}',
 | 
			
		||||
                        price=service.price,
 | 
			
		||||
                        amount=quantity
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            deal = basic_deal
 | 
			
		||||
            create_bill_request = CreateBillRequestSchema(
 | 
			
		||||
                listener_transaction_id=deal.id,
 | 
			
		||||
                payer_name=deal.client.name,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										240
									
								
								services/deal.py
									
									
									
									
									
								
							
							
						
						
									
										240
									
								
								services/deal.py
									
									
									
									
									
								
							@@ -1,4 +1,5 @@
 | 
			
		||||
import lexorank
 | 
			
		||||
from attr import dataclass
 | 
			
		||||
from fastapi import HTTPException
 | 
			
		||||
from sqlalchemy import select, func, update, delete, insert
 | 
			
		||||
from sqlalchemy.orm import joinedload, selectinload
 | 
			
		||||
@@ -6,7 +7,7 @@ from starlette import status
 | 
			
		||||
 | 
			
		||||
import models.deal
 | 
			
		||||
import models.secondary
 | 
			
		||||
from models import User, Service, Client, DealProductService
 | 
			
		||||
from models import User, Service, Client, DealProductService, deal_relations
 | 
			
		||||
from models.deal import *
 | 
			
		||||
from schemas.client import ClientDetailsSchema
 | 
			
		||||
from schemas.deal import *
 | 
			
		||||
@@ -248,7 +249,7 @@ class DealService(BaseService):
 | 
			
		||||
                    delivery_date=deal.delivery_date,
 | 
			
		||||
                    receiving_slot_date=deal.receiving_slot_date,
 | 
			
		||||
                    bill_request=deal.bill_request,
 | 
			
		||||
                    # group=deal.group
 | 
			
		||||
                    group=deal.group
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
        return DealSummaryResponse(summaries=summaries)
 | 
			
		||||
@@ -1048,6 +1049,66 @@ class DealService(BaseService):
 | 
			
		||||
            await self.session.rollback()
 | 
			
		||||
            return DealCompleteResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def get_quantity_dict(self, deals: List[models.Deal]):
 | 
			
		||||
        services_quantity = defaultdict(lambda: 0)
 | 
			
		||||
        for deal in deals:
 | 
			
		||||
            for product in deal.products:
 | 
			
		||||
                product: DealProduct
 | 
			
		||||
                for service in product.services:
 | 
			
		||||
                    service: DealProductService
 | 
			
		||||
                    services_quantity[service.service_id] += product.quantity
 | 
			
		||||
            for service in deal.services:
 | 
			
		||||
                service: models.DealService
 | 
			
		||||
                services_quantity[service.service_id] += service.quantity
 | 
			
		||||
        return services_quantity
 | 
			
		||||
 | 
			
		||||
    async def _recalculate_price_single(self, deal: models.Deal, quantity_dict: dict):
 | 
			
		||||
        services_quantity = quantity_dict
 | 
			
		||||
        services_prices = {}
 | 
			
		||||
        for product in deal.products:
 | 
			
		||||
            for service in product.services:
 | 
			
		||||
                if service.is_fixed_price:
 | 
			
		||||
                    continue
 | 
			
		||||
                quantity = services_quantity[service.service_id]
 | 
			
		||||
                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
 | 
			
		||||
                )
 | 
			
		||||
                service.price = price
 | 
			
		||||
                services_prices[service.service_id] = price
 | 
			
		||||
        for service in deal.services:
 | 
			
		||||
            service: models.DealService
 | 
			
		||||
            if service.is_fixed_price:
 | 
			
		||||
                continue
 | 
			
		||||
            quantity = services_quantity[service.service_id]
 | 
			
		||||
            price = self.get_service_price(
 | 
			
		||||
                service=service.service,
 | 
			
		||||
                quantity=quantity
 | 
			
		||||
            )
 | 
			
		||||
            print(service.service_id, price)
 | 
			
		||||
            service.price = price
 | 
			
		||||
 | 
			
		||||
    async def _recalculate_price_group(self, group: models.DealGroup):
 | 
			
		||||
        deals = await self.session.scalars(
 | 
			
		||||
            select(Deal)
 | 
			
		||||
            .options(
 | 
			
		||||
                selectinload(Deal.services)
 | 
			
		||||
                .joinedload(models.DealService.service),
 | 
			
		||||
                selectinload(Deal.products)
 | 
			
		||||
                .selectinload(DealProduct.services)
 | 
			
		||||
                .joinedload(DealProductService.service),
 | 
			
		||||
            )
 | 
			
		||||
            .where(Deal.group == group)
 | 
			
		||||
        )
 | 
			
		||||
        deals = list(deals.all())
 | 
			
		||||
        services_quantity = await self.get_quantity_dict(deals)
 | 
			
		||||
        for deal in deals:
 | 
			
		||||
            await self._recalculate_price_single(deal, services_quantity)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    async def recalculate_price(self, request: DealRecalculatePriceRequest) -> DealRecalculatePriceResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            deal_stmt = (
 | 
			
		||||
@@ -1060,46 +1121,151 @@ class DealService(BaseService):
 | 
			
		||||
                    selectinload(Deal.products)
 | 
			
		||||
                    .selectinload(DealProduct.services)
 | 
			
		||||
                    .joinedload(DealProductService.service),
 | 
			
		||||
                    joinedload(Deal.group)
 | 
			
		||||
                )
 | 
			
		||||
                .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
 | 
			
		||||
            if not deal.group:
 | 
			
		||||
                quantity_dict = await self.get_quantity_dict([deal])
 | 
			
		||||
                await self._recalculate_price_single(deal, quantity_dict)
 | 
			
		||||
            else:
 | 
			
		||||
                await self._recalculate_price_group(deal.group)
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return DealRecalculatePriceResponse(ok=True, message="Цены успешно пересчитаны")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            return DealRecalculatePriceResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def add_to_group(self, user: User, request: DealAddToGroupRequest) -> DealAddToGroupResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            # changing status if needed
 | 
			
		||||
            deal_id = await self.session.scalar(
 | 
			
		||||
                select(deal_relations.c.deal_id)
 | 
			
		||||
                .where(deal_relations.c.group_id == request.group_id)
 | 
			
		||||
            )
 | 
			
		||||
            group_deal_status = await self.session.scalar(
 | 
			
		||||
                select(Deal.current_status)
 | 
			
		||||
                .where(Deal.id == deal_id)
 | 
			
		||||
            )
 | 
			
		||||
            request_deal = await self.session.scalar(
 | 
			
		||||
                select(Deal).where(Deal.id == request.deal_id)
 | 
			
		||||
            )
 | 
			
		||||
            if group_deal_status != request_deal.current_status:
 | 
			
		||||
                await self.change_status(request_deal, group_deal_status, user)
 | 
			
		||||
            insert_stmt = insert(deal_relations).values({
 | 
			
		||||
                'deal_id': request.deal_id,
 | 
			
		||||
                'group_id': request.group_id
 | 
			
		||||
            })
 | 
			
		||||
            await self.session.execute(insert_stmt)
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
 | 
			
		||||
            return DealAddToGroupResponse(ok=True, message="Сделка успешно добавлена в группу")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            await self.session.rollback()
 | 
			
		||||
            return DealAddToGroupResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def create_group(self, user: User, request: DealCreateGroupRequest) -> DealCreateGroupResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            # getting lexorank for grop
 | 
			
		||||
 | 
			
		||||
            group = models.DealGroup(
 | 
			
		||||
                name='',
 | 
			
		||||
                lexorank=lexorank.middle(lexorank.Bucket.BUCEKT_0).__str__(),
 | 
			
		||||
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            self.session.add(group)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
            for deal_id in [request.dragging_deal_id, request.hovered_deal_id]:
 | 
			
		||||
                insert_stmt = insert(deal_relations).values({
 | 
			
		||||
                    'deal_id': deal_id,
 | 
			
		||||
                    'group_id': group.id
 | 
			
		||||
                })
 | 
			
		||||
                await self.session.execute(insert_stmt)
 | 
			
		||||
            # changing status if needed on draggable deal
 | 
			
		||||
            dragging_deal = await self.session.scalar(
 | 
			
		||||
                select(Deal).where(Deal.id == request.dragging_deal_id)
 | 
			
		||||
            )
 | 
			
		||||
            dropped_deal = await self.session.scalar(
 | 
			
		||||
                select(Deal).where(Deal.id == request.hovered_deal_id)
 | 
			
		||||
            )
 | 
			
		||||
            if dragging_deal.current_status != dropped_deal.current_status:
 | 
			
		||||
                await self.change_status(dragging_deal, DealStatus(dropped_deal.current_status), user)
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return DealCreateGroupResponse(ok=True, message="Группа успешно создана")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            return DealCreateGroupResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def remove_from_group(self, request: DealRemoveFromGroupRequest) -> DealRemoveFromGroupResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            delete_stmt = (
 | 
			
		||||
                delete(deal_relations)
 | 
			
		||||
                .where(
 | 
			
		||||
                    deal_relations.c.deal_id == request.deal_id,
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.execute(delete_stmt)
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return DealRemoveFromGroupResponse(ok=True, message="Сделка успешно удалена из группы")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            await self.session.rollback()
 | 
			
		||||
            return DealRemoveFromGroupResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def update_group(self, request: DealGroupUpdateRequest) -> DealGroupUpdateResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            group = await self.session.scalar(
 | 
			
		||||
                select(models.DealGroup).where(models.DealGroup.id == request.data.id)
 | 
			
		||||
            )
 | 
			
		||||
            if not group:
 | 
			
		||||
                return DealGroupUpdateResponse(ok=False, message="Группа не найдена")
 | 
			
		||||
            # update by dictionary
 | 
			
		||||
            request_dict = request.data.dict()
 | 
			
		||||
            update_stmt = (
 | 
			
		||||
                update(
 | 
			
		||||
                    models.DealGroup
 | 
			
		||||
                )
 | 
			
		||||
                .where(models.DealGroup.id == request.data.id)
 | 
			
		||||
                .values(**request_dict)
 | 
			
		||||
            )
 | 
			
		||||
            await self.session.execute(update_stmt)
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return DealGroupUpdateResponse(ok=True, message="Группа успешно обновлена")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            await self.session.rollback()
 | 
			
		||||
            return DealGroupUpdateResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def change_group_status(self, user: User,
 | 
			
		||||
                                  request: DealGroupChangeStatusRequest) -> DealGroupChangeStatusResponse:
 | 
			
		||||
        try:
 | 
			
		||||
            # getting all deals in group
 | 
			
		||||
            deals = await self.session.scalars(
 | 
			
		||||
                select(deal_relations.c.deal_id)
 | 
			
		||||
                .where(deal_relations.c.group_id == request.group_id)
 | 
			
		||||
            )
 | 
			
		||||
            for deal_id in deals:
 | 
			
		||||
                deal = await self.session.scalar(
 | 
			
		||||
                    select(Deal).where(Deal.id == deal_id)
 | 
			
		||||
                )
 | 
			
		||||
                await self.change_status(deal, DealStatus(request.new_status), user)
 | 
			
		||||
            await self.session.commit()
 | 
			
		||||
            return DealGroupChangeStatusResponse(ok=True, message="Статус группы успешно изменен")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            await self.session.rollback()
 | 
			
		||||
            return DealGroupChangeStatusResponse(ok=False, message=str(e))
 | 
			
		||||
 | 
			
		||||
    async def get_deals_grouped(self, deal:models.Deal)->List[models.Deal]:
 | 
			
		||||
        if not deal.group:
 | 
			
		||||
            return [deal]
 | 
			
		||||
        deals = await self.session.scalars(
 | 
			
		||||
            select(Deal)
 | 
			
		||||
            .options(
 | 
			
		||||
                selectinload(Deal.services)
 | 
			
		||||
                .joinedload(models.DealService.service),
 | 
			
		||||
                selectinload(Deal.products)
 | 
			
		||||
                .selectinload(DealProduct.services)
 | 
			
		||||
                .joinedload(DealProductService.service),
 | 
			
		||||
            )
 | 
			
		||||
            .where(Deal.group == deal.group)
 | 
			
		||||
        )
 | 
			
		||||
        deals = list(deals.all())
 | 
			
		||||
        return deals
 | 
			
		||||
		Reference in New Issue
	
	Block a user