feat: departments and department sections
This commit is contained in:
		
							
								
								
									
										1
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								main.py
									
									
									
									
									
								
							@@ -49,6 +49,7 @@ routers_list = [
 | 
				
			|||||||
    routers.work_shifts_router,
 | 
					    routers.work_shifts_router,
 | 
				
			||||||
    routers.transaction_router,
 | 
					    routers.transaction_router,
 | 
				
			||||||
    routers.shipping_router,
 | 
					    routers.shipping_router,
 | 
				
			||||||
 | 
					    routers.department_router,
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
for router in routers_list:
 | 
					for router in routers_list:
 | 
				
			||||||
    app.include_router(router)
 | 
					    app.include_router(router)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,13 @@ user_pay_rate = Table(
 | 
				
			|||||||
    Column('user_id', ForeignKey('users.id'), primary_key=True, unique=True)
 | 
					    Column('user_id', ForeignKey('users.id'), primary_key=True, unique=True)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					user_department_section = Table(
 | 
				
			||||||
 | 
					    'user_department_section',
 | 
				
			||||||
 | 
					    BaseModel.metadata,
 | 
				
			||||||
 | 
					    Column('department_section_id', ForeignKey('department_sections.id'), primary_key=True),
 | 
				
			||||||
 | 
					    Column('user_id', ForeignKey('users.id'), primary_key=True)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Permission(BaseModel):
 | 
					class Permission(BaseModel):
 | 
				
			||||||
    __tablename__ = 'permissions'
 | 
					    __tablename__ = 'permissions'
 | 
				
			||||||
@@ -135,3 +142,33 @@ class PassportImage(BaseModel):
 | 
				
			|||||||
    user: Mapped["User"] = relationship(back_populates='passport_images')
 | 
					    user: Mapped["User"] = relationship(back_populates='passport_images')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    image_url: Mapped[str] = mapped_column(nullable=False)
 | 
					    image_url: Mapped[str] = mapped_column(nullable=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Department(BaseModel):
 | 
				
			||||||
 | 
					    __tablename__ = 'departments'
 | 
				
			||||||
 | 
					    id: Mapped[int] = mapped_column(primary_key=True)
 | 
				
			||||||
 | 
					    name: Mapped[str] = mapped_column(unique=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sections: Mapped[list['DepartmentSection']] = relationship(
 | 
				
			||||||
 | 
					        back_populates='department',
 | 
				
			||||||
 | 
					        lazy='selectin',
 | 
				
			||||||
 | 
					        cascade='all, delete',
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DepartmentSection(BaseModel):
 | 
				
			||||||
 | 
					    __tablename__ = 'department_sections'
 | 
				
			||||||
 | 
					    id: Mapped[int] = mapped_column(primary_key=True)
 | 
				
			||||||
 | 
					    name: Mapped[str] = mapped_column(index=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    department_id: Mapped[int] = mapped_column(ForeignKey('departments.id'))
 | 
				
			||||||
 | 
					    department: Mapped["Department"] = relationship(
 | 
				
			||||||
 | 
					        back_populates='sections',
 | 
				
			||||||
 | 
					        lazy='selectin',
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    users: Mapped[list[User]] = relationship(
 | 
				
			||||||
 | 
					        'User',
 | 
				
			||||||
 | 
					        secondary=user_department_section,
 | 
				
			||||||
 | 
					        uselist=True,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,3 +17,4 @@ from .work_shifts import work_shifts_router
 | 
				
			|||||||
from .statistics import statistics_router
 | 
					from .statistics import statistics_router
 | 
				
			||||||
from .transaction import transaction_router
 | 
					from .transaction import transaction_router
 | 
				
			||||||
from .shipping import shipping_router
 | 
					from .shipping import shipping_router
 | 
				
			||||||
 | 
					from .department import department_router
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										131
									
								
								routers/department.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								routers/department.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from backend.dependecies import SessionDependency
 | 
				
			||||||
 | 
					from schemas.department import *
 | 
				
			||||||
 | 
					from services.auth import authorized_user
 | 
				
			||||||
 | 
					from services.department import DepartmentService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					department_router = APIRouter(
 | 
				
			||||||
 | 
					    prefix="/department",
 | 
				
			||||||
 | 
					    tags=["department"],
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.get(
 | 
				
			||||||
 | 
					    "/",
 | 
				
			||||||
 | 
					    operation_id="get_departments",
 | 
				
			||||||
 | 
					    response_model=GetDepartmentsResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def get_departments(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).get_departments()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.post(
 | 
				
			||||||
 | 
					    "/",
 | 
				
			||||||
 | 
					    operation_id="create_department",
 | 
				
			||||||
 | 
					    response_model=CreateDepartmentResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def create_department(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: CreateDepartmentRequest,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).create_department(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.patch(
 | 
				
			||||||
 | 
					    "/",
 | 
				
			||||||
 | 
					    operation_id="update_department",
 | 
				
			||||||
 | 
					    response_model=UpdateDepartmentResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def update_department(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: UpdateDepartmentRequest,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).update_department(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.delete(
 | 
				
			||||||
 | 
					    "/{department_id}",
 | 
				
			||||||
 | 
					    operation_id="delete_department",
 | 
				
			||||||
 | 
					    response_model=DeleteDepartmentResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def delete_department(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        department_id: int,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).delete_department(department_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.post(
 | 
				
			||||||
 | 
					    "/section",
 | 
				
			||||||
 | 
					    operation_id="create_section",
 | 
				
			||||||
 | 
					    response_model=CreateDepartmentSectionResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def create_section(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: CreateDepartmentSectionRequest,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).create_department_section(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.patch(
 | 
				
			||||||
 | 
					    "/section",
 | 
				
			||||||
 | 
					    operation_id="update_section",
 | 
				
			||||||
 | 
					    response_model=UpdateDepartmentSectionResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def update_section(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: UpdateDepartmentSectionRequest,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).update_department_section(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.delete(
 | 
				
			||||||
 | 
					    "/section/{section_id}",
 | 
				
			||||||
 | 
					    operation_id="delete_section",
 | 
				
			||||||
 | 
					    response_model=DeleteDepartmentSectionResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def delete_section(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        section_id: int,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).delete_department_section(section_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.get(
 | 
				
			||||||
 | 
					    "/users/{section_id}",
 | 
				
			||||||
 | 
					    operation_id="get_available_users_for_section",
 | 
				
			||||||
 | 
					    response_model=GetAvailableUsersForDepartmentSectionResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def get_available_users_for_department_section(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        section_id: int,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).get_available_users_for_section(section_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.post(
 | 
				
			||||||
 | 
					    "/users",
 | 
				
			||||||
 | 
					    operation_id="add_user",
 | 
				
			||||||
 | 
					    response_model=AddUserResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def add_user(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: AddUserRequest,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).add_user(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@department_router.post(
 | 
				
			||||||
 | 
					    "/users/delete",
 | 
				
			||||||
 | 
					    operation_id="delete_user",
 | 
				
			||||||
 | 
					    response_model=DeleteUserResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def delete_user(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: DeleteUserRequest,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DepartmentService(session).delete_user(request)
 | 
				
			||||||
							
								
								
									
										99
									
								
								schemas/department.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								schemas/department.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					from schemas.base import BaseSchema, OkMessageSchema
 | 
				
			||||||
 | 
					from schemas.user import UserSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Entities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DepartmentSectionBaseSchema(BaseSchema):
 | 
				
			||||||
 | 
					    name: str
 | 
				
			||||||
 | 
					    department_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DepartmentSectionSchema(DepartmentSectionBaseSchema):
 | 
				
			||||||
 | 
					    id: int
 | 
				
			||||||
 | 
					    users: list[UserSchema] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DepartmentBaseSchema(BaseSchema):
 | 
				
			||||||
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DepartmentSchema(DepartmentBaseSchema):
 | 
				
			||||||
 | 
					    id: int
 | 
				
			||||||
 | 
					    sections: list[DepartmentSectionSchema] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateDepartmentRequest(BaseSchema):
 | 
				
			||||||
 | 
					    department: DepartmentBaseSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateDepartmentRequest(BaseSchema):
 | 
				
			||||||
 | 
					    department: DepartmentSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateDepartmentSectionRequest(BaseSchema):
 | 
				
			||||||
 | 
					    section: DepartmentSectionBaseSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateDepartmentSectionRequest(BaseSchema):
 | 
				
			||||||
 | 
					    section: DepartmentSectionSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddUserRequest(BaseSchema):
 | 
				
			||||||
 | 
					    user_id: int
 | 
				
			||||||
 | 
					    section_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeleteUserRequest(BaseSchema):
 | 
				
			||||||
 | 
					    user_id: int
 | 
				
			||||||
 | 
					    section_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Responses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GetDepartmentsResponse(BaseSchema):
 | 
				
			||||||
 | 
					    departments: list[DepartmentSchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateDepartmentResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateDepartmentResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeleteDepartmentResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateDepartmentSectionResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateDepartmentSectionResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeleteDepartmentSectionResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GetAvailableUsersForDepartmentSectionResponse(BaseSchema):
 | 
				
			||||||
 | 
					    users: list[UserSchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddUserResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeleteUserResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
							
								
								
									
										159
									
								
								services/department.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								services/department.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
				
			|||||||
 | 
					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)
 | 
				
			||||||
		Reference in New Issue
	
	Block a user