120 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from datetime import datetime
 | 
						||
from typing import Optional
 | 
						||
 | 
						||
from sqlalchemy import select, and_, func
 | 
						||
 | 
						||
from models import Board, Deal
 | 
						||
from schemas.board import *
 | 
						||
from services.base import BaseService
 | 
						||
 | 
						||
 | 
						||
class BoardService(BaseService):
 | 
						||
    async def _get_boards_for_project(self, project_id: int) -> list[Board]:
 | 
						||
        stmt = (
 | 
						||
            select(Board)
 | 
						||
            .where(
 | 
						||
                and_(
 | 
						||
                    Board.is_deleted == False,
 | 
						||
                    Board.project_id == project_id,
 | 
						||
                )
 | 
						||
            )
 | 
						||
            .order_by(Board.ordinal_number)
 | 
						||
        )
 | 
						||
        boards = (await self.session.scalars(stmt)).all()
 | 
						||
        return list(boards)
 | 
						||
 | 
						||
    async def get_boards(self, project_id: int) -> GetBoardsResponse:
 | 
						||
        boards = await self._get_boards_for_project(project_id)
 | 
						||
        return GetBoardsResponse(boards=boards)
 | 
						||
 | 
						||
    async def create_board(self, request: CreateBoardRequest) -> CreateBoardResponse:
 | 
						||
        boards = await self._get_boards_for_project(request.board.project_id)
 | 
						||
        if len(boards) == 0:
 | 
						||
            ordinal_number = 1
 | 
						||
        else:
 | 
						||
            ordinal_number = boards[-1].ordinal_number + 1
 | 
						||
 | 
						||
        board = Board(
 | 
						||
            **request.board.model_dump(),
 | 
						||
            created_at=datetime.now(),
 | 
						||
            ordinal_number=ordinal_number,
 | 
						||
        )
 | 
						||
        self.session.add(board)
 | 
						||
        await self.session.commit()
 | 
						||
 | 
						||
        return CreateBoardResponse(ok=True, message="Доска успешно создана")
 | 
						||
 | 
						||
    async def _get_board_by_id(self, board_id: int) -> Optional[Board]:
 | 
						||
        return await self.session.get(Board, board_id)
 | 
						||
 | 
						||
    async def update_board(self, request: UpdateBoardRequest) -> UpdateBoardResponse:
 | 
						||
        board = await self._get_board_by_id(request.board.id)
 | 
						||
        if not board:
 | 
						||
            return UpdateBoardResponse(ok=False, message=f"Доска с ID {request.board.id} не найдена")
 | 
						||
 | 
						||
        board.name = request.board.name
 | 
						||
        await self.session.commit()
 | 
						||
        return UpdateBoardResponse(ok=True, message="Доска успешно обновлена")
 | 
						||
 | 
						||
    async def update_board_order(self, request: UpdateBoardOrderRequest) -> UpdateBoardOrderResponse:
 | 
						||
        boards = await self._get_boards_for_project(request.project_id)
 | 
						||
        board_idx = 0
 | 
						||
        while board_idx < len(boards) and boards[board_idx].id != request.board_id:
 | 
						||
            board_idx += 1
 | 
						||
        if board_idx == len(boards):
 | 
						||
            return UpdateBoardOrderResponse(ok=False, message=f"Доска с ID {request.board_id} не найдена в проекте")
 | 
						||
 | 
						||
        board = boards.pop(board_idx)
 | 
						||
        boards.insert(request.new_ordinal_number - 1, board)
 | 
						||
        new_ordinal_number = 1
 | 
						||
        for board in boards:
 | 
						||
            board.ordinal_number = new_ordinal_number
 | 
						||
            new_ordinal_number += 1
 | 
						||
 | 
						||
        await self.session.commit()
 | 
						||
        return UpdateBoardOrderResponse(ok=True, message="Порядок досок изменен")
 | 
						||
 | 
						||
    async def _count_deals_in_progress(self, board_id: int) -> int:
 | 
						||
        stmt = (
 | 
						||
            select(func.count(Deal.id))
 | 
						||
            .where(
 | 
						||
                and_(
 | 
						||
                    Deal.board_id == board_id,
 | 
						||
                    Deal.is_deleted == False,
 | 
						||
                    Deal.is_completed == False,
 | 
						||
                )
 | 
						||
            )
 | 
						||
        )
 | 
						||
        return (await self.session.scalars(stmt)).first()
 | 
						||
 | 
						||
    async def _count_deals(self, board_id: int) -> int:
 | 
						||
        stmt = (
 | 
						||
            select(func.count(Deal.id))
 | 
						||
            .where(Deal.board_id == board_id)
 | 
						||
        )
 | 
						||
        return (await self.session.scalars(stmt)).first()
 | 
						||
 | 
						||
    async def delete_board(self, board_id: int) -> DeleteBoardResponse:
 | 
						||
        board = await self._get_board_by_id(board_id)
 | 
						||
        if not board:
 | 
						||
            return DeleteBoardResponse(ok=False, message=f"Доска с ID {board_id} не найдена")
 | 
						||
 | 
						||
        count_deals_in_progress = await self._count_deals_in_progress(board_id)
 | 
						||
        if count_deals_in_progress != 0:
 | 
						||
            return DeleteBoardResponse(
 | 
						||
                ok=False,
 | 
						||
                message=f"Нельзя удалить доску с активными сделками",
 | 
						||
            )
 | 
						||
 | 
						||
        count_deals = await self._count_deals(board_id)
 | 
						||
        if count_deals == 0:
 | 
						||
            await self.session.delete(board)
 | 
						||
        else:
 | 
						||
            board.is_deleted = True
 | 
						||
            for status in board.deal_statuses:
 | 
						||
                status.is_deleted = True
 | 
						||
 | 
						||
        await self.session.commit()
 | 
						||
 | 
						||
        return DeleteBoardResponse(ok=True, message="Доска успешно удалена")
 |