Files
hospital_performance/backend/app/services/department_service.py
2026-02-28 15:06:52 +08:00

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