feat: nested department sections, attaching department sections in the user editor
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from sqlalchemy import select, update, delete, insert, and_
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from backend import config
|
||||
from external.s3_uploader.uploader import S3Uploader
|
||||
from models import User, user_position, user_pay_rate, PassportImage
|
||||
from models import User, user_position, user_pay_rate, PassportImage, DepartmentSection, UserDepartmentSection
|
||||
from services.base import BaseService
|
||||
from schemas.user import *
|
||||
|
||||
@@ -11,6 +12,9 @@ class UserService(BaseService):
|
||||
async def get_all(self) -> GetAllUsersResponse:
|
||||
stmt = (
|
||||
select(User)
|
||||
.options(
|
||||
selectinload(User.department_sections),
|
||||
)
|
||||
.order_by(User.id.desc())
|
||||
.where(User.is_deleted == False)
|
||||
)
|
||||
@@ -99,6 +103,36 @@ class UserService(BaseService):
|
||||
except Exception as e:
|
||||
return UpdateUserResponse(ok=False, message=str(e))
|
||||
|
||||
async def update_department_sections(
|
||||
self,
|
||||
user_id: int,
|
||||
request: UpdateUserDepartmentSectionsRequest
|
||||
) -> UpdateUserDepartmentSectionsResponse:
|
||||
user = await self.get_by_id(user_id)
|
||||
if not user:
|
||||
return UpdateUserDepartmentSectionsResponse(ok=False, message=f"Пользователь с ID: {user_id} не найден")
|
||||
|
||||
stmt_delete = delete(UserDepartmentSection).where(UserDepartmentSection.user_id == user_id)
|
||||
await self.session.execute(stmt_delete)
|
||||
|
||||
for section_schema in request.department_sections:
|
||||
section = await self.session.get(DepartmentSection, section_schema.section_id)
|
||||
if not section:
|
||||
await self.session.rollback()
|
||||
return UpdateUserDepartmentSectionsResponse(
|
||||
ok=False, message=f"Отдел с ID: {section_schema.section_id} не найден"
|
||||
)
|
||||
user_section = UserDepartmentSection(
|
||||
user_id=user_id,
|
||||
is_chief=section_schema.is_chief,
|
||||
section_id=section_schema.section_id
|
||||
)
|
||||
user.department_sections.append(user_section)
|
||||
|
||||
await self.session.commit()
|
||||
|
||||
return UpdateUserDepartmentSectionsResponse(ok=True, message="Отделы пользователя успешно обновлены")
|
||||
|
||||
async def upload_passport_image(self, user_id: int, file_bytes: bytes) -> UploadPassportImageResponse:
|
||||
try:
|
||||
user: Optional[User] = await self.session.get(User, user_id)
|
||||
|
||||
Reference in New Issue
Block a user