提交文件
This commit is contained in:
448
.qoder/repowiki/zh/content/后端开发指南/服务层开发/统计分析服务.md
Normal file
448
.qoder/repowiki/zh/content/后端开发指南/服务层开发/统计分析服务.md
Normal file
@@ -0,0 +1,448 @@
|
||||
# 统计分析服务
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py)
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py)
|
||||
- [backend/app/core/database.py](file://backend/app/core/database.py)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py)
|
||||
- [backend/app/main.py](file://backend/app/main.py)
|
||||
- [backend/app/api/v1/__init__.py](file://backend/app/api/v1/__init__.py)
|
||||
- [docs/详细设计.md](file://docs/详细设计.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向“统计分析服务”的开发与使用,围绕 StatsService 类的实现原理展开,系统阐述多维度统计分析、数据聚合与报表生成能力,重点覆盖以下主题:
|
||||
- BSC(平衡计分卡)维度分析:财务、客户、内部流程、学习与成长四个维度的指标计算与聚合
|
||||
- 科室绩效统计:按科室汇总、平均分、最高/最低分、人员列表与排序
|
||||
- 趋势分析:按月度的时间序列趋势(平均分、加权分)
|
||||
- 排名统计:按加权分的绩效排名
|
||||
- 指标完成度:指标平均分、最大/最小分、完成率
|
||||
- 数据库交互模式、查询优化与潜在缓存策略
|
||||
- 统计结果的数据格式化、图表数据准备与 API 接口设计
|
||||
- 具体统计场景示例与性能考虑
|
||||
|
||||
## 项目结构
|
||||
后端采用 FastAPI + SQLAlchemy 2.x 异步 ORM 的架构,统计分析服务位于服务层,API 层负责请求参数解析与响应封装,模型层定义数据结构与枚举,数据库层提供异步连接与会话管理。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "应用层"
|
||||
API["API 路由<br/>stats.py"]
|
||||
SVC["服务层<br/>stats_service.py"]
|
||||
end
|
||||
subgraph "模型层"
|
||||
MODELS["数据模型与枚举<br/>models.py"]
|
||||
end
|
||||
subgraph "基础设施"
|
||||
CFG["配置<br/>config.py"]
|
||||
DB["数据库连接<br/>database.py"]
|
||||
MAIN["应用入口<br/>main.py"]
|
||||
end
|
||||
API --> SVC
|
||||
SVC --> MODELS
|
||||
API --> DB
|
||||
SVC --> DB
|
||||
DB --> CFG
|
||||
MAIN --> API
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L1-L242)
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L1-L300)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L1-L438)
|
||||
- [backend/app/core/database.py](file://backend/app/core/database.py#L1-L39)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L1-L47)
|
||||
- [backend/app/main.py](file://backend/app/main.py#L1-L92)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L1-L242)
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L1-L300)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L1-L438)
|
||||
- [backend/app/core/database.py](file://backend/app/core/database.py#L1-L39)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L1-L47)
|
||||
- [backend/app/main.py](file://backend/app/main.py#L1-L92)
|
||||
|
||||
## 核心组件
|
||||
- StatsService:提供 BSC 维度统计、科室统计、趋势分析、排名、指标完成度等统计方法
|
||||
- API 路由 stats.py:定义 /stats 前缀下的统计接口,负责参数校验、默认值处理与统一响应包装
|
||||
- 数据模型与枚举:包含 BSC 维度、评估状态、科室类型、指标类型等,支撑统计逻辑
|
||||
- 数据库与配置:异步连接、会话工厂、数据库 URL 与池参数
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L16-L300)
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L1-L242)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L29-L52)
|
||||
|
||||
## 架构总览
|
||||
统计分析服务遵循“API → 服务 → 模型/数据库”的分层架构。API 层负责输入参数与响应格式标准化;服务层执行复杂聚合与计算;模型层提供数据结构与枚举;数据库层提供异步连接与事务管理。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant API as "API(stats.py)"
|
||||
participant Svc as "StatsService"
|
||||
participant DB as "AsyncSession"
|
||||
participant Model as "ORM模型"
|
||||
Client->>API : GET /api/v1/stats/bsc-dimension
|
||||
API->>API : 参数校验与默认值处理
|
||||
API->>Svc : 调用 get_bsc_dimension_stats(...)
|
||||
Svc->>DB : 异步查询SQLAlchemy select + func
|
||||
DB->>Model : 映射到 Assessment/AssessmentDetail/Indicator/Department/Staff
|
||||
Svc-->>API : 返回聚合结果
|
||||
API-->>Client : 统一响应 {code,message,data}
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L17-L33)
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L19-L72)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L117-L181)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### StatsService 类与方法族
|
||||
- get_bsc_dimension_stats:按 BSC 四维度聚合得分、权重与指标数量,计算平均分
|
||||
- get_department_stats:按科室汇总人员、总分、平均分、最高/最低分与人员列表,并整体排序
|
||||
- get_trend_stats:按月度聚合平均分与加权分,支持跨年范围与科室过滤
|
||||
- get_ranking_stats:按加权分排名前 N 的员工
|
||||
- get_completion_stats:按指标统计平均分、最大/最小分、完成率与样本数
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class StatsService {
|
||||
+get_bsc_dimension_stats(db, department_id, period_year, period_month) Dict
|
||||
+get_department_stats(db, period_year, period_month) List
|
||||
+get_trend_stats(db, department_id, period_year, months) List
|
||||
+get_ranking_stats(db, period_year, period_month, limit) List
|
||||
+get_completion_stats(db, indicator_id, period_year, period_month) Dict
|
||||
}
|
||||
class Assessment {
|
||||
+int id
|
||||
+int staff_id
|
||||
+int period_year
|
||||
+int period_month
|
||||
+float total_score
|
||||
+float weighted_score
|
||||
+AssessmentStatus status
|
||||
}
|
||||
class AssessmentDetail {
|
||||
+int id
|
||||
+int assessment_id
|
||||
+int indicator_id
|
||||
+float actual_value
|
||||
+float score
|
||||
}
|
||||
class Indicator {
|
||||
+int id
|
||||
+string name
|
||||
+string code
|
||||
+IndicatorType indicator_type
|
||||
+BSCDimension bs_dimension
|
||||
+float weight
|
||||
+float max_score
|
||||
+float target_value
|
||||
}
|
||||
class Department {
|
||||
+int id
|
||||
+string name
|
||||
+string code
|
||||
+DeptType dept_type
|
||||
}
|
||||
class Staff {
|
||||
+int id
|
||||
+string employee_id
|
||||
+string name
|
||||
+int department_id
|
||||
}
|
||||
StatsService --> Assessment : "查询"
|
||||
StatsService --> AssessmentDetail : "连接"
|
||||
StatsService --> Indicator : "按维度聚合"
|
||||
StatsService --> Department : "科室汇总"
|
||||
StatsService --> Staff : "关联人员"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L16-L300)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L117-L181)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L19-L299)
|
||||
|
||||
#### BSC 维度分析(get_bsc_dimension_stats)
|
||||
- 输入:可选科室 ID、年、月
|
||||
- 过滤:仅统计已确认的考核记录
|
||||
- 聚合:按 BSC 维度分组,计算总分(加权)、总权重、指标数量与平均分
|
||||
- 输出:包含各维度的得分、权重、指标数与平均分,以及统计周期
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入 get_bsc_dimension_stats"]) --> BuildCond["构建查询条件<br/>状态=FINALIZED(+年+月+科室)"]
|
||||
BuildCond --> ExecSel["执行聚合查询<br/>按维度分组(sum(score*weight), sum(weight), count)"]
|
||||
ExecSel --> Iterate["遍历结果<br/>填充维度字典"]
|
||||
Iterate --> CalcAvg["计算平均分=总分/总权重"]
|
||||
CalcAvg --> Ret["返回 {dimensions, period}"]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L19-L72)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L19-L72)
|
||||
|
||||
#### 科室绩效统计(get_department_stats)
|
||||
- 输入:年、月
|
||||
- 过滤:仅统计已确认的考核记录
|
||||
- 聚合:按科室汇总人员数、总分、平均分、最高/最低分,并收集人员得分列表
|
||||
- 排序:按平均分降序
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S(["进入 get_department_stats"]) --> Q["查询关联数据<br/>Staff→Assessment→Department"]
|
||||
Q --> Group["按科室分组聚合<br/>计数/求和/记录人员列表"]
|
||||
Group --> Compute["计算平均分=总分/人数"]
|
||||
Compute --> Sort["按平均分降序排序"]
|
||||
Sort --> R(["返回科室统计列表"])
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L74-L146)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L74-L146)
|
||||
|
||||
#### 趋势分析(get_trend_stats)
|
||||
- 输入:可选科室 ID、年(为空则使用当前年)、月份数(默认 6)
|
||||
- 范围:若未指定年份,按当前年份与最近 N 个月推导起止月份,支持跨年
|
||||
- 聚合:按月度 group by,计算平均分与加权分、样本数
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Enter(["进入 get_trend_stats"]) --> YearCheck{"是否指定年份?"}
|
||||
YearCheck -- 否 --> SetCur["设置为当前年份"]
|
||||
YearCheck -- 是 --> KeepYear["使用传入年份"]
|
||||
SetCur --> Range["计算起始月=当前月-N+1<br/>处理跨年"]
|
||||
KeepYear --> Range
|
||||
Range --> Cond["构造月份范围条件"]
|
||||
Cond --> Join["连接 Staff 并过滤 FINALIZED"]
|
||||
Join --> GroupBy["按月分组聚合"]
|
||||
GroupBy --> Out(["返回月度趋势列表"])
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L148-L199)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L148-L199)
|
||||
|
||||
#### 排名统计(get_ranking_stats)
|
||||
- 输入:年、月、限制条数
|
||||
- 过滤:仅统计已确认的考核记录
|
||||
- 排序:按加权分降序,返回前 N 条并标注排名
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant API as "API"
|
||||
participant Svc as "StatsService"
|
||||
participant DB as "AsyncSession"
|
||||
API->>Svc : get_ranking_stats(year, month, limit)
|
||||
Svc->>DB : select Staff/Assessment/Department
|
||||
DB-->>Svc : 结果集
|
||||
Svc-->>API : 按加权分降序,标注 rank
|
||||
API-->>API : 统一响应
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L201-L244)
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L210-L224)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L201-L244)
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L210-L224)
|
||||
|
||||
#### 指标完成度(get_completion_stats)
|
||||
- 输入:可选指标 ID、年、月
|
||||
- 过滤:仅统计已确认的考核记录
|
||||
- 聚合:按指标 group by,计算平均分、最大/最小分、样本数与完成率(平均分/目标值)
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
In(["进入 get_completion_stats"]) --> Cond["构造条件<br/>FINALIZED(+年+月+指标ID?)"]
|
||||
Cond --> Sel["select 指标字段 + avg/max/min/count"]
|
||||
Sel --> Group["group by 指标"]
|
||||
Group --> Rate["完成率=avg/max(target_value)"]
|
||||
Rate --> Ret(["返回指标完成度列表"])
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L246-L299)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L246-L299)
|
||||
|
||||
### API 接口设计与数据格式
|
||||
- 统一响应结构:包含 code、message、data 字段
|
||||
- 参数校验与默认值:
|
||||
- 年/月未传时,趋势与周期统计接口会使用当前年/月
|
||||
- 排名与周期统计支持 limit 控制返回数量
|
||||
- 接口一览:
|
||||
- GET /stats/bsc-dimension:BSC 维度分析
|
||||
- GET /stats/department:科室绩效统计
|
||||
- GET /stats/trend:趋势分析(月度)
|
||||
- GET /stats/department-ranking:科室绩效排名(前 N)
|
||||
- GET /stats/ranking:个人绩效排名(前 N)
|
||||
- GET /stats/completion:指标完成度
|
||||
- GET /stats/period:周期统计(含汇总)
|
||||
- GET /stats/alerts、/stats/kpi-gauges、/stats/finance-trend:预留接口(当前返回模拟数据)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Router as "FastAPI 路由"
|
||||
participant Handler as "stats.py 处理函数"
|
||||
participant Svc as "StatsService"
|
||||
participant DB as "AsyncSession"
|
||||
Client->>Router : GET /api/v1/stats/bsc-dimension?year&month&dept_id
|
||||
Router->>Handler : 参数解析与默认值
|
||||
Handler->>Svc : 调用对应统计方法
|
||||
Svc->>DB : 异步查询
|
||||
DB-->>Svc : 结果
|
||||
Svc-->>Handler : 聚合结果
|
||||
Handler-->>Client : {code,message,data}
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L17-L242)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L17-L242)
|
||||
|
||||
### 数据模型与枚举(支撑统计)
|
||||
- BSCDimension:financial、customer、internal_process、learning_growth
|
||||
- AssessmentStatus:FINALIZED 等
|
||||
- DeptType、IndicatorType 等枚举用于过滤与分类
|
||||
- 关键实体:Assessment、AssessmentDetail、Indicator、Department、Staff
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class BSCDimension {
|
||||
<<enum>>
|
||||
+FINANCIAL
|
||||
+CUSTOMER
|
||||
+INTERNAL_PROCESS
|
||||
+LEARNING_GROWTH
|
||||
}
|
||||
class AssessmentStatus {
|
||||
<<enum>>
|
||||
+FINALIZED
|
||||
}
|
||||
class DeptType {
|
||||
<<enum>>
|
||||
+CLINICAL_SURGICAL
|
||||
+...
|
||||
}
|
||||
class IndicatorType {
|
||||
<<enum>>
|
||||
+QUALITY
|
||||
+QUANTITY
|
||||
+EFFICIENCY
|
||||
+SERVICE
|
||||
+COST
|
||||
}
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L29-L61)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L29-L61)
|
||||
|
||||
## 依赖分析
|
||||
- 统计服务依赖 SQLAlchemy 异步会话与 ORM 模型,通过 select + func 实现聚合
|
||||
- API 层依赖服务层与数据库会话注入
|
||||
- 配置层提供数据库连接参数与池大小,影响并发与吞吐
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
API["api/v1/stats.py"] --> SVC["services/stats_service.py"]
|
||||
SVC --> MODELS["models/models.py"]
|
||||
API --> DB["core/database.py"]
|
||||
SVC --> DB
|
||||
DB --> CFG["core/config.py"]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L1-L242)
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L1-L300)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L1-L438)
|
||||
- [backend/app/core/database.py](file://backend/app/core/database.py#L1-L39)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L1-L47)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L1-L242)
|
||||
- [backend/app/services/stats_service.py](file://backend/app/services/stats_service.py#L1-L300)
|
||||
- [backend/app/core/database.py](file://backend/app/core/database.py#L1-L39)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L1-L47)
|
||||
|
||||
## 性能考量
|
||||
- 查询优化
|
||||
- 使用 group by 与聚合函数(sum、avg、count)减少应用侧循环计算
|
||||
- 通过索引字段过滤(Assessment.status、Assessment.period_year/month、Assessment.staff_id)降低扫描范围
|
||||
- 趋势分析中按月分组,避免大结果集内存占用
|
||||
- 数据库连接与并发
|
||||
- 异步连接与会话工厂支持高并发;数据库池参数可在配置中调优
|
||||
- 缓存策略(建议)
|
||||
- 对高频但不频繁变化的统计结果(如 BSC 维度、指标完成度)引入短期缓存(如 Redis)
|
||||
- 按参数组合生成缓存键(年、月、科室、指标等)
|
||||
- 响应格式化
|
||||
- 将数值统一为浮点并限制精度,便于前端图表渲染
|
||||
- 提供图表友好的数组结构(时间序列、排名列表)
|
||||
|
||||
[本节为通用性能指导,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 常见问题
|
||||
- 参数缺失:年/月未传导致默认值逻辑异常,检查 API 层默认值处理
|
||||
- 权限与认证:确保请求携带有效 Token
|
||||
- 数据缺失:仅统计已确认的考核记录,若无数据请检查 Assessment.status
|
||||
- 日志与异常
|
||||
- 应用层已注册全局异常处理器,便于定位错误
|
||||
- 建议在服务层增加关键步骤的日志输出(如查询条件、聚合结果规模)
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/main.py](file://backend/app/main.py#L58-L75)
|
||||
- [backend/app/api/v1/stats.py](file://backend/app/api/v1/stats.py#L52-L70)
|
||||
|
||||
## 结论
|
||||
统计分析服务以 StatsService 为核心,围绕 BSC 四维度、科室统计、趋势分析、排名与指标完成度构建了完整的多维统计能力。通过 SQLAlchemy 异步 ORM 与合理的查询策略,实现了高效的数据聚合与报表生成。建议在生产环境中引入缓存与更细粒度的索引优化,并持续完善财务、预警与仪表盘等预留接口的实际数据来源。
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
|
||||
## 附录
|
||||
|
||||
### 统计场景示例
|
||||
- BSC 维度分析:按月查看财务、客户、内部流程、学习与成长四个维度的加权得分与平均分
|
||||
- 科室绩效:按月汇总各科室平均分、最高/最低分与人员列表,用于科室排名与改进
|
||||
- 趋势分析:查看近 6 个月的平均分与加权分变化,识别波动与改善趋势
|
||||
- 排名统计:查看个人绩效排名前 10 的员工及其所在科室
|
||||
- 指标完成度:查看各指标的平均分、完成率与样本数,辅助指标优化
|
||||
|
||||
[本节为概念性场景说明,不直接分析具体文件]
|
||||
|
||||
### 与系统设计文档的对应关系
|
||||
- 系统设计强调“多维度考核”“科学量化”“流程自动化”“报表与分析中心”,统计分析服务正对应“报表与分析中心”的实现。
|
||||
|
||||
**章节来源**
|
||||
- [docs/详细设计.md](file://docs/详细设计.md#L155-L164)
|
||||
Reference in New Issue
Block a user