150 lines
4.8 KiB
Python
150 lines
4.8 KiB
Python
"""
|
|
科室服务层
|
|
"""
|
|
from typing import Optional, List
|
|
from sqlalchemy import select, func
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy.orm import selectinload
|
|
|
|
from app.models.models import Department
|
|
from app.schemas.schemas import DepartmentCreate, DepartmentUpdate, DepartmentTree
|
|
|
|
|
|
class DepartmentService:
|
|
"""科室服务"""
|
|
|
|
@staticmethod
|
|
async def get_list(
|
|
db: AsyncSession,
|
|
dept_type: Optional[str] = None,
|
|
is_active: Optional[bool] = None,
|
|
page: int = 1,
|
|
page_size: int = 20
|
|
) -> tuple[List[Department], int]:
|
|
"""获取科室列表"""
|
|
query = select(Department)
|
|
|
|
if dept_type:
|
|
query = query.where(Department.dept_type == dept_type)
|
|
if is_active is not None:
|
|
query = query.where(Department.is_active == is_active)
|
|
|
|
# 统计总数
|
|
count_query = select(func.count()).select_from(query.subquery())
|
|
total = await db.scalar(count_query)
|
|
|
|
# 分页
|
|
query = query.order_by(Department.sort_order, Department.id)
|
|
query = query.offset((page - 1) * page_size).limit(page_size)
|
|
|
|
result = await db.execute(query)
|
|
departments = result.scalars().all()
|
|
|
|
return departments, total or 0
|
|
|
|
@staticmethod
|
|
async def get_by_id(db: AsyncSession, dept_id: int) -> Optional[Department]:
|
|
"""根据ID获取科室"""
|
|
result = await db.execute(
|
|
select(Department).where(Department.id == dept_id)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
@staticmethod
|
|
async def get_by_code(db: AsyncSession, code: str) -> Optional[Department]:
|
|
"""根据编码获取科室"""
|
|
result = await db.execute(
|
|
select(Department).where(Department.code == code)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
@staticmethod
|
|
async def create(db: AsyncSession, dept_data: DepartmentCreate) -> Department:
|
|
"""创建科室"""
|
|
# 计算层级
|
|
level = 1
|
|
if dept_data.parent_id:
|
|
parent = await DepartmentService.get_by_id(db, dept_data.parent_id)
|
|
if parent:
|
|
level = parent.level + 1
|
|
|
|
department = Department(
|
|
**dept_data.model_dump(exclude={'level'}),
|
|
level=level
|
|
)
|
|
db.add(department)
|
|
await db.flush()
|
|
await db.refresh(department)
|
|
return department
|
|
|
|
@staticmethod
|
|
async def update(db: AsyncSession, dept_id: int, dept_data: DepartmentUpdate) -> Optional[Department]:
|
|
"""更新科室"""
|
|
department = await DepartmentService.get_by_id(db, dept_id)
|
|
if not department:
|
|
return None
|
|
|
|
update_data = dept_data.model_dump(exclude_unset=True)
|
|
for key, value in update_data.items():
|
|
setattr(department, key, value)
|
|
|
|
await db.flush()
|
|
await db.refresh(department)
|
|
return department
|
|
|
|
@staticmethod
|
|
async def delete(db: AsyncSession, dept_id: int) -> bool:
|
|
"""删除科室"""
|
|
department = await DepartmentService.get_by_id(db, dept_id)
|
|
if not department:
|
|
return False
|
|
|
|
# 检查是否有子科室
|
|
result = await db.execute(
|
|
select(func.count()).where(Department.parent_id == dept_id)
|
|
)
|
|
if result.scalar() > 0:
|
|
return False
|
|
|
|
await db.delete(department)
|
|
return True
|
|
|
|
@staticmethod
|
|
async def get_tree(db: AsyncSession, dept_type: Optional[str] = None) -> List[DepartmentTree]:
|
|
"""获取科室树形结构"""
|
|
query = select(Department).order_by(Department.sort_order, Department.id)
|
|
|
|
if dept_type:
|
|
query = query.where(Department.dept_type == dept_type)
|
|
|
|
result = await db.execute(query)
|
|
departments = result.scalars().all()
|
|
|
|
# 构建树形结构 - 手动构建避免懒加载问题
|
|
dept_map = {}
|
|
for d in departments:
|
|
dept_map[d.id] = DepartmentTree(
|
|
id=d.id,
|
|
name=d.name,
|
|
code=d.code,
|
|
dept_type=d.dept_type,
|
|
parent_id=d.parent_id,
|
|
level=d.level,
|
|
sort_order=d.sort_order,
|
|
is_active=d.is_active,
|
|
description=d.description,
|
|
created_at=d.created_at,
|
|
updated_at=d.updated_at,
|
|
children=[]
|
|
)
|
|
roots = []
|
|
|
|
for dept in departments:
|
|
tree_node = dept_map[dept.id]
|
|
if dept.parent_id and dept.parent_id in dept_map:
|
|
dept_map[dept.parent_id].children.append(tree_node)
|
|
else:
|
|
roots.append(tree_node)
|
|
|
|
return roots
|