提交文件
This commit is contained in:
349
.qoder/repowiki/zh/content/业务逻辑设计/工资计算算法.md
Normal file
349
.qoder/repowiki/zh/content/业务逻辑设计/工资计算算法.md
Normal file
@@ -0,0 +1,349 @@
|
||||
# 工资计算算法
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py)
|
||||
- [salary.py](file://backend/app/api/v1/salary.py)
|
||||
- [models.py](file://backend/app/models/models.py)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py)
|
||||
- [assessments.py](file://backend/app/api/v1/assessments.py)
|
||||
- [finance.py](file://backend/app/models/finance.py)
|
||||
- [database.md](file://docs/database.md)
|
||||
- [详细设计.md](file://docs/详细设计.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向医院绩效系统的工资计算算法,系统性阐述绩效奖金计算公式、工资构成要素与计算逻辑,解释基础工资、绩效系数、考核得分权重的计算方法,覆盖不同岗位类型的差异、特殊津贴与扣款处理,以及批量工资生成的算法实现、并发处理与数据一致性保障。同时提供计算规则的配置方式、扩展点与性能优化策略,帮助读者在理解现有实现的基础上进行定制与演进。
|
||||
|
||||
## 项目结构
|
||||
后端采用FastAPI + SQLAlchemy异步ORM,服务层负责业务逻辑,API层提供REST接口,模型层定义数据库表结构与关系,Schema层定义请求/响应数据结构。工资计算相关的核心文件如下:
|
||||
- 服务层:salary_service.py(工资计算与生成)、assessment_service.py(考核计算)
|
||||
- API层:salary.py(工资接口)、assessments.py(考核接口)
|
||||
- 模型层:models.py(实体与关系)、finance.py(财务核算模型)
|
||||
- Schema层:schemas.py(数据模式)
|
||||
- 文档:database.md(数据库设计)、详细设计.md(系统设计)
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "API层"
|
||||
A1["salary.py"]
|
||||
A2["assessments.py"]
|
||||
end
|
||||
subgraph "服务层"
|
||||
S1["salary_service.py"]
|
||||
S2["assessment_service.py"]
|
||||
end
|
||||
subgraph "模型层"
|
||||
M1["models.py"]
|
||||
M2["finance.py"]
|
||||
end
|
||||
subgraph "Schema层"
|
||||
SC["schemas.py"]
|
||||
end
|
||||
subgraph "文档"
|
||||
D1["database.md"]
|
||||
D2["详细设计.md"]
|
||||
end
|
||||
A1 --> S1
|
||||
A2 --> S2
|
||||
S1 --> M1
|
||||
S2 --> M1
|
||||
S1 --> SC
|
||||
S2 --> SC
|
||||
M1 --> D1
|
||||
D2 --> D1
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [salary.py](file://backend/app/api/v1/salary.py#L1-L156)
|
||||
- [assessments.py](file://backend/app/api/v1/assessments.py#L1-L166)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L1-L260)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [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.md](file://docs/database.md#L1-L216)
|
||||
- [详细设计.md](file://docs/详细设计.md#L1-L196)
|
||||
|
||||
章节来源
|
||||
- [salary.py](file://backend/app/api/v1/salary.py#L1-L156)
|
||||
- [assessments.py](file://backend/app/api/v1/assessments.py#L1-L166)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L1-L260)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [models.py](file://backend/app/models/models.py#L1-L438)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L1-L743)
|
||||
- [finance.py](file://backend/app/models/finance.py#L1-L79)
|
||||
- [database.md](file://docs/database.md#L1-L216)
|
||||
- [详细设计.md](file://docs/详细设计.md#L1-L196)
|
||||
|
||||
## 核心组件
|
||||
- 工资服务(SalaryService):提供工资记录查询、创建、更新、生成、批量生成、确认与批量确认等能力;核心计算函数为绩效奖金计算。
|
||||
- 考核服务(AssessmentService):提供考核记录的创建、更新、提交、审核、确认与批量创建等能力;核心计算为总分与加权得分。
|
||||
- 数据模型(models.py):定义员工、考核、工资记录等实体及其字段与关系。
|
||||
- 数据模式(schemas.py):定义API请求/响应的数据结构。
|
||||
- 财务模型(finance.py):定义科室财务收支记录,用于财务核算与对账。
|
||||
|
||||
章节来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L14-L260)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L14-L263)
|
||||
- [models.py](file://backend/app/models/models.py#L88-L231)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L272-L311)
|
||||
- [finance.py](file://backend/app/models/finance.py#L45-L79)
|
||||
|
||||
## 架构总览
|
||||
工资计算遵循“先考核、后工资”的流程:考核服务计算加权得分,工资服务据此生成工资记录。系统通过API层暴露查询、生成、确认等接口,服务层封装业务规则,模型层承载数据与关系。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as "用户"
|
||||
participant API as "API层(salary.py)"
|
||||
participant SVC as "服务层(SalaryService)"
|
||||
participant ASVC as "服务层(AssessmentService)"
|
||||
participant DB as "数据库(models.py)"
|
||||
U->>API : "POST /salary/generate"
|
||||
API->>SVC : "generate_from_assessment(staff_id, year, month)"
|
||||
SVC->>DB : "查询员工信息(Staff)"
|
||||
SVC->>DB : "查询已确认考核(Assessment.status=FINALIZED)"
|
||||
SVC->>SVC : "calculate_performance_bonus(weighted_score, performance_ratio)"
|
||||
SVC->>DB : "插入SalaryRecord"
|
||||
SVC-->>API : "返回工资记录ID"
|
||||
API-->>U : "生成成功"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [salary.py](file://backend/app/api/v1/salary.py#L96-L110)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L127-L190)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L195-L205)
|
||||
- [models.py](file://backend/app/models/models.py#L88-L231)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 绩效奖金计算公式与工资构成
|
||||
- 绩效奖金计算
|
||||
- 公式:绩效奖金 = 绩效基数 × (绩效得分/100) × 绩效系数
|
||||
- 绩效基数:固定常量,可在服务层中配置与调整
|
||||
- 绩效得分:来自考核的加权得分
|
||||
- 绩效系数:来自员工表的performance_ratio
|
||||
- 工资构成要素
|
||||
- 基本工资:来自员工表base_salary
|
||||
- 绩效奖金:按上述公式计算
|
||||
- 补贴:允许在工资记录中单独维护
|
||||
- 扣款:允许在工资记录中单独维护
|
||||
- 应发工资:基本工资 + 绩效奖金 + 补贴 - 扣款
|
||||
- 状态流转
|
||||
- 工资记录默认状态为“待确认”,确认后进入“已确认”状态
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始"]) --> LoadStaff["加载员工信息"]
|
||||
LoadStaff --> LoadAssess["加载已确认考核"]
|
||||
LoadAssess --> CheckDup{"是否存在同周期工资记录?"}
|
||||
CheckDup --> |是| Abort["终止生成"]
|
||||
CheckDup --> |否| CalcBonus["计算绩效奖金<br/>= 基数 × (得分/100) × 系数"]
|
||||
CalcBonus --> ComputeTotal["计算应发工资<br/>= 基本工资 + 奖金 + 补贴 - 扣款"]
|
||||
ComputeTotal --> CreateRec["创建工资记录(状态: 待确认)"]
|
||||
CreateRec --> End(["结束"])
|
||||
Abort --> End
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L127-L190)
|
||||
- [models.py](file://backend/app/models/models.py#L205-L231)
|
||||
|
||||
章节来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L17-L18)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L71-L74)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L173-L174)
|
||||
- [models.py](file://backend/app/models/models.py#L205-L231)
|
||||
|
||||
### 考核得分权重与加权计算
|
||||
- 总分:明细得分累加
|
||||
- 加权得分:明细得分 × 指标权重累加
|
||||
- 考核状态:草稿 → 提交 → 审核 → 确认(FINALIZED)
|
||||
- 生成工资时要求考核状态为“已确认”,避免未完成流程的误算
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["创建考核"] --> B["计算总分=sum(明细.score)"]
|
||||
B --> C["计算加权得分=Σ(明细.score × 指标权重)"]
|
||||
C --> D["提交/审核/确认"]
|
||||
D --> E{"状态=FINALIZED?"}
|
||||
E --> |是| F["可用于生成工资"]
|
||||
E --> |否| G["不可生成工资"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L71-L108)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L195-L205)
|
||||
|
||||
章节来源
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L71-L108)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L195-L205)
|
||||
|
||||
### 不同岗位类型的工资差异
|
||||
- 基础差异体现在两个字段:
|
||||
- 基本工资(base_salary):由员工信息决定
|
||||
- 绩效系数(performance_ratio):由员工信息决定
|
||||
- 系统未内置“岗位类型”字段,因此不同岗位的差异通过上述两字段配置体现。若需引入岗位类型,可在模型层新增字段并在服务层扩展计算逻辑。
|
||||
|
||||
章节来源
|
||||
- [models.py](file://backend/app/models/models.py#L88-L114)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L107-L118)
|
||||
|
||||
### 特殊津贴与扣款处理
|
||||
- 特殊津贴与扣款通过工资记录的allowance与deduction字段维护,支持在创建与更新时单独设置。
|
||||
- 应发工资为基本工资、绩效奖金、补贴与扣款的组合,计算逻辑在服务层统一处理。
|
||||
|
||||
章节来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L77-L124)
|
||||
- [models.py](file://backend/app/models/models.py#L205-L231)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L274-L311)
|
||||
|
||||
### 批量工资生成与并发处理
|
||||
- 单次生成:根据员工ID与周期生成单条工资记录
|
||||
- 科室批量生成:遍历该科室已确认考核的员工,逐条生成工资记录
|
||||
- 并发与一致性:
|
||||
- 生成前检查是否存在同周期工资记录,避免重复
|
||||
- 使用数据库事务与flush/refresh确保写入一致性
|
||||
- 批量生成时逐条生成,避免跨事务的复杂锁竞争
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant API as "API层(salary.py)"
|
||||
participant SVC as "服务层(SalaryService)"
|
||||
participant DB as "数据库(models.py)"
|
||||
API->>SVC : "batch_generate_for_department(dept_id, year, month)"
|
||||
SVC->>DB : "查询该科室已确认考核的员工"
|
||||
loop 遍历每个员工
|
||||
SVC->>SVC : "generate_from_assessment(staff_id, year, month)"
|
||||
SVC->>DB : "检查同周期是否存在工资记录"
|
||||
alt 存在则跳过
|
||||
SVC-->>SVC : "跳过"
|
||||
else 不存在则生成
|
||||
SVC->>DB : "插入SalaryRecord"
|
||||
end
|
||||
end
|
||||
SVC-->>API : "返回生成的记录列表"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [salary.py](file://backend/app/api/v1/salary.py#L113-L129)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L193-L219)
|
||||
|
||||
章节来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L193-L219)
|
||||
- [salary.py](file://backend/app/api/v1/salary.py#L113-L129)
|
||||
|
||||
### 数据一致性与状态管理
|
||||
- 工资记录状态:pending(待确认)→ confirmed(已确认)
|
||||
- 考核记录状态:draft → submitted → reviewed → finalized
|
||||
- 生成工资时仅接受finalized状态的考核,确保数据一致性
|
||||
- 批量确认接口支持按周期与科室范围批量更新状态
|
||||
|
||||
章节来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L222-L259)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L158-L205)
|
||||
|
||||
### 计算规则配置与扩展点
|
||||
- 绩效基数:可通过修改服务层常量进行配置
|
||||
- 绩效系数:通过员工信息维护
|
||||
- 加权计算方法:在考核服务中实现,可扩展为更复杂的权重聚合
|
||||
- 工资构成扩展:可在Schema与模型中增加新的字段,并在服务层扩展计算逻辑
|
||||
|
||||
章节来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L17-L18)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L71-L108)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L274-L311)
|
||||
- [models.py](file://backend/app/models/models.py#L205-L231)
|
||||
|
||||
## 依赖关系分析
|
||||
- API层依赖服务层;服务层依赖模型层;Schema层为API与服务层之间的数据契约
|
||||
- 工资服务依赖员工与考核数据;考核服务依赖指标与明细数据
|
||||
- 数据库索引覆盖查询与统计场景,有助于提升查询性能
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
API_S["salary.py"] --> SVC_S["salary_service.py"]
|
||||
API_A["assessments.py"] --> SVC_A["assessment_service.py"]
|
||||
SVC_S --> MODELS["models.py"]
|
||||
SVC_A --> MODELS
|
||||
MODELS --> DB["数据库"]
|
||||
SCHEMAS["schemas.py"] --> API_S
|
||||
SCHEMAS --> API_A
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [salary.py](file://backend/app/api/v1/salary.py#L1-L156)
|
||||
- [assessments.py](file://backend/app/api/v1/assessments.py#L1-L166)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L1-L260)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [models.py](file://backend/app/models/models.py#L1-L438)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L1-L743)
|
||||
|
||||
章节来源
|
||||
- [salary.py](file://backend/app/api/v1/salary.py#L1-L156)
|
||||
- [assessments.py](file://backend/app/api/v1/assessments.py#L1-L166)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L1-L260)
|
||||
- [assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [models.py](file://backend/app/models/models.py#L1-L438)
|
||||
- [schemas.py](file://backend/app/schemas/schemas.py#L1-L743)
|
||||
|
||||
## 性能考量
|
||||
- 查询与分页:服务层提供分页查询,避免一次性加载大量数据
|
||||
- 关联加载:使用selectinload按需加载关联对象,减少N+1查询
|
||||
- 索引优化:数据库表对常用查询字段建立索引,如工资记录的员工ID与周期组合索引
|
||||
- 批量操作:批量生成与批量确认接口减少多次往返,提升吞吐
|
||||
- 异步IO:基于SQLAlchemy异步会话,适合高并发场景
|
||||
|
||||
章节来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L21-L58)
|
||||
- [models.py](file://backend/app/models/models.py#L227-L231)
|
||||
- [database.md](file://docs/database.md#L197-L216)
|
||||
|
||||
## 故障排查指南
|
||||
- 无法生成工资
|
||||
- 检查是否存在同周期的工资记录
|
||||
- 检查考核是否已确认(FINALIZED)
|
||||
- 检查员工是否存在
|
||||
- 无法更新工资
|
||||
- 仅待确认状态可更新
|
||||
- 无法确认工资
|
||||
- 仅待确认状态可确认
|
||||
- 批量生成异常
|
||||
- 检查是否存在未确认的考核
|
||||
- 检查数据库连接与事务
|
||||
|
||||
章节来源
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L133-L164)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L104-L124)
|
||||
- [salary_service.py](file://backend/app/services/salary_service.py#L222-L231)
|
||||
|
||||
## 结论
|
||||
本系统以“考核得分×绩效系数×基数”的核心公式实现绩效奖金计算,通过严格的流程控制与状态管理确保数据一致性。工资构成清晰、扩展灵活,支持按科室批量生成与批量确认,满足医院绩效工资核算的实际需求。未来可在模型层引入岗位类型、扩展加权计算方法与增加更多补贴/扣款项,进一步提升系统的适应性与可配置性。
|
||||
|
||||
## 附录
|
||||
- 数据库表结构概览与索引
|
||||
- 员工表:包含基本工资与绩效系数
|
||||
- 考核表:包含总分与加权得分
|
||||
- 工资记录表:包含基本工资、绩效得分、绩效奖金、补贴、扣款与应发工资
|
||||
- 系统设计文档要点
|
||||
- 多维度考核、评分方法(区间法、扣分法等)
|
||||
- 绩效结果应用(与绩效工资挂钩)
|
||||
|
||||
章节来源
|
||||
- [database.md](file://docs/database.md#L97-L136)
|
||||
- [database.md](file://docs/database.md#L197-L216)
|
||||
- [详细设计.md](file://docs/详细设计.md#L328-L381)
|
||||
Reference in New Issue
Block a user