Files
2026-02-28 15:06:52 +08:00

242 lines
8.1 KiB
Python

"""
统计报表 API
"""
from typing import Optional
from datetime import datetime
from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
from app.core.security import get_current_active_user
from app.models.models import User
from app.services.stats_service import StatsService
router = APIRouter(prefix="/stats", tags=["统计报表"])
@router.get("/bsc-dimension", summary="BSC 维度分析")
async def get_bsc_dimension_stats(
department_id: Optional[int] = Query(None, description="科室 ID"),
period_year: int = Query(..., description="年度"),
period_month: int = Query(..., description="月份"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取 BSC 四个维度的统计分析"""
result = await StatsService.get_bsc_dimension_stats(
db, department_id, period_year, period_month
)
return {
"code": 200,
"message": "success",
"data": result
}
@router.get("/department", summary="科室绩效统计")
async def get_department_stats(
period_year: int = Query(..., description="年度"),
period_month: int = Query(..., description="月份"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取各科室绩效统计"""
result = await StatsService.get_department_stats(db, period_year, period_month)
return {
"code": 200,
"message": "success",
"data": result
}
@router.get("/trend", summary="趋势分析")
async def get_trend_stats(
department_id: Optional[int] = Query(None, description="科室 ID"),
period_year: Optional[int] = Query(None, description="年度"),
months: Optional[int] = Query(6, ge=1, le=24, description="最近几个月"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取绩效趋势分析(月度)"""
# 如果没有指定年份,使用当前年份
if not period_year:
period_year = datetime.now().year
result = await StatsService.get_trend_stats(db, department_id, period_year, months)
return {
"code": 200,
"message": "success",
"data": result
}
@router.get("/alerts", summary="预警数据")
async def get_alerts(
limit: Optional[int] = Query(10, ge=1, le=100, description="返回数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取预警数据(考核到期、工资未发等)"""
# TODO: 从数据库实际查询预警数据
# 目前返回模拟数据用于演示
return {
"code": 200,
"message": "success",
"data": {
"lowScoreStaff": [], # 低分员工
"incompleteDepartments": [], # 未完成考核科室
"anomalyData": [] # 异常数据
}
}
@router.get("/period", summary="周期统计")
async def get_period_stats(
period_year: Optional[int] = Query(None, description="年度"),
period_month: Optional[int] = Query(None, description="月份"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取周期统计数据"""
# 如果没有指定年月,使用当前年月
if not period_year:
period_year = datetime.now().year
if not period_month:
period_month = datetime.now().month
# 获取该周期的考核统计
result = await StatsService.get_department_stats(db, period_year, period_month)
# 计算汇总数据
total_departments = len(result)
total_staff = sum(dept.get('staff_count', 0) for dept in result)
avg_score = sum(dept.get('avg_score', 0) for dept in result) / total_departments if total_departments > 0 else 0
return {
"code": 200,
"message": "success",
"data": {
"period": f"{period_year}{period_month}",
"total_departments": total_departments,
"total_staff": total_staff,
"avg_score": round(avg_score, 2),
"departments": result
}
}
@router.get("/kpi-gauges", summary="关键指标仪表盘")
async def get_kpi_gauges(
period_year: Optional[int] = Query(None, description="年度"),
period_month: Optional[int] = Query(None, description="月份"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取关键指标仪表盘数据"""
# 如果没有指定年月,使用当前年月
if not period_year:
period_year = datetime.now().year
if not period_month:
period_month = datetime.now().month
# TODO: 从数据库实际计算这些指标
# 目前返回模拟数据用于演示
return {
"code": 200,
"message": "success",
"data": {
"bed_usage_rate": 85.5, # 床位使用率 (%)
"drug_ratio": 32.8, # 药占比 (%)
"material_ratio": 18.5, # 材料占比 (%)
"satisfaction_rate": 92.3 # 患者满意度 (%)
}
}
@router.get("/finance-trend", summary="收支趋势")
async def get_finance_trend(
months: Optional[int] = Query(6, ge=1, le=24, description="最近几个月"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取收支趋势数据"""
# TODO: 从数据库实际查询收支数据
# 目前返回模拟数据用于演示
from datetime import datetime
current_month = datetime.now().month
data = []
for i in range(months, 0, -1):
month = current_month - i + 1
if month < 1:
month += 12
data.append({
"period": f"{month}",
"income": 1000000 + (months - i) * 50000,
"expense": 800000 + (months - i) * 30000,
"profit": 200000 + (months - i) * 20000
})
return {
"code": 200,
"message": "success",
"data": data
}
@router.get("/department-ranking", summary="科室绩效排名")
async def get_department_ranking(
period_year: Optional[int] = Query(None, description="年度"),
period_month: Optional[int] = Query(None, description="月份"),
limit: Optional[int] = Query(10, ge=1, le=100, description="返回数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取科室绩效排名"""
# 如果没有指定年月,使用当前年月
if not period_year:
period_year = datetime.now().year
if not period_month:
period_month = datetime.now().month
result = await StatsService.get_department_stats(db, period_year, period_month)
# 返回前 limit 个
return {
"code": 200,
"message": "success",
"data": result[:limit] if limit else result
}
@router.get("/ranking", summary="绩效排名")
async def get_ranking_stats(
period_year: int = Query(..., description="年度"),
period_month: int = Query(..., description="月份"),
limit: int = Query(10, ge=1, le=100, description="返回数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取绩效排名前 N 名"""
result = await StatsService.get_ranking_stats(db, period_year, period_month, limit)
return {
"code": 200,
"message": "success",
"data": result
}
@router.get("/completion", summary="指标完成度")
async def get_completion_stats(
indicator_id: Optional[int] = Query(None, description="指标 ID"),
period_year: int = Query(..., description="年度"),
period_month: int = Query(..., description="月份"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取指标完成度统计"""
result = await StatsService.get_completion_stats(db, indicator_id, period_year, period_month)
return {
"code": 200,
"message": "success",
"data": result
}