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="Доска успешно удалена")
|