add backend source code
This commit is contained in:
196
backend/app/services/indicator_service.py
Normal file
196
backend/app/services/indicator_service.py
Normal file
@@ -0,0 +1,196 @@
|
||||
"""
|
||||
考核指标服务层
|
||||
"""
|
||||
import json
|
||||
from typing import Optional, List, Dict, Any
|
||||
from sqlalchemy import select, func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.models import Indicator, IndicatorType, BSCDimension
|
||||
from app.schemas.schemas import IndicatorCreate, IndicatorUpdate
|
||||
|
||||
|
||||
class IndicatorService:
|
||||
"""考核指标服务"""
|
||||
|
||||
@staticmethod
|
||||
async def get_list(
|
||||
db: AsyncSession,
|
||||
indicator_type: Optional[str] = None,
|
||||
bs_dimension: Optional[str] = None,
|
||||
is_active: Optional[bool] = None,
|
||||
page: int = 1,
|
||||
page_size: int = 20
|
||||
) -> tuple[List[Indicator], int]:
|
||||
"""获取指标列表"""
|
||||
query = select(Indicator)
|
||||
|
||||
if indicator_type:
|
||||
query = query.where(Indicator.indicator_type == indicator_type)
|
||||
if bs_dimension:
|
||||
query = query.where(Indicator.bs_dimension == bs_dimension)
|
||||
if is_active is not None:
|
||||
query = query.where(Indicator.is_active == is_active)
|
||||
|
||||
# 统计总数
|
||||
count_query = select(func.count()).select_from(query.subquery())
|
||||
total = await db.scalar(count_query)
|
||||
|
||||
# 分页
|
||||
query = query.order_by(Indicator.indicator_type, Indicator.id)
|
||||
query = query.offset((page - 1) * page_size).limit(page_size)
|
||||
|
||||
result = await db.execute(query)
|
||||
indicators = result.scalars().all()
|
||||
|
||||
return indicators, total or 0
|
||||
|
||||
@staticmethod
|
||||
async def get_by_id(db: AsyncSession, indicator_id: int) -> Optional[Indicator]:
|
||||
"""根据 ID 获取指标"""
|
||||
result = await db.execute(
|
||||
select(Indicator).where(Indicator.id == indicator_id)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
@staticmethod
|
||||
async def get_active_indicators(db: AsyncSession) -> List[Indicator]:
|
||||
"""获取所有启用的指标"""
|
||||
result = await db.execute(
|
||||
select(Indicator)
|
||||
.where(Indicator.is_active == True)
|
||||
.order_by(Indicator.indicator_type, Indicator.id)
|
||||
)
|
||||
return result.scalars().all()
|
||||
|
||||
@staticmethod
|
||||
async def create(db: AsyncSession, indicator_data: IndicatorCreate) -> Indicator:
|
||||
"""创建指标"""
|
||||
indicator = Indicator(**indicator_data.model_dump())
|
||||
db.add(indicator)
|
||||
await db.commit()
|
||||
await db.refresh(indicator)
|
||||
return indicator
|
||||
|
||||
@staticmethod
|
||||
async def update(
|
||||
db: AsyncSession,
|
||||
indicator_id: int,
|
||||
indicator_data: IndicatorUpdate
|
||||
) -> Optional[Indicator]:
|
||||
"""更新指标"""
|
||||
indicator = await IndicatorService.get_by_id(db, indicator_id)
|
||||
if not indicator:
|
||||
return None
|
||||
|
||||
update_data = indicator_data.model_dump(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(indicator, key, value)
|
||||
|
||||
await db.commit()
|
||||
await db.refresh(indicator)
|
||||
return indicator
|
||||
|
||||
@staticmethod
|
||||
async def delete(db: AsyncSession, indicator_id: int) -> bool:
|
||||
"""删除指标"""
|
||||
indicator = await IndicatorService.get_by_id(db, indicator_id)
|
||||
if not indicator:
|
||||
return False
|
||||
|
||||
await db.delete(indicator)
|
||||
await db.commit()
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
async def import_template(
|
||||
db: AsyncSession,
|
||||
template_data: Dict[str, Any],
|
||||
overwrite: bool = False
|
||||
) -> int:
|
||||
"""导入指标模板"""
|
||||
dept_type = template_data.get('dept_type')
|
||||
indicators_data = template_data.get('indicators', [])
|
||||
created_count = 0
|
||||
|
||||
for ind_data in indicators_data:
|
||||
# 检查是否已存在
|
||||
existing = await db.execute(
|
||||
select(Indicator).where(Indicator.code == ind_data['code'])
|
||||
)
|
||||
|
||||
if existing.scalar_one_or_none():
|
||||
if overwrite:
|
||||
# 更新现有指标
|
||||
indicator = existing.scalar_one_or_none()
|
||||
if indicator:
|
||||
for key, value in ind_data.items():
|
||||
if hasattr(indicator, key):
|
||||
setattr(indicator, key, value)
|
||||
continue
|
||||
|
||||
# 创建新指标
|
||||
indicator = Indicator(
|
||||
name=ind_data.get('name'),
|
||||
code=ind_data.get('code'),
|
||||
indicator_type=ind_data.get('indicator_type'),
|
||||
bs_dimension=ind_data.get('bs_dimension'),
|
||||
weight=ind_data.get('weight', 1.0),
|
||||
max_score=ind_data.get('max_score', 100.0),
|
||||
target_value=ind_data.get('target_value'),
|
||||
target_unit=ind_data.get('target_unit'),
|
||||
calculation_method=ind_data.get('calculation_method'),
|
||||
assessment_method=ind_data.get('assessment_method'),
|
||||
deduction_standard=ind_data.get('deduction_standard'),
|
||||
data_source=ind_data.get('data_source'),
|
||||
applicable_dept_types=json.dumps([dept_type]) if dept_type else None,
|
||||
is_veto=ind_data.get('is_veto', False),
|
||||
is_active=ind_data.get('is_active', True)
|
||||
)
|
||||
db.add(indicator)
|
||||
created_count += 1
|
||||
|
||||
await db.commit()
|
||||
return created_count
|
||||
|
||||
@staticmethod
|
||||
async def get_templates() -> List[Dict[str, Any]]:
|
||||
"""获取指标模板列表"""
|
||||
return [
|
||||
{
|
||||
"name": "手术临床科室考核指标",
|
||||
"dept_type": "clinical_surgical",
|
||||
"description": "适用于外科系统各手术科室",
|
||||
"indicator_count": 12
|
||||
},
|
||||
{
|
||||
"name": "非手术有病房科室考核指标",
|
||||
"dept_type": "clinical_nonsurgical_ward",
|
||||
"description": "适用于内科系统等有病房科室",
|
||||
"indicator_count": 10
|
||||
},
|
||||
{
|
||||
"name": "非手术无病房科室考核指标",
|
||||
"dept_type": "clinical_nonsurgical_noward",
|
||||
"description": "适用于门诊科室",
|
||||
"indicator_count": 8
|
||||
},
|
||||
{
|
||||
"name": "医技科室考核指标",
|
||||
"dept_type": "medical_tech",
|
||||
"description": "适用于检验科、放射科等医技科室",
|
||||
"indicator_count": 8
|
||||
},
|
||||
{
|
||||
"name": "行政科室考核指标",
|
||||
"dept_type": "admin",
|
||||
"description": "适用于党办、财务科、医保办等行政科室",
|
||||
"indicator_count": 6
|
||||
},
|
||||
{
|
||||
"name": "后勤保障科室考核指标",
|
||||
"dept_type": "logistics",
|
||||
"description": "适用于总务科、采购科、基建科",
|
||||
"indicator_count": 6
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user