feat: projects and boards
This commit is contained in:
128
services/status.py
Normal file
128
services/status.py
Normal file
@@ -0,0 +1,128 @@
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import select, and_, func
|
||||
|
||||
from models import DealStatus, Deal
|
||||
from schemas.status import *
|
||||
from services.base import BaseService
|
||||
|
||||
|
||||
class StatusService(BaseService):
|
||||
async def _get_statuses_for_board(self, board_id: int) -> list[DealStatus]:
|
||||
stmt = (
|
||||
select(DealStatus)
|
||||
.where(
|
||||
and_(
|
||||
DealStatus.board_id == board_id,
|
||||
DealStatus.is_deleted == False,
|
||||
)
|
||||
)
|
||||
.order_by(DealStatus.ordinal_number)
|
||||
)
|
||||
statuses = (await self.session.scalars(stmt)).all()
|
||||
return list(statuses)
|
||||
|
||||
async def _get_status_by_id(self, status_id: int) -> Optional[DealStatus]:
|
||||
stmt = (
|
||||
select(DealStatus)
|
||||
.where(DealStatus.id == status_id)
|
||||
)
|
||||
status = await self.session.scalar(stmt)
|
||||
return status
|
||||
|
||||
async def create_status(self, request: CreateStatusRequest) -> CreateStatusResponse:
|
||||
statuses = await self._get_statuses_for_board(request.status.board_id)
|
||||
if len(statuses) == 0:
|
||||
ordinal_number = 1
|
||||
else:
|
||||
statuses[-1].is_finishing = False
|
||||
ordinal_number = statuses[-1].ordinal_number + 1
|
||||
|
||||
status = DealStatus(
|
||||
**request.status.model_dump(),
|
||||
ordinal_number=ordinal_number,
|
||||
is_finishing=True,
|
||||
)
|
||||
self.session.add(status)
|
||||
await self.session.commit()
|
||||
|
||||
return CreateStatusResponse(ok=True, message="Статус успешно создан")
|
||||
|
||||
async def update_status(self, request: UpdateStatusRequest) -> UpdateStatusResponse:
|
||||
status = await self._get_status_by_id(request.status.id)
|
||||
if not status:
|
||||
return UpdateStatusResponse(ok=False, message=f"Статус с ID {request.status.id} не найден")
|
||||
|
||||
status.name = request.status.name
|
||||
await self.session.commit()
|
||||
|
||||
return UpdateStatusResponse(ok=True, message="Статус успешно изменен")
|
||||
|
||||
async def update_status_order(self, request: UpdateStatusOrderRequest) -> UpdateStatusOrderResponse:
|
||||
statuses = await self._get_statuses_for_board(request.board_id)
|
||||
status_idx = 0
|
||||
while status_idx < len(statuses) and statuses[status_idx].id != request.status_id:
|
||||
status_idx += 1
|
||||
if status_idx == len(statuses):
|
||||
return UpdateStatusOrderResponse(ok=False, message=f"Статус с ID {request.status_id} не найден")
|
||||
|
||||
status = statuses.pop(status_idx)
|
||||
statuses.insert(request.new_ordinal_number - 1, status)
|
||||
new_ordinal_number = 1
|
||||
for status in statuses:
|
||||
status.ordinal_number = new_ordinal_number
|
||||
status.is_finishing = False
|
||||
new_ordinal_number += 1
|
||||
|
||||
statuses[-1].is_finishing = True
|
||||
|
||||
await self.session.commit()
|
||||
return UpdateStatusOrderResponse(ok=True, message="Порядок статусов изменен")
|
||||
|
||||
async def _count_deals_in_progress(self, status_id: int) -> int:
|
||||
stmt = (
|
||||
select(func.count(Deal.id))
|
||||
.where(
|
||||
and_(
|
||||
Deal.current_status_id == status_id,
|
||||
Deal.is_deleted == False,
|
||||
Deal.is_completed == False,
|
||||
)
|
||||
)
|
||||
)
|
||||
return (await self.session.scalars(stmt)).first()
|
||||
|
||||
async def _count_deals(self, status_id: int) -> int:
|
||||
stmt = (
|
||||
select(func.count(Deal.id))
|
||||
.where(Deal.current_status_id == status_id)
|
||||
)
|
||||
return (await self.session.scalars(stmt)).first()
|
||||
|
||||
async def _set_finishing_flag_to_prev_status(self, status: DealStatus):
|
||||
statuses = await self._get_statuses_for_board(status.board_id)
|
||||
if len(statuses) < 2:
|
||||
return
|
||||
statuses[-2].is_finishing = True
|
||||
statuses[-1].is_finishing = False
|
||||
|
||||
async def delete_status(self, status_id: int) -> DeleteStatusResponse:
|
||||
status = await self._get_status_by_id(status_id)
|
||||
if not status:
|
||||
return DeleteStatusResponse(ok=False, message=f"Статус с ID {status_id} не найден")
|
||||
|
||||
count_deals_in_progress = await self._count_deals_in_progress(status_id)
|
||||
if count_deals_in_progress != 0:
|
||||
return DeleteStatusResponse(ok=False, message="Нельзя удалить статус с активными сделками")
|
||||
|
||||
if status.is_finishing:
|
||||
await self._set_finishing_flag_to_prev_status(status)
|
||||
|
||||
count_deals = await self._count_deals(status_id)
|
||||
if count_deals == 0:
|
||||
await self.session.delete(status)
|
||||
else:
|
||||
status.is_deleted = True
|
||||
await self.session.commit()
|
||||
|
||||
return DeleteStatusResponse(ok=True, message="Статус успешно удален")
|
||||
Reference in New Issue
Block a user