242 lines
8.1 KiB
Python
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
|
|
}
|