Files
Fulfillment-Backend/services/department.py

212 lines
9.9 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 sqlalchemy import select, and_, delete, or_
from sqlalchemy.orm import selectinload
from models import Department, DepartmentSection, User, UserDepartmentSection
from schemas.department import *
from services.base import BaseService
class DepartmentService(BaseService):
async def get_departments(self) -> GetDepartmentsResponse:
sections_selectinload = selectinload(Department.sections)
for _ in range(10):
sections_selectinload = sections_selectinload.selectinload(DepartmentSection.sections)
stmt = (
select(Department)
.options(
sections_selectinload,
selectinload(Department.sections)
.selectinload(DepartmentSection.users)
.selectinload(UserDepartmentSection.user)
.noload(User.department_sections),
)
.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_sections(self) -> GetDepartmentSectionsResponse:
stmt = select(DepartmentSection)
sections = (await self.session.execute(stmt)).scalars().all()
return GetDepartmentSectionsResponse(department_sections=sections)
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 = None,
parent_section_id: int = None,
) -> Optional[DepartmentSection]:
return await self._get_section(and_(
DepartmentSection.name == name,
and_(
or_(department_id is None, DepartmentSection.department_id == department_id),
or_(parent_section_id is None, DepartmentSection.parent_department_section_id == parent_section_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,
department_id=request.section.department_id,
parent_section_id=request.section.parent_department_section_id,
)
if section:
return CreateDepartmentSectionResponse(
ok=False,
message="Отдел с таким названием уже существует в департаменте",
)
section = DepartmentSection(
name=request.section.name,
department_id=request.section.department_id,
parent_department_section_id=request.section.parent_department_section_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_same_name = await self._get_section_by_name(
request.section.name,
department_id=request.section.department_id,
parent_section_id=request.section.parent_department_section_id,
)
if section_same_name:
return UpdateDepartmentSectionResponse(ok=False, message="Отдел с данным именем уже существует")
section.parent_department_section_id = request.section.parent_department_section_id
section.department_id = request.section.department_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(UserDepartmentSection.user_id.label("user_id"))
.where(UserDepartmentSection.section_id == section_id)
.group_by(UserDepartmentSection.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:
user_department_section = UserDepartmentSection(
user_id=request.user_id,
section_id=section.id,
is_chief=request.is_chief,
)
section.users.append(user_department_section)
message = f"Пользователь успешно добавлен в отдел"
else:
delete_stmt = (
delete(UserDepartmentSection)
.where(and_(
UserDepartmentSection.user_id == request.user_id,
UserDepartmentSection.section_id == request.section_id,
))
)
await self.session.execute(delete_stmt)
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)