from lexorank import lexorank from sqlalchemy import select, insert, update, delete from sqlalchemy.orm import selectinload from models import CardService as DealServiceModel, User, Card, CardProduct, Product, GroupBillRequest from models.card_group import CardGroup, card_relations from schemas.group import * from services.base import BaseService from services.card import CardsService class CardGroupService(BaseService): async def get_cards_by_group_id(self, group_id) -> list[Card]: group: CardGroup | None = await self.session.scalar( select(CardGroup) .where(CardGroup.id == group_id) .options( selectinload(CardGroup.cards).selectinload(Card.products).selectinload(CardProduct.services), selectinload(CardGroup.cards).selectinload(Card.products) .selectinload(CardProduct.product).selectinload(Product.barcodes), selectinload(CardGroup.cards).selectinload(Card.services).selectinload(DealServiceModel.service), selectinload(CardGroup.cards).selectinload(Card.status_history), selectinload(CardGroup.cards).selectinload(Card.group).selectinload(CardGroup.cards), selectinload(CardGroup.cards).joinedload(Card.client), selectinload(CardGroup.cards).joinedload(Card.shipping_warehouse), ) ) return group.cards if group else [] async def create_group_model(self) -> CardGroup: group = CardGroup( 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: CreateCardGroupRequest) -> CardCreateGroupResponse: try: group = await self.create_group_model() for card_id in [request.dragging_card_id, request.hovered_card_id]: insert_stmt = insert(card_relations).values({ 'card_id': card_id, 'group_id': group.id }) await self.session.execute(insert_stmt) # changing status if needed on draggable card dragging_card = await self.session.scalar( select(Card).where(Card.id == request.dragging_card_id) ) dropped_card = await self.session.scalar( select(Card).where(Card.id == request.hovered_card_id) ) if dragging_card.current_status_id != dropped_card.current_status_id: card_service = CardsService(self.session) await card_service.change_status(dragging_card, dropped_card.current_status_id, user) await self.session.commit() return CardCreateGroupResponse(ok=True, message="Группа успешно создана") except Exception as e: return CardCreateGroupResponse(ok=False, message=str(e)) async def update_group(self, request: CardGroupUpdateRequest) -> CardGroupUpdateResponse: try: group = await self.session.scalar( select(CardGroup).where(CardGroup.id == request.data.id) ) if not group: return CardGroupUpdateResponse(ok=False, message="Группа не найдена") update_stmt = ( update(CardGroup) .where(CardGroup.id == request.data.id) .values(name=request.data.name, lexorank=request.data.lexorank) ) await self.session.execute(update_stmt) await self.session.commit() return CardGroupUpdateResponse(ok=True, message="Группа успешно обновлена") except Exception as e: print(e) await self.session.rollback() return CardGroupUpdateResponse(ok=False, message=str(e)) async def complete_group(self, group_id: int) -> list[Card]: cards = await self.get_cards_by_group_id(group_id) for card in cards: card.is_completed = True return cards async def delete_group(self, group_id: int) -> None: cards = await self.get_cards_by_group_id(group_id) for card in cards: card.is_deleted = True await self.session.commit() async def change_group_status( self, user: User, request: CardGroupChangeStatusRequest, ) -> CardGroupChangeStatusResponse: try: # getting all cards in group cards = await self.session.scalars( select(card_relations.c.card_id) .where(card_relations.c.group_id == request.group_id) ) card_service = CardsService(self.session) for card_id in cards: card = await self.session.scalar( select(Card).where(Card.id == card_id) ) await card_service.change_status(card, request.new_status, user) await self.session.commit() return CardGroupChangeStatusResponse(ok=True, message="Статус группы успешно изменен") except Exception as e: await self.session.rollback() return CardGroupChangeStatusResponse(ok=False, message=str(e)) async def add_card(self, user: User, request: CardAddToGroupRequest) -> CardAddToGroupResponse: try: group_bill_request = await self.session.get(GroupBillRequest, request.group_id) if group_bill_request: raise Exception("Нельзя добавить сделку, так как на группу выставлен счёт.") # changing status if needed card_id = await self.session.scalar( select(card_relations.c.card_id) .where(card_relations.c.group_id == request.group_id) ) group_card_status = await self.session.scalar( select(Card.current_status_id) .where(Card.id == card_id) ) request_card = await self.session.scalar( select(Card).where(Card.id == request.card_id) ) if group_card_status != request_card.current_status_id: await CardsService(self.session).change_status(request_card, group_card_status, user) insert_stmt = insert(card_relations).values({ 'card_id': request.card_id, 'group_id': request.group_id }) await self.session.execute(insert_stmt) await self.session.commit() return CardAddToGroupResponse(ok=True, message="Сделка успешно добавлена в группу") except Exception as e: await self.session.rollback() return CardAddToGroupResponse(ok=False, message=str(e)) async def remove_card(self, request: CardRemoveFromGroupRequest) -> CardRemoveFromGroupResponse: try: delete_stmt = ( delete(card_relations) .where( card_relations.c.card_id == request.card_id, ) ) await self.session.execute(delete_stmt) await self.session.commit() return CardRemoveFromGroupResponse(ok=True, message="Сделка успешно удалена из группы") except Exception as e: await self.session.rollback() return CardRemoveFromGroupResponse(ok=False, message=str(e))