160 lines
7.8 KiB
Python
160 lines
7.8 KiB
Python
from typing import Optional
|
||
|
||
from sqlalchemy import select, and_
|
||
from sqlalchemy.orm import selectinload
|
||
|
||
from models import Department, DepartmentSection, User, user_department_section
|
||
from schemas.department import *
|
||
from services.base import BaseService
|
||
|
||
|
||
class DepartmentService(BaseService):
|
||
async def get_departments(self) -> GetDepartmentsResponse:
|
||
stmt = (
|
||
select(Department)
|
||
.options(
|
||
selectinload(Department.sections).selectinload(DepartmentSection.users)
|
||
)
|
||
.order_by(Department.name)
|
||
)
|
||
departments = (await self.session.execute(stmt)).scalars().all()
|
||
return GetDepartmentsResponse(departments=departments)
|
||
|
||
async def _get_department(self, filter_condition) -> Optional[Department]:
|
||
stmt = (
|
||
select(Department)
|
||
.where(filter_condition)
|
||
.options(selectinload(Department.sections))
|
||
)
|
||
departments = (await self.session.execute(stmt)).one_or_none()
|
||
return departments[0] if departments else None
|
||
|
||
async def _get_department_by_name(self, name: str) -> Optional[Department]:
|
||
return await self._get_department(Department.name == name)
|
||
|
||
async def _get_department_by_id(self, department_id: int) -> Optional[Department]:
|
||
return await self._get_department(Department.id == department_id)
|
||
|
||
async def create_department(self, request: CreateDepartmentRequest) -> CreateDepartmentResponse:
|
||
department = await self._get_department_by_name(request.department.name)
|
||
if department:
|
||
return CreateDepartmentResponse(ok=False, message="Департамент с таким названием уже существует")
|
||
|
||
department = Department(name=request.department.name)
|
||
self.session.add(department)
|
||
await self.session.commit()
|
||
return CreateDepartmentResponse(ok=True, message="Департамент успешно создан")
|
||
|
||
async def update_department(self, request: UpdateDepartmentRequest) -> UpdateDepartmentResponse:
|
||
department_same_name = await self._get_department_by_name(request.department.name)
|
||
if department_same_name and department_same_name.id != request.department.id:
|
||
return UpdateDepartmentResponse(ok=False, message="Департамент с данным именем уже существует")
|
||
|
||
department = await self._get_department_by_id(request.department.id)
|
||
if not department:
|
||
return UpdateDepartmentResponse(ok=False, message=f"Департамент с ID {request.department.id} не найден")
|
||
|
||
department.name = request.department.name
|
||
await self.session.commit()
|
||
return UpdateDepartmentResponse(ok=True, message="Департамент успешно изменен")
|
||
|
||
async def delete_department(self, department_id: int) -> DeleteDepartmentResponse:
|
||
department = await self.session.get(Department, department_id)
|
||
if not department:
|
||
return CreateDepartmentResponse(ok=False, message=f"Департамент с ID {department_id} не найден")
|
||
|
||
await self.session.delete(department)
|
||
await self.session.commit()
|
||
return DeleteDepartmentResponse(ok=True, message="Департамент успешно удален")
|
||
|
||
async def _get_section(self, filter_condition) -> Optional[DepartmentSection]:
|
||
stmt = (
|
||
select(DepartmentSection)
|
||
.where(filter_condition)
|
||
.options(selectinload(DepartmentSection.users))
|
||
)
|
||
departments = (await self.session.execute(stmt)).one_or_none()
|
||
return departments[0] if departments else None
|
||
|
||
async def _get_section_by_name(self, name: str, department_id: int) -> Optional[DepartmentSection]:
|
||
return await self._get_section(and_(
|
||
DepartmentSection.name == name,
|
||
DepartmentSection.department_id == department_id,
|
||
))
|
||
|
||
async def _get_section_by_id(self, section_id: int) -> Optional[DepartmentSection]:
|
||
return await self._get_section(DepartmentSection.id == section_id)
|
||
|
||
async def create_department_section(self, request: CreateDepartmentSectionRequest) -> CreateDepartmentSectionResponse:
|
||
section = await self._get_section_by_name(request.section.name, request.section.department_id)
|
||
if section:
|
||
return CreateDepartmentSectionResponse(ok=False, message="Отдел с таким названием уже существует в департаменте")
|
||
|
||
section = DepartmentSection(name=request.section.name, department_id=request.section.department_id)
|
||
self.session.add(section)
|
||
await self.session.commit()
|
||
return CreateDepartmentSectionResponse(ok=True, message="Отдел успешно создан")
|
||
|
||
async def update_department_section(self, request: UpdateDepartmentSectionRequest) -> UpdateDepartmentSectionResponse:
|
||
section = await self._get_section_by_id(request.section.id)
|
||
if not section:
|
||
return UpdateDepartmentSectionResponse(ok=False, message=f"Отдел с ID {request.section.id} не найден")
|
||
|
||
section.name = request.section.name
|
||
await self.session.commit()
|
||
return UpdateDepartmentSectionResponse(ok=True, message="Отдел успешно изменен")
|
||
|
||
async def get_available_users_for_section(self, section_id: int) -> GetAvailableUsersForDepartmentSectionResponse:
|
||
sub_user_ids_in_section = (
|
||
select(user_department_section.c.user_id.label("user_id"))
|
||
.where(user_department_section.c.department_section_id == section_id)
|
||
.group_by(user_department_section.c.user_id)
|
||
.subquery()
|
||
)
|
||
stmt = (
|
||
select(User)
|
||
.join(sub_user_ids_in_section, sub_user_ids_in_section.c.user_id == User.id, isouter=True)
|
||
.where(and_(
|
||
sub_user_ids_in_section.c.user_id == None,
|
||
User.is_deleted == False,
|
||
))
|
||
)
|
||
users = (await self.session.execute(stmt)).scalars().all()
|
||
return GetAvailableUsersForDepartmentSectionResponse(users=users)
|
||
|
||
async def delete_department_section(self, section_id: int) -> DeleteDepartmentSectionResponse:
|
||
section = await self._get_section_by_id(section_id)
|
||
if not section:
|
||
return DeleteDepartmentSectionResponse(ok=False, message=f"Отдел с ID {section_id} не найден")
|
||
|
||
await self.session.delete(section)
|
||
await self.session.commit()
|
||
return DeleteDepartmentSectionResponse(ok=True, message="Отдел успешно удален")
|
||
|
||
async def _modify_user(self, request: AddUserRequest | DeleteUserRequest, is_adding: bool) -> tuple[bool, str]:
|
||
section = await self._get_section_by_id(request.section_id)
|
||
if not section:
|
||
return False, f"Отдел с ID {request.section_id} не найден"
|
||
|
||
user = await self.session.get(User, request.user_id)
|
||
if not user:
|
||
return False, f"Пользователь с ID {request.user_id} не найден"
|
||
|
||
if is_adding:
|
||
section.users.append(user)
|
||
message = f"Пользователь успешно добавлен в отдел"
|
||
else:
|
||
section.users.remove(user)
|
||
message = f"Пользователь успешно удален из отдела"
|
||
|
||
await self.session.commit()
|
||
return True, message
|
||
|
||
async def add_user(self, request: AddUserRequest) -> AddUserResponse:
|
||
ok, message = await self._modify_user(request, True)
|
||
return AddUserResponse(ok=ok, message=message)
|
||
|
||
async def delete_user(self, request: DeleteUserRequest) -> DeleteUserResponse:
|
||
ok, message = await self._modify_user(request, False)
|
||
return DeleteUserResponse(ok=ok, message=message)
|