# 工资服务 **本文引用的文件** - [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) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [组件详解](#组件详解) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向“工资服务”的开发与维护,围绕 SalaryService 类的实现架构展开,系统性阐述以下内容: - 绩效奖金计算算法:基础工资、绩效系数、考核等级对应的奖金计算逻辑 - 工资记录的数据结构、字段含义与业务规则 - 批量生成工资记录的机制:按月度、季度或年度的计算流程 - 与考核服务、员工服务的集成关系与数据一致性保障 - 异常处理、事务管理与性能优化策略 - 实际计算示例与边界条件处理 ## 项目结构 后端采用分层架构:API 层负责路由与鉴权,Service 层封装业务逻辑,Model 层定义数据模型,Schema 层定义输入输出结构。工资服务位于 Service 层,与考核服务、员工服务协作,最终落库到 SalaryRecord。 ```mermaid graph TB API["API 路由
salary.py"] --> SVC["服务层
salary_service.py"] SVC --> MODEL["模型层
models.py 中的 SalaryRecord/Assessment/Staff"] SVC --> SCHEMA["Schema 定义
schemas.py"] SVC --> ASSESS_SVC["考核服务
assessment_service.py"] SVC --> STAFF_SVC["员工服务
staff_service.py"] SVC --> DB["数据库连接
database.py"] DB --> CONF["配置
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 路由
salary.py" participant SVC as "服务层
salary_service.py" participant ASSESS as "考核服务
assessment_service.py" participant STAFF as "员工服务
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["加载已确认考核
Assessment.finalized"] LoadAssess --> LoadStaff["加载员工信息
Staff.performance_ratio"] LoadStaff --> CalcBonus["计算奖金
奖金 = 奖金基数 × 得分/100 × 系数"] CalcBonus --> SumTotal["汇总总工资
总工资 = 基本工资 + 奖金 + 补贴 - 扣款"] 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)