""" 科室服务层 """ 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