提交文件
This commit is contained in:
350
.qoder/repowiki/zh/content/后端开发指南/服务层开发/工资服务.md
Normal file
350
.qoder/repowiki/zh/content/后端开发指南/服务层开发/工资服务.md
Normal file
@@ -0,0 +1,350 @@
|
||||
# 工资服务
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py)
|
||||
- [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py)
|
||||
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py)
|
||||
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py)
|
||||
- [backend/app/core/database.py](file://backend/app/core/database.py)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py)
|
||||
- [backend/init_db.py](file://backend/init_db.py)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [组件详解](#组件详解)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向“工资服务”的开发与维护,围绕 SalaryService 类的实现架构展开,系统性阐述以下内容:
|
||||
- 绩效奖金计算算法:基础工资、绩效系数、考核等级对应的奖金计算逻辑
|
||||
- 工资记录的数据结构、字段含义与业务规则
|
||||
- 批量生成工资记录的机制:按月度、季度或年度的计算流程
|
||||
- 与考核服务、员工服务的集成关系与数据一致性保障
|
||||
- 异常处理、事务管理与性能优化策略
|
||||
- 实际计算示例与边界条件处理
|
||||
|
||||
## 项目结构
|
||||
后端采用分层架构:API 层负责路由与鉴权,Service 层封装业务逻辑,Model 层定义数据模型,Schema 层定义输入输出结构。工资服务位于 Service 层,与考核服务、员工服务协作,最终落库到 SalaryRecord。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
API["API 路由<br/>salary.py"] --> SVC["服务层<br/>salary_service.py"]
|
||||
SVC --> MODEL["模型层<br/>models.py 中的 SalaryRecord/Assessment/Staff"]
|
||||
SVC --> SCHEMA["Schema 定义<br/>schemas.py"]
|
||||
SVC --> ASSESS_SVC["考核服务<br/>assessment_service.py"]
|
||||
SVC --> STAFF_SVC["员工服务<br/>staff_service.py"]
|
||||
SVC --> DB["数据库连接<br/>database.py"]
|
||||
DB --> CONF["配置<br/>config.py"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py#L1-L156)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L1-L260)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L205-L230)
|
||||
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L272-L313)
|
||||
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112)
|
||||
- [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/salary.py](file://backend/app/api/v1/salary.py#L1-L156)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L1-L260)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L205-L230)
|
||||
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L272-L313)
|
||||
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112)
|
||||
- [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)
|
||||
|
||||
## 核心组件
|
||||
- 工资服务(SalaryService):提供查询、创建、更新、生成、确认、批量生成与批量确认等能力;核心算法集中在绩效奖金计算与总工资汇总。
|
||||
- 工资记录模型(SalaryRecord):持久化存储工资条目,包含基础工资、绩效得分、绩效奖金、扣款、补贴、应发工资、状态等字段。
|
||||
- 考核服务(AssessmentService):提供考核的创建、提交、审核、确认等流程,为工资生成提供“已确认”的考核数据。
|
||||
- 员工服务(StaffService):提供员工信息查询与维护,为工资生成提供基础工资与绩效系数。
|
||||
- API 路由(salary.py):对外暴露查询、生成、确认、批量生成与批量确认等接口,并进行权限校验。
|
||||
|
||||
章节来源
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L14-L260)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L205-L230)
|
||||
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112)
|
||||
- [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py#L1-L156)
|
||||
|
||||
## 架构总览
|
||||
工资服务的调用链路如下:前端请求经 API 路由进入,由 SalaryService 执行业务逻辑;若需要从考核生成,则联动 AssessmentService 与 StaffService;最终写入数据库并返回结果。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant FE as "前端"
|
||||
participant API as "API 路由<br/>salary.py"
|
||||
participant SVC as "服务层<br/>salary_service.py"
|
||||
participant ASSESS as "考核服务<br/>assessment_service.py"
|
||||
participant STAFF as "员工服务<br/>staff_service.py"
|
||||
participant DB as "数据库"
|
||||
FE->>API : "POST /salary/generate"
|
||||
API->>SVC : "generate_from_assessment(staff_id, year, month)"
|
||||
SVC->>DB : "查询员工信息"
|
||||
DB-->>SVC : "Staff"
|
||||
SVC->>DB : "查询已确认考核"
|
||||
DB-->>SVC : "Assessment(finalized)"
|
||||
SVC->>SVC : "calculate_performance_bonus()"
|
||||
SVC->>DB : "插入 SalaryRecord"
|
||||
DB-->>SVC : "返回新记录"
|
||||
SVC-->>API : "返回记录ID"
|
||||
API-->>FE : "生成成功"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py#L96-L110)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L127-L190)
|
||||
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L195-L205)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L52-L59)
|
||||
|
||||
## 组件详解
|
||||
|
||||
### 工资记录数据模型与字段语义
|
||||
- 表名:salary_records
|
||||
- 字段与含义(节选):
|
||||
- staff_id:员工ID
|
||||
- period_year / period_month:所属周期(年/月)
|
||||
- base_salary:基本工资
|
||||
- performance_score:绩效得分
|
||||
- performance_bonus:绩效奖金
|
||||
- allowance:补贴
|
||||
- deduction:扣款
|
||||
- total_salary:应发工资(base_salary + performance_bonus + allowance - deduction)
|
||||
- status:状态(默认 pending,支持 confirmed)
|
||||
- remark:备注
|
||||
- created_at / updated_at:创建与更新时间
|
||||
|
||||
业务规则:
|
||||
- 总工资由服务层在创建/更新时计算并入库
|
||||
- 状态仅允许在“pending”状态下进行更新与确认
|
||||
- 生成工资记录前需确保同一员工当月无重复记录
|
||||
|
||||
章节来源
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L205-L230)
|
||||
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L272-L313)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L77-L124)
|
||||
|
||||
### 绩效奖金计算算法
|
||||
- 奖金基数:PERFORMANCE_BASE(静态常量)
|
||||
- 计算公式:奖金 = 奖金基数 × (绩效得分/100) × 员工绩效系数
|
||||
- 输入来源:
|
||||
- 绩效得分:来自已确认的 Assessment.weighted_score
|
||||
- 绩效系数:来自 Staff.performance_ratio
|
||||
- 输出:performance_bonus,用于后续总工资计算
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始"]) --> LoadAssess["加载已确认考核<br/>Assessment.finalized"]
|
||||
LoadAssess --> LoadStaff["加载员工信息<br/>Staff.performance_ratio"]
|
||||
LoadStaff --> CalcBonus["计算奖金<br/>奖金 = 奖金基数 × 得分/100 × 系数"]
|
||||
CalcBonus --> SumTotal["汇总总工资<br/>总工资 = 基本工资 + 奖金 + 补贴 - 扣款"]
|
||||
SumTotal --> Persist["持久化 SalaryRecord"]
|
||||
Persist --> End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L71-L74)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L167-L170)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L173-L186)
|
||||
|
||||
章节来源
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L17-L18)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L71-L74)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L167-L170)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L173-L186)
|
||||
|
||||
### 工资记录生成与批量处理机制
|
||||
- 单条生成:generate_from_assessment
|
||||
- 校验员工存在
|
||||
- 查询当期“已确认”的 Assessment
|
||||
- 检查是否存在重复工资记录
|
||||
- 计算奖金与总工资
|
||||
- 插入 SalaryRecord(状态 pending)
|
||||
- 批量生成:batch_generate_for_department
|
||||
- 基于部门与周期,查询所有“已确认”的 Assessment
|
||||
- 对每个评估逐条调用单条生成
|
||||
- 批量确认:batch_confirm
|
||||
- 按年/月筛选 pending 状态的记录
|
||||
- 可选按部门过滤
|
||||
- 将状态置为 confirmed 并返回确认数量
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant API as "API 路由"
|
||||
participant SVC as "SalaryService"
|
||||
participant DB as "数据库"
|
||||
API->>SVC : "batch_generate_for_department(dept_id, year, month)"
|
||||
SVC->>DB : "查询已确认考核(按部门+周期)"
|
||||
DB-->>SVC : "Assessments 列表"
|
||||
loop 遍历每个 Assessment
|
||||
SVC->>SVC : "generate_from_assessment()"
|
||||
SVC->>DB : "插入 SalaryRecord"
|
||||
end
|
||||
SVC-->>API : "返回生成的记录列表"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py#L113-L129)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L193-L219)
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py#L96-L129)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L127-L190)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L193-L219)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L234-L259)
|
||||
|
||||
### 与考核服务、员工服务的集成关系
|
||||
- 与考核服务(AssessmentService):
|
||||
- 生成工资记录的前提是存在“已确认”的 Assessment
|
||||
- 通过 Assessment.status == "finalized" 进行筛选
|
||||
- 与员工服务(StaffService):
|
||||
- 读取员工的基础工资与绩效系数
|
||||
- 作为奖金计算的输入参数
|
||||
- 数据一致性:
|
||||
- 生成前检查重复记录,避免重复发薪
|
||||
- 仅对 pending 状态的记录允许更新与确认
|
||||
|
||||
章节来源
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L134-L153)
|
||||
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L195-L205)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L52-L59)
|
||||
|
||||
### API 接口与权限控制
|
||||
- 查询列表与详情:普通用户可访问
|
||||
- 创建、更新、单条生成、确认:需要管理员或经理权限
|
||||
- 批量生成、批量确认:需要管理员或经理权限
|
||||
- 返回格式遵循统一响应结构(code/message/data)
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py#L20-L156)
|
||||
|
||||
## 依赖关系分析
|
||||
- SalaryService 依赖:
|
||||
- SQLAlchemy 异步会话(AsyncSession)
|
||||
- 模型:SalaryRecord、Staff、Assessment
|
||||
- Schema:SalaryRecordCreate、SalaryRecordUpdate
|
||||
- 服务:AssessmentService、StaffService
|
||||
- 外部依赖:
|
||||
- 数据库连接与事务管理(database.py)
|
||||
- 应用配置(config.py)
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class SalaryService {
|
||||
+get_list(...)
|
||||
+get_by_id(...)
|
||||
+create(...)
|
||||
+update(...)
|
||||
+calculate_performance_bonus(...)
|
||||
+generate_from_assessment(...)
|
||||
+batch_generate_for_department(...)
|
||||
+confirm(...)
|
||||
+batch_confirm(...)
|
||||
}
|
||||
class AssessmentService {
|
||||
+get_by_id(...)
|
||||
+finalize(...)
|
||||
}
|
||||
class StaffService {
|
||||
+get_by_id(...)
|
||||
}
|
||||
class SalaryRecord
|
||||
class Staff
|
||||
class Assessment
|
||||
SalaryService --> AssessmentService : "查询已确认考核"
|
||||
SalaryService --> StaffService : "读取员工信息"
|
||||
SalaryService --> SalaryRecord : "创建/更新"
|
||||
SalaryService --> Staff : "读取基础工资/系数"
|
||||
SalaryService --> Assessment : "读取加权得分"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L14-L260)
|
||||
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L205-L230)
|
||||
|
||||
章节来源
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L1-L260)
|
||||
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L1-L263)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L205-L230)
|
||||
|
||||
## 性能考量
|
||||
- 数据库连接池与并发:
|
||||
- 配置文件提供数据库连接池大小与溢出参数,建议结合业务峰值合理设置
|
||||
- 查询优化:
|
||||
- SalaryRecord 与 Assessment 均具备按 staff_id、period、status 的索引,有利于分页与筛选
|
||||
- 批量生成时建议按部门分批处理,避免一次性加载过多记录
|
||||
- 事务与回滚:
|
||||
- 数据库会话在异常时自动回滚,确保数据一致性
|
||||
- I/O 与序列化:
|
||||
- API 层对响应进行统一包装,注意避免在高频接口中进行大量对象转换
|
||||
|
||||
章节来源
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L18-L26)
|
||||
- [backend/app/core/database.py](file://backend/app/core/database.py#L10-L20)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L227-L230)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L193-L219)
|
||||
|
||||
## 故障排查指南
|
||||
- 无法生成工资记录
|
||||
- 检查是否存在“已确认”的 Assessment
|
||||
- 检查是否已存在同员工/同周期的工资记录
|
||||
- 检查员工是否存在且基础工资/绩效系数有效
|
||||
- 更新失败
|
||||
- 仅允许对状态为“pending”的记录进行更新
|
||||
- 确认失败
|
||||
- 仅允许对状态为“pending”的记录进行确认
|
||||
- 批量生成/确认
|
||||
- 确认年/月参数正确
|
||||
- 如指定部门,确认部门ID有效
|
||||
- 数据库异常
|
||||
- 查看会话依赖的回滚逻辑是否触发
|
||||
- 检查连接池配置与数据库可用性
|
||||
|
||||
章节来源
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L104-L124)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L222-L231)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L234-L259)
|
||||
- [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py#L96-L156)
|
||||
- [backend/app/core/database.py](file://backend/app/core/database.py#L28-L39)
|
||||
|
||||
## 结论
|
||||
SalaryService 提供了完整的工资核算闭环:从“已确认”的考核数据出发,结合员工基础信息,计算绩效奖金并生成工资记录;支持单条与批量生成、单条与批量确认,并通过严格的权限控制与状态约束保障业务正确性。配合合理的数据库索引与连接池配置,可在高并发场景下保持稳定与高效。
|
||||
|
||||
## 附录
|
||||
|
||||
### 实际计算示例与边界条件
|
||||
- 示例场景
|
||||
- 员工基础工资:10000,绩效系数:1.2
|
||||
- 考核加权得分:90
|
||||
- 奖金基数:3000
|
||||
- 计算过程:奖金 = 3000 × (90/100) × 1.2;总工资 = 基础工资 + 奖金 + 补贴 - 扣款
|
||||
- 边界条件
|
||||
- 绩效得分/系数为 0:奖金为 0
|
||||
- 补贴/扣款为负:不合法,应在输入层约束
|
||||
- 已存在同周期记录:拒绝重复生成
|
||||
- 非“已确认”考核:拒绝生成
|
||||
- 非“pending”状态:拒绝更新/确认
|
||||
|
||||
章节来源
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L17-L18)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L71-L74)
|
||||
- [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py#L127-L190)
|
||||
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L272-L313)
|
||||
Reference in New Issue
Block a user