Files
Fulfillment-Backend/services/status.py

129 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from typing import Optional
from sqlalchemy import select, and_, func
from models import CardStatus, Card
from schemas.status import *
from services.base import BaseService
class StatusService(BaseService):
async def _get_statuses_for_board(self, board_id: int) -> list[CardStatus]:
stmt = (
select(CardStatus)
.where(
and_(
CardStatus.board_id == board_id,
CardStatus.is_deleted == False,
)
)
.order_by(CardStatus.ordinal_number)
)
statuses = (await self.session.scalars(stmt)).all()
return list(statuses)
async def _get_status_by_id(self, status_id: int) -> Optional[CardStatus]:
stmt = (
select(CardStatus)
.where(CardStatus.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 = CardStatus(
**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(Card.id))
.where(
and_(
Card.current_status_id == status_id,
Card.is_deleted == False,
Card.is_completed == False,
)
)
)
return (await self.session.scalars(stmt)).first()
async def _count_deals(self, status_id: int) -> int:
stmt = (
select(func.count(Card.id))
.where(Card.current_status_id == status_id)
)
return (await self.session.scalars(stmt)).first()
async def _set_finishing_flag_to_prev_status(self, status: CardStatus):
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="Статус успешно удален")