18 KiB
18 KiB
工资核算模型
**本文引用的文件** - [backend/app/models/models.py](file://backend/app/models/models.py) - [backend/app/models/finance.py](file://backend/app/models/finance.py) - [backend/app/api/v1/salary.py](file://backend/app/api/v1/salary.py) - [backend/app/services/salary_service.py](file://backend/app/services/salary_service.py) - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py) - [backend/alembic/versions/001_initial.py](file://backend/alembic/versions/001_initial.py) - [backend/alembic/versions/002_template.py](file://backend/alembic/versions/002_template.py) - [frontend/src/views/salary/Salary.vue](file://frontend/src/views/salary/Salary.vue) - [frontend/src/api/salary.js](file://frontend/src/api/salary.js) - [docs/database.md](file://docs/database.md) - [docs/详细设计文档.md](file://docs/详细设计文档.md)目录
简介
本文档深入解析医院绩效系统中的工资核算模型,重点围绕SalaryRecord模型的设计理念、实现细节以及与考核系统的集成关系。文档涵盖以下关键内容:
- 基本工资、绩效得分、绩效奖金、扣款补贴的计算逻辑
- 工资核算的时间周期与状态管理(待处理、已确认)
- 应发工资的计算公式与字段约束
- 绩效奖金与绩效得分的关系、扣款与补贴的设置规则
- 与员工的多对一关系、历史记录的版本控制
- 批量核算的性能优化策略
- 工资计算示例、异常处理机制与数据准确性验证方法
项目结构
后端采用FastAPI + SQLAlchemy异步ORM架构,工资核算功能位于以下模块:
- 模型层:定义SalaryRecord、Staff、Assessment等实体及其关系
- 服务层:实现工资计算、生成、确认、批量处理等业务逻辑
- API层:提供REST接口,支持按考核生成工资、批量生成与确认
- 前端:提供工资记录查询、编辑、确认等界面
graph TB
subgraph "前端"
FE_View["Salary.vue<br/>视图组件"]
FE_API["salary.js<br/>API封装"]
end
subgraph "后端"
API["salary.py<br/>API路由"]
Service["salary_service.py<br/>服务层"]
Model["models.py<br/>数据模型"]
Schema["schemas.py<br/>数据模式"]
DB["数据库<br/>salary_records表"]
end
FE_View --> FE_API
FE_API --> API
API --> Service
Service --> Model
Model --> DB
Schema --> API
图表来源
- backend/app/api/v1/salary.py
- backend/app/services/salary_service.py
- backend/app/models/models.py
- frontend/src/views/salary/Salary.vue
- frontend/src/api/salary.js
章节来源
- backend/app/api/v1/salary.py
- backend/app/services/salary_service.py
- backend/app/models/models.py
- frontend/src/views/salary/Salary.vue
- frontend/src/api/salary.js
核心组件
- SalaryRecord模型:存储工资核算结果,包含基本工资、绩效得分、绩效奖金、扣款、补贴、应发工资与状态
- Staff模型:员工基本信息与绩效系数,用于绩效奖金计算
- Assessment模型:考核记录,提供加权得分作为绩效奖金依据
- SalaryService服务:实现工资计算、生成、确认、批量处理等核心逻辑
- API路由:提供查询、创建、更新、按考核生成、批量生成与确认等接口
章节来源
- backend/app/models/models.py
- backend/app/models/models.py
- backend/app/models/models.py
- backend/app/services/salary_service.py
- backend/app/api/v1/salary.py
架构概览
工资核算从考核结果出发,通过服务层计算绩效奖金并生成工资记录;前端提供查询与确认操作,后端通过权限控制确保只有管理员或经理可以进行关键操作。
sequenceDiagram
participant Client as "客户端"
participant API as "salary.py"
participant Service as "salary_service.py"
participant DB as "数据库"
Client->>API : POST /salary/generate?staff_id&period_year&period_month
API->>Service : generate_from_assessment(staff_id, year, month)
Service->>DB : 查询员工信息(Staff)
Service->>DB : 查询已确认考核(Assessment.status='finalized')
Service->>Service : calculate_performance_bonus(weighted_score, performance_ratio)
Service->>DB : 插入SalaryRecord(状态=pending)
DB-->>Service : 返回新记录
Service-->>API : 返回记录ID
API-->>Client : {code,message,data : id}
图表来源
章节来源
详细组件分析
SalaryRecord模型设计
- 字段定义
- 基本工资:base_salary,数值型,精度10位小数2位
- 绩效得分:performance_score,数值型,精度5位小数2位
- 绩效奖金:performance_bonus,数值型,精度10位小数2位
- 扣款:deduction,数值型,精度10位小数2位
- 补贴:allowance,数值型,精度10位小数2位
- 应发工资:total_salary,数值型,精度10位小数2位
- 状态:status,默认"pending"
- 时间周期:period_year、period_month
- 外键:staff_id,关联员工表
- 约束与索引
- 外键约束:staff_id -> staff.id
- 索引:staff_id、(period_year, period_month)
- 关系
- 与Staff为多对一关系,支持反向访问salary_records
classDiagram
class Staff {
+int id
+string employee_id
+string name
+int department_id
+string position
+string title
+float base_salary
+float performance_ratio
+string status
+datetime hire_date
+datetime created_at
+datetime updated_at
+Assessment[] assessments
+SalaryRecord[] salary_records
}
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 "1" o-- "*" SalaryRecord : "多对一"
图表来源
章节来源
- backend/app/models/models.py
- backend/alembic/versions/001_initial.py
- docs/database.md
- docs/详细设计文档.md
计算逻辑与公式
- 绩效奖金计算
- 公式:绩效奖金 = 绩效基数 × (绩效得分/100) × 绩效系数
- 绩效基数:固定常量,服务层中定义
- 绩效系数:来自员工表的performance_ratio
- 应发工资计算
- 公式:应发工资 = 基本工资 + 绩效奖金 + 补贴 - 扣款
- 该公式在创建与更新工资记录时均会重新计算并持久化
flowchart TD
Start(["开始"]) --> LoadStaff["加载员工信息<br/>获取base_salary, performance_ratio"]
LoadStaff --> LoadAssessment["加载已确认考核<br/>获取weighted_score"]
LoadAssessment --> CheckExisting{"是否存在同周期工资记录?"}
CheckExisting --> |是| ReturnNone["返回空不重复生成"]
CheckExisting --> |否| CalcBonus["计算绩效奖金<br/>bonus = 基数 × (score/100) × ratio"]
CalcBonus --> CalcTotal["计算应发工资<br/>total = base + bonus + allowance - deduction"]
CalcTotal --> CreateRecord["创建SalaryRecord<br/>状态=pending"]
CreateRecord --> End(["结束"])
ReturnNone --> End
图表来源
章节来源
- backend/app/services/salary_service.py
- backend/app/services/salary_service.py
- backend/app/services/salary_service.py
时间周期与状态管理
- 时间周期
- 由period_year与period_month共同构成,用于唯一标识某员工的某月工资记录
- 数据库层面在salary_records上建立了复合索引(idx_salary_period),提升查询效率
- 状态管理
- 待处理:pending(默认状态)
- 已确认:confirmed(管理员/经理确认后变更)
- 已发放:paid(当前服务层未实现,但模型预留字段)
- 状态变更流程
- 单条确认:调用确认接口,仅当状态为pending时允许变更
- 批量确认:按年月筛选pending状态记录,可选择按科室过滤
stateDiagram-v2
[*] --> 待处理
待处理 --> 已确认 : "确认工资"
已确认 --> 已发放 : "发放工资"
已发放 --> [*]
图表来源
章节来源
- backend/app/models/models.py
- backend/app/services/salary_service.py
- backend/app/services/salary_service.py
与员工的多对一关系与历史版本控制
- 多对一关系
- SalaryRecord.staff_id -> Staff.id,每个工资记录对应唯一员工
- Staff.salary_records反向关系,支持按员工查询其历史工资记录
- 历史版本控制
- 当前版本未实现SalaryRecord的版本号字段;如需版本控制,可在模型中增加version字段并在更新时递增
- 绩效计划的版本控制已在其他模型中实现(PerformancePlan.version),可借鉴其模式
章节来源
批量核算的性能优化
- 批量生成
- 服务层先查询指定科室下所有已确认的考核记录,再逐条生成工资记录
- 建议在大规模数据场景下:
- 使用分批处理(分页查询考核记录)
- 异步并发插入(注意数据库连接池与事务边界)
- 增加数据库索引覆盖查询条件
- 批量确认
- 通过SQL查询一次性筛选出待确认记录,减少多次往返
- 支持按科室过滤,缩小确认范围
章节来源
扣款与补贴的设置规则
- 扣款与补贴均为数值型字段,支持在创建或更新时设置
- 服务层在创建与更新时均会重新计算应发工资:total_salary = base_salary + performance_bonus + allowance - deduction
- 建议在业务层增加校验规则:
- 扣款与补贴必须非负
- 应发工资计算后可进行合理性校验(如不得为负)
章节来源
绩效奖金与绩效得分的关系
- 绩效奖金 = 绩效基数 × (绩效得分/100) × 绩效系数
- 绩效得分来自Assessment.weighted_score,状态必须为"finalized"
- 绩效系数来自Staff.performance_ratio,不同岗位/级别可设置不同系数
章节来源
API与前端交互
- API接口
- 列表查询:支持按员工、科室、年份、月份、状态筛选
- 详情查询:返回带员工与科室名称的完整信息
- 创建/更新:仅允许在待处理状态下更新
- 按考核生成:基于已确认考核自动生成工资记录
- 批量生成/确认:支持按科室批量生成与批量确认
- 前端展示
- 列表显示基本工资、绩效得分、绩效奖金、补贴、扣款、应发工资等字段
- 提供编辑弹窗,支持更新扣款、补贴、备注等
章节来源
依赖分析
- 模型依赖
- SalaryRecord依赖Staff(外键)
- Assessment与SalaryRecord通过staff_id间接关联
- 服务层依赖
- 依赖Staff、Assessment模型进行数据查询与计算
- 依赖Pydantic模式进行请求/响应数据校验
- API层依赖
- 依赖Security中间件进行权限控制(管理员/经理)
- 依赖数据库会话进行异步操作
graph LR
SalaryRecord["SalaryRecord模型"] --> Staff["Staff模型"]
SalaryService["SalaryService"] --> SalaryRecord
SalaryService --> Staff
SalaryService --> Assessment["Assessment模型"]
API["salary.py"] --> SalaryService
API --> Schema["schemas.py"]
图表来源
- backend/app/models/models.py
- backend/app/models/models.py
- backend/app/models/models.py
- backend/app/services/salary_service.py
- backend/app/api/v1/salary.py
章节来源
- backend/app/models/models.py
- backend/app/models/models.py
- backend/app/models/models.py
- backend/app/services/salary_service.py
- backend/app/api/v1/salary.py
性能考虑
- 查询优化
- salary_records表已建立索引:staff_id、(period_year, period_month)
- API层使用selectinload预加载关联对象,避免N+1查询
- 批量处理
- 批量生成与确认采用SQL查询一次性筛选,减少循环调用
- 建议在高并发场景下增加数据库连接池配置与事务隔离级别
- 数据类型
- 使用Numeric类型保证金额精度,避免浮点误差累积
[本节为通用性能建议,无需特定文件来源]
故障排除指南
- 无法生成工资
- 检查是否存在已确认的考核记录且状态为"finalized"
- 检查是否已存在同周期的工资记录(防止重复生成)
- 无法确认工资
- 确认记录状态必须为"pending"
- 检查权限:仅管理员或经理可执行确认操作
- 数据不一致
- 更新扣款/补贴后需重新计算应发工资
- 核对数据库索引是否生效,避免查询性能问题
章节来源
- backend/app/services/salary_service.py
- backend/app/services/salary_service.py
- backend/app/api/v1/salary.py
结论
SalaryRecord模型通过清晰的字段设计与严格的计算逻辑,实现了从考核到工资的自动化流转。服务层提供了完善的生成、确认与批量处理能力,并通过索引与预加载优化了查询性能。未来可在版本控制、状态扩展(如已发放)与更细粒度的扣款/补贴规则方面进一步增强。
[本节为总结性内容,无需特定文件来源]
附录
工资计算示例
- 输入
- 员工:基本工资=10000,绩效系数=1.2
- 考核:加权得分=95
- 扣款=0,补贴=500
- 计算过程
- 绩效奖金 = 固定基数 × (95/100) × 1.2
- 应发工资 = 10000 + 绩效奖金 + 500 - 0
- 输出
- 工资记录状态=pending,等待确认
章节来源
数据准确性验证方法
- 金额精度:使用Numeric类型,避免浮点误差
- 业务规则:在服务层增加校验(扣款/补贴非负、应发工资合理)
- 索引验证:确认salary_records索引生效,提升查询性能
- 测试覆盖:编写单元测试验证计算逻辑与状态变更流程
章节来源