feat: nested department sections, attaching department sections in the user editor

This commit is contained in:
2025-01-19 12:01:10 +04:00
parent 43a95ef75c
commit b8947ce68e
7 changed files with 198 additions and 32 deletions

View File

@@ -1,19 +1,25 @@
from typing import Optional
from sqlalchemy import select, and_
from sqlalchemy import select, and_, delete, or_
from sqlalchemy.orm import selectinload
from models import Department, DepartmentSection, User, user_department_section
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(
selectinload(Department.sections).selectinload(DepartmentSection.users)
sections_selectinload,
selectinload(Department.sections)
.selectinload(DepartmentSection.users)
.selectinload(UserDepartmentSection.user)
.noload(User.department_sections),
)
.order_by(Department.name)
)
@@ -67,6 +73,11 @@ class DepartmentService(BaseService):
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)
@@ -76,21 +87,40 @@ class DepartmentService(BaseService):
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]:
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,
DepartmentSection.department_id == department_id,
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, request.section.department_id)
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="Отдел с таким названием уже существует в департаменте")
return CreateDepartmentSectionResponse(
ok=False,
message="Отдел с таким названием уже существует в департаменте",
)
section = DepartmentSection(name=request.section.name, department_id=request.section.department_id)
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="Отдел успешно создан")
@@ -99,6 +129,14 @@ class DepartmentService(BaseService):
section = await self._get_section_by_id(request.section.id)
if not section:
return UpdateDepartmentSectionResponse(ok=False, message=f"Отдел с ID {request.section.id} не найден")
if section.name != request.section.name:
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.name = request.section.name
await self.session.commit()
@@ -106,9 +144,9 @@ class DepartmentService(BaseService):
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)
select(UserDepartmentSection.user_id.label("user_id"))
.where(UserDepartmentSection.section_id == section_id)
.group_by(UserDepartmentSection.user_id)
.subquery()
)
stmt = (
@@ -141,10 +179,22 @@ class DepartmentService(BaseService):
return False, f"Пользователь с ID {request.user_id} не найден"
if is_adding:
section.users.append(user)
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:
section.users.remove(user)
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()