提交文件
This commit is contained in:
471
.qoder/repowiki/zh/content/数据模型详解/数据模型详解.md
Normal file
471
.qoder/repowiki/zh/content/数据模型详解/数据模型详解.md
Normal file
@@ -0,0 +1,471 @@
|
||||
# 数据模型详解
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [models.py](file://backend/app/models/models.py)
|
||||
- [finance.py](file://backend/app/models/finance.py)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py)
|
||||
- [database.py](file://backend/app/core/database.py)
|
||||
- [config.py](file://backend/app/core/config.py)
|
||||
- [init_db.py](file://backend/init_db.py)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py)
|
||||
- [staff_service.py](file://backend/app/services/staff_service.py)
|
||||
- [indicator_service.py](file://backend/app/services/indicator_service.py)
|
||||
- [001_initial.py](file://backend/alembic/versions/001_initial.py)
|
||||
- [002_template.py](file://backend/alembic/versions/002_template.py)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概览](#架构概览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向医院绩效系统的核心数据模型,系统化阐述 Department、Staff、Assessment、AssessmentDetail、SalaryRecord 等关键实体的设计理念、字段定义、数据类型与约束条件,并深入解析模型间的关系映射、级联操作与数据完整性保障机制。同时,结合服务层业务逻辑,给出数据验证规则、业务规则实现、性能优化策略、模型扩展指南以及版本兼容与迁移策略,帮助开发者与运维人员高效理解与维护该数据模型。
|
||||
|
||||
## 项目结构
|
||||
后端采用 SQLAlchemy ORM + Alembic 迁移的架构,模型集中于 models 模块,配合 Pydantic 的数据模式(schemas)进行输入输出校验;数据库连接通过异步引擎与会话工厂实现;迁移脚本确保数据库结构演进的可控性。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "模型层"
|
||||
M1["models.py<br/>核心业务模型"]
|
||||
M2["finance.py<br/>财务核算模型"]
|
||||
end
|
||||
subgraph "数据模式层"
|
||||
S1["schemas.py<br/>Pydantic模式"]
|
||||
end
|
||||
subgraph "基础设施层"
|
||||
C1["config.py<br/>配置"]
|
||||
D1["database.py<br/>数据库连接"]
|
||||
end
|
||||
subgraph "迁移层"
|
||||
V1["001_initial.py<br/>初始版本"]
|
||||
V2["002_template.py<br/>模板版本"]
|
||||
end
|
||||
subgraph "服务层"
|
||||
A1["assessment_service.py"]
|
||||
S2["salary_service.py"]
|
||||
ST1["staff_service.py"]
|
||||
I1["indicator_service.py"]
|
||||
end
|
||||
M1 --> S1
|
||||
M2 --> S1
|
||||
C1 --> D1
|
||||
V1 --> M1
|
||||
V2 --> M1
|
||||
A1 --> M1
|
||||
S2 --> M1
|
||||
ST1 --> M1
|
||||
I1 --> M1
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [models.py](file://backend/app/models/models.py#L62-L230)
|
||||
- [finance.py](file://backend/app/models/finance.py#L45-L74)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L1-L743)
|
||||
- [database.py](file://backend/app/core/database.py#L9-L39)
|
||||
- [config.py](file://backend/app/core/config.py#L9-L47)
|
||||
- [001_initial.py](file://backend/alembic/versions/001_initial.py#L21-L183)
|
||||
- [002_template.py](file://backend/alembic/versions/002_template.py#L21-L96)
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L1-L438)
|
||||
- [finance.py](file://backend/app/models/finance.py#L1-L79)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L1-L743)
|
||||
- [database.py](file://backend/app/core/database.py#L1-L39)
|
||||
- [config.py](file://backend/app/core/config.py#L1-L47)
|
||||
- [001_initial.py](file://backend/alembic/versions/001_initial.py#L1-L183)
|
||||
- [002_template.py](file://backend/alembic/versions/002_template.py#L1-L96)
|
||||
|
||||
## 核心组件
|
||||
本节聚焦五个关键模型的字段定义、数据类型、约束条件与业务含义。
|
||||
|
||||
- Department(科室信息)
|
||||
- 字段与类型:自增主键、字符串名称与编码(唯一)、枚举类型、层级、排序、启用状态、描述、时间戳
|
||||
- 约束:编码唯一;索引覆盖类型与父级
|
||||
- 关系:自关联父子关系;一对多到 Staff
|
||||
- 业务意义:支撑组织架构与层级管理
|
||||
|
||||
- Staff(员工信息)
|
||||
- 字段与类型:唯一工号、姓名、所属科室外键、职位、职称、联系方式、基本工资、绩效系数、状态、入职日期、时间戳
|
||||
- 约束:工号唯一;索引覆盖科室与状态
|
||||
- 关系:多对一到 Department;一对多到 Assessment、SalaryRecord
|
||||
- 业务意义:员工档案与薪酬基础数据
|
||||
|
||||
- Assessment(考核记录)
|
||||
- 字段与类型:员工外键、考核年月、周期类型、总分、加权得分、状态、考核人/审核人外键、时间戳、备注
|
||||
- 约束:复合索引覆盖员工、年月、状态;级联删除明细
|
||||
- 关系:多对一到 Staff;一对多到 AssessmentDetail
|
||||
- 业务意义:记录单次考核的聚合结果与流转状态
|
||||
|
||||
- AssessmentDetail(考核明细)
|
||||
- 字段与类型:考核记录外键、指标外键、实际值、得分、佐证材料、备注、时间戳
|
||||
- 约束:明细索引覆盖考核与指标
|
||||
- 关系:多对一到 Assessment、Indicator
|
||||
- 业务意义:承载具体指标的得分与证据
|
||||
|
||||
- SalaryRecord(工资核算记录)
|
||||
- 字段与类型:员工外键、年月、基本工资、绩效得分、绩效奖金、扣款、补贴、应发工资、状态、备注、时间戳
|
||||
- 约束:索引覆盖员工与年月
|
||||
- 关系:多对一到 Staff
|
||||
- 业务意义:工资发放依据与统计入口
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L62-L230)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L64-L311)
|
||||
|
||||
## 架构概览
|
||||
数据模型围绕“员工-科室-考核-工资”主线展开,通过外键与关系映射实现强一致的数据完整性;服务层负责业务规则与流程控制,如考核状态机、工资计算与生成、模板导入等。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Department {
|
||||
+int id
|
||||
+string name
|
||||
+string code
|
||||
+enum dept_type
|
||||
+int level
|
||||
+int sort_order
|
||||
+bool is_active
|
||||
+datetime created_at
|
||||
+datetime updated_at
|
||||
+children : Department[]
|
||||
+staff : Staff[]
|
||||
}
|
||||
class Staff {
|
||||
+int id
|
||||
+string employee_id
|
||||
+string name
|
||||
+int department_id
|
||||
+string position
|
||||
+string title
|
||||
+string phone
|
||||
+string email
|
||||
+float base_salary
|
||||
+float performance_ratio
|
||||
+enum status
|
||||
+datetime hire_date
|
||||
+datetime created_at
|
||||
+datetime updated_at
|
||||
+department : Department
|
||||
+assessments : Assessment[]
|
||||
+salary_records : SalaryRecord[]
|
||||
}
|
||||
class Assessment {
|
||||
+int id
|
||||
+int staff_id
|
||||
+int period_year
|
||||
+int period_month
|
||||
+string period_type
|
||||
+float total_score
|
||||
+float weighted_score
|
||||
+enum status
|
||||
+int assessor_id
|
||||
+int reviewer_id
|
||||
+datetime submit_time
|
||||
+datetime review_time
|
||||
+string remark
|
||||
+datetime created_at
|
||||
+datetime updated_at
|
||||
+staff : Staff
|
||||
+assessor : Staff
|
||||
+reviewer : Staff
|
||||
+details : AssessmentDetail[]
|
||||
}
|
||||
class AssessmentDetail {
|
||||
+int id
|
||||
+int assessment_id
|
||||
+int indicator_id
|
||||
+float actual_value
|
||||
+float score
|
||||
+string evidence
|
||||
+string remark
|
||||
+datetime created_at
|
||||
+datetime updated_at
|
||||
+assessment : Assessment
|
||||
+indicator : Indicator
|
||||
}
|
||||
class SalaryRecord {
|
||||
+int id
|
||||
+int staff_id
|
||||
+int period_year
|
||||
+int period_month
|
||||
+float base_salary
|
||||
+float performance_score
|
||||
+float performance_bonus
|
||||
+float deduction
|
||||
+float allowance
|
||||
+float total_salary
|
||||
+string status
|
||||
+string remark
|
||||
+datetime created_at
|
||||
+datetime updated_at
|
||||
+staff : Staff
|
||||
}
|
||||
Department "1" <-- "many" Staff : "外键"
|
||||
Staff "1" <-- "many" Assessment : "外键"
|
||||
Staff "1" <-- "many" SalaryRecord : "外键"
|
||||
Assessment "1" <-- "many" AssessmentDetail : "级联删除"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [models.py](file://backend/app/models/models.py#L62-L230)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Department(科室信息)
|
||||
- 设计要点
|
||||
- 使用自关联实现层级树结构,支持多级科室组织
|
||||
- 通过枚举限定科室类型,便于筛选与模板匹配
|
||||
- 索引提升按类型与父子关系查询效率
|
||||
- 业务规则
|
||||
- 启用/停用控制科室参与统计与流程
|
||||
- 层级与排序用于前端树形展示与权限控制
|
||||
- 外键与关系
|
||||
- Department.parent → Department.children(自关联)
|
||||
- Department.staff → Staff(一对多)
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L62-L86)
|
||||
- [001_initial.py](file://backend/alembic/versions/001_initial.py#L22-L41)
|
||||
|
||||
### Staff(员工信息)
|
||||
- 设计要点
|
||||
- 唯一工号确保跨系统识别一致性
|
||||
- 绩效系数与基本工资构成工资基础
|
||||
- 状态枚举支持在职、休假、离职、退休等生命周期
|
||||
- 业务规则
|
||||
- 仅在职员工参与考核与工资生成
|
||||
- 基本工资与绩效系数影响最终绩效奖金
|
||||
- 外键与关系
|
||||
- Staff.department → Department
|
||||
- Staff.assessments → Assessment
|
||||
- Staff.salary_records → SalaryRecord
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L88-L114)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L107-L149)
|
||||
- [init_db.py](file://backend/init_db.py#L42-L53)
|
||||
|
||||
### Assessment(考核记录)
|
||||
- 设计要点
|
||||
- 年、月、周期类型组合唯一性避免重复
|
||||
- 总分与加权得分分离,加权由明细权重累积
|
||||
- 状态机驱动流程:草稿→提交→审核→确认/驳回
|
||||
- 业务规则
|
||||
- 仅草稿或驳回状态允许修改
|
||||
- 提交后进入审核流程,审核通过方可确认
|
||||
- 外键与关系
|
||||
- Assessment.staff → Staff
|
||||
- Assessment.assessor/reviewer → Staff
|
||||
- Assessment.details → AssessmentDetail(级联删除)
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> 草稿
|
||||
草稿 --> 已提交 : "提交"
|
||||
已提交 --> 已审核 : "审核通过"
|
||||
已提交 --> 已驳回 : "审核驳回"
|
||||
已审核 --> 已确认 : "确认"
|
||||
已确认 --> [*]
|
||||
已驳回 --> 草稿 : "修改后重新提交"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [models.py](file://backend/app/models/models.py#L149-L178)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L159-L205)
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L149-L178)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L79-L262)
|
||||
|
||||
### AssessmentDetail(考核明细)
|
||||
- 设计要点
|
||||
- 明细与指标绑定,支持不同指标的权重与计算
|
||||
- 实际值与得分可独立记录,便于审计与复核
|
||||
- 业务规则
|
||||
- 加权得分来源于指标权重与得分乘积之和
|
||||
- 外键与关系
|
||||
- AssessmentDetail.assessment → Assessment
|
||||
- AssessmentDetail.indicator → Indicator
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L181-L202)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L79-L108)
|
||||
|
||||
### SalaryRecord(工资核算记录)
|
||||
- 设计要点
|
||||
- 应发工资 = 基本工资 + 绩效奖金 + 补贴 - 扣款
|
||||
- 绩效奖金 = 绩效基数 × (绩效得分/100) × 绩效系数
|
||||
- 年月唯一,避免重复发薪
|
||||
- 业务规则
|
||||
- 仅当考核处于“已确认”状态才可生成工资记录
|
||||
- 工资记录状态默认“待处理”,支持后续调整
|
||||
- 外键与关系
|
||||
- SalaryRecord.staff → Staff
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始"]) --> GetAssessment["获取已确认考核记录"]
|
||||
GetAssessment --> Exists{"是否存在?"}
|
||||
Exists --> |否| End(["结束"])
|
||||
Exists --> |是| CalcBonus["计算绩效奖金"]
|
||||
CalcBonus --> SumTotal["计算应发工资"]
|
||||
SumTotal --> CreateRecord["创建工资记录"]
|
||||
CreateRecord --> End
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [models.py](file://backend/app/models/models.py#L205-L230)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L127-L190)
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L205-L230)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L70-L199)
|
||||
|
||||
### 财务核算模型(DepartmentFinance)
|
||||
- 设计要点
|
||||
- 收入/支出两类,按类别细分(检查费、检验费、床位费、材料费、人员支出等)
|
||||
- 金额非负约束,确保财务数据正确性
|
||||
- 按科室与年月索引,支持财务统计
|
||||
- 业务规则
|
||||
- 金额必须≥0
|
||||
- 与科室关联,支持按科室维度的收支结余分析
|
||||
|
||||
**章节来源**
|
||||
- [finance.py](file://backend/app/models/finance.py#L45-L74)
|
||||
|
||||
## 依赖分析
|
||||
- 模型依赖
|
||||
- Assessment 依赖 Staff、AssessmentDetail
|
||||
- AssessmentDetail 依赖 Assessment、Indicator
|
||||
- SalaryRecord 依赖 Staff
|
||||
- Department 依赖 Staff(自关联)
|
||||
- 服务层依赖
|
||||
- AssessmentService 依赖 Assessment、AssessmentDetail、Indicator
|
||||
- SalaryService 依赖 Staff、Assessment、SalaryRecord
|
||||
- 其他服务(StaffService、IndicatorService)分别依赖对应模型
|
||||
- 数据库与配置
|
||||
- 异步引擎与会话工厂统一管理连接与事务
|
||||
- Alembic 迁移脚本确保表结构演进
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A["AssessmentService"] --> AM["Assessment"]
|
||||
A --> ADM["AssessmentDetail"]
|
||||
A --> IM["Indicator"]
|
||||
S["SalaryService"] --> SM["Staff"]
|
||||
S --> AS["Assessment"]
|
||||
S --> SRM["SalaryRecord"]
|
||||
ST["StaffService"] --> STM["Staff"]
|
||||
I["IndicatorService"] --> IM
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L79-L262)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L77-L199)
|
||||
- [staff_service.py](file://backend/app/services/staff_service.py#L16-L112)
|
||||
- [indicator_service.py](file://backend/app/services/indicator_service.py#L16-L197)
|
||||
|
||||
**章节来源**
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L1-L262)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L1-L199)
|
||||
- [staff_service.py](file://backend/app/services/staff_service.py#L1-L112)
|
||||
- [indicator_service.py](file://backend/app/services/indicator_service.py#L1-L197)
|
||||
|
||||
## 性能考虑
|
||||
- 索引策略
|
||||
- 员工:按部门与状态建立索引,加速筛选与分页
|
||||
- 考核:按员工、年月、状态建立复合索引,支持快速定位与统计
|
||||
- 工资:按员工与年月建立索引,提升查询效率
|
||||
- 科室:按类型与父级建立索引,优化树形查询
|
||||
- 查询优化
|
||||
- 使用 selectinload 预加载关联对象,减少 N+1 查询
|
||||
- 分页查询配合 COUNT 子查询,避免全表扫描
|
||||
- 异步与连接池
|
||||
- 异步引擎与连接池配置,提升并发吞吐
|
||||
- 数据类型
|
||||
- 使用 Numeric 精确存储金额与分数,避免浮点误差
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L82-L85)
|
||||
- [models.py](file://backend/app/models/models.py#L111-L114)
|
||||
- [models.py](file://backend/app/models/models.py#L174-L178)
|
||||
- [models.py](file://backend/app/models/models.py#L227-L230)
|
||||
- [config.py](file://backend/app/core/config.py#L18-L22)
|
||||
- [database.py](file://backend/app/core/database.py#L9-L20)
|
||||
|
||||
## 故障排除指南
|
||||
- 常见问题
|
||||
- 无法更新考核:仅草稿或驳回状态允许修改
|
||||
- 无法生成工资:需先完成“已确认”的考核记录
|
||||
- 重复工资:同一年月同员工只允许一条工资记录
|
||||
- 财务异常:金额必须≥0,否则触发约束错误
|
||||
- 排查步骤
|
||||
- 检查 Assessment 状态与时间戳
|
||||
- 核对 Staff 的基本工资与绩效系数
|
||||
- 确认 SalaryRecord 的年月与员工唯一性
|
||||
- 校验 DepartmentFinance 的金额与类别
|
||||
- 日志与调试
|
||||
- 开启数据库回滚与关闭,确保异常时数据一致性
|
||||
- 使用分页与索引优化查询,避免超时
|
||||
|
||||
**章节来源**
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L111-L156)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L127-L190)
|
||||
- [finance.py](file://backend/app/models/finance.py#L73-L74)
|
||||
- [database.py](file://backend/app/core/database.py#L28-L39)
|
||||
|
||||
## 结论
|
||||
本数据模型以清晰的实体边界、严谨的外键关系与完善的索引策略为基础,结合服务层的状态机与计算逻辑,实现了从“员工-科室-考核-工资”的闭环管理。通过 Alembic 迁移与 Pydantic 模式,系统具备良好的可演进性与可维护性。建议在扩展新功能时遵循现有命名规范、索引策略与事务处理模式,确保数据一致性与性能表现。
|
||||
|
||||
## 附录
|
||||
|
||||
### 字段定义与约束对照表
|
||||
- Department
|
||||
- 字段:id、name、code(唯一)、dept_type、parent_id、level、sort_order、is_active、description、created_at、updated_at
|
||||
- 约束:唯一索引(code),普通索引(dept_type、parent_id)
|
||||
- Staff
|
||||
- 字段:id、employee_id(唯一)、name、department_id、position、title、phone、email、base_salary、performance_ratio、status、hire_date、created_at、updated_at
|
||||
- 约束:唯一索引(employee_id),普通索引(department_id、status)
|
||||
- Assessment
|
||||
- 字段:id、staff_id、period_year、period_month、period_type、total_score、weighted_score、status、assessor_id、reviewer_id、submit_time、review_time、remark、created_at、updated_at
|
||||
- 约束:普通索引(staff_id、period_year、period_month、status),级联删除明细
|
||||
- AssessmentDetail
|
||||
- 字段:id、assessment_id、indicator_id、actual_value、score、evidence、remark、created_at、updated_at
|
||||
- 约束:普通索引(assessment_id、indicator_id)
|
||||
- SalaryRecord
|
||||
- 字段:id、staff_id、period_year、period_month、base_salary、performance_score、performance_bonus、deduction、allowance、total_salary、status、remark、created_at、updated_at
|
||||
- 约束:普通索引(staff_id、period_year、period_month)
|
||||
- DepartmentFinance
|
||||
- 字段:id、department_id、period_year、period_month、finance_type、category、amount(≥0)、source、remark、created_at、updated_at
|
||||
- 约束:普通索引(department_id、period_year、period_month、finance_type、category),check(amount ≥ 0)
|
||||
|
||||
**章节来源**
|
||||
- [models.py](file://backend/app/models/models.py#L62-L230)
|
||||
- [finance.py](file://backend/app/models/finance.py#L45-L74)
|
||||
|
||||
### 版本兼容与迁移策略
|
||||
- 初始版本(001_initial.py)
|
||||
- 创建 departments、staff、indicators、assessments、assessment_details、salary_records、users 表
|
||||
- 建立基础索引与外键约束
|
||||
- 模板版本(002_template.py)
|
||||
- 新增 indicator_templates、template_indicators 表
|
||||
- 为 indicators 表动态添加 BSC 维度、目标单位、考核方法、扣分标准、数据来源、适用科室类型、是否 veto 等列
|
||||
- 迁移建议
|
||||
- 新增字段采用条件判断(如字段存在性检查),避免重复执行报错
|
||||
- 对历史数据进行补全(如适用科室类型 JSON 数组),确保业务可用
|
||||
- 升级前备份数据库,升级后验证索引与约束生效
|
||||
|
||||
**章节来源**
|
||||
- [001_initial.py](file://backend/alembic/versions/001_initial.py#L21-L183)
|
||||
- [002_template.py](file://backend/alembic/versions/002_template.py#L21-L96)
|
||||
Reference in New Issue
Block a user