feat: projects and boards
This commit is contained in:
119
services/board.py
Normal file
119
services/board.py
Normal file
@@ -0,0 +1,119 @@
|
||||
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="Доска успешно удалена")
|
||||
Reference in New Issue
Block a user