from lexorank import lexorank from sqlalchemy import select, insert, update, delete from sqlalchemy.orm import selectinload from models import DealService as DealServiceModel, User, Deal, DealProduct, Product, GroupBillRequest from models.deal_group import DealGroup, deal_relations from schemas.group import * from services.base import BaseService from services.deal import DealService class DealGroupService(BaseService): async def get_deals_by_group_id(self, group_id) -> list[Deal]: group: DealGroup | None = await self.session.scalar( select(DealGroup) .where(DealGroup.id == group_id) .options( selectinload(DealGroup.deals).selectinload(Deal.products).selectinload(DealProduct.services), selectinload(DealGroup.deals).selectinload(Deal.products) .selectinload(DealProduct.product).selectinload(Product.barcodes), selectinload(DealGroup.deals).selectinload(Deal.services).selectinload(DealServiceModel.service), selectinload(DealGroup.deals).selectinload(Deal.status_history), selectinload(DealGroup.deals).selectinload(Deal.group).selectinload(DealGroup.deals), selectinload(DealGroup.deals).joinedload(Deal.client), selectinload(DealGroup.deals).joinedload(Deal.shipping_warehouse), ) ) return group.deals if group else [] async def create_group_model(self) -> DealGroup: group = DealGroup( name='', lexorank=lexorank.middle(lexorank.Bucket.BUCEKT_0).__str__(), ) self.session.add(group) await self.session.flush() return group async def create_group(self, user: User, request: DealCreateGroupRequest) -> DealCreateGroupResponse: try: group = await self.create_group_model() 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_id != dropped_deal.current_status_id: deal_service = DealService(self.session) await deal_service.change_status(dragging_deal, dropped_deal.current_status_id, user) await self.session.commit() return DealCreateGroupResponse(ok=True, message="Группа успешно создана") except Exception as e: return DealCreateGroupResponse(ok=False, message=str(e)) async def update_group(self, request: DealGroupUpdateRequest) -> DealGroupUpdateResponse: try: group = await self.session.scalar( select(DealGroup).where(DealGroup.id == request.data.id) ) if not group: return DealGroupUpdateResponse(ok=False, message="Группа не найдена") # update by dictionary request_dict = request.data.model_dump() request_dict.pop("bill_request", None) update_stmt = ( update(DealGroup) .where(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 complete_group(self, group_id: int) -> list[Deal]: deals = await self.get_deals_by_group_id(group_id) for deal in deals: deal.is_completed = True return deals async def delete_group(self, group_id: int) -> None: deals = await self.get_deals_by_group_id(group_id) for deal in deals: deal.is_deleted = True await self.session.commit() 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) ) deal_service = DealService(self.session) for deal_id in deals: deal = await self.session.scalar( select(Deal).where(Deal.id == deal_id) ) await deal_service.change_status(deal, 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 add_deal(self, user: User, request: DealAddToGroupRequest) -> DealAddToGroupResponse: try: group_bill_request = await self.session.get(GroupBillRequest, request.group_id) if group_bill_request: raise Exception("Нельзя добавить сделку, так как на группу выставлен счёт.") # 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_id) .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_id: await DealService(self.session).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 remove_deal(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))