fix: 修复薪资编辑保存失败 + 应发计算丢失细化字段

两个问题:
1. 编辑保存 422 错误:updateEntrySchema 要求 min(0),但 bonus
   可能为负数(如扣款),导致 Zod 验证失败。放宽为 z.number().optional()
2. 应发不随编辑变化:编辑条目时 inputs 只合并 5 个基本字段,
   丢失了 positionSalary/performanceSalary 等细化字段,
   导致 calcBatchEntry 计算的 totalPay 不包含细化薪资项。
   修复:从 entry 中补全所有细化字段

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
selfrelease
2026-08-16 14:19:43 +08:00
parent ea2dfe3b4b
commit 2875965113
+18 -10
View File
@@ -520,15 +520,15 @@ router.post('/batches', async (req: AuthRequest, res: Response, next: NextFuncti
// 编辑批次条目(计算依据项 + 社保公积金手动覆盖)
const updateEntrySchema = z.object({
baseSalary: z.number().min(0).optional(),
overtimePay: z.number().min(0).optional(),
allowance: z.number().min(0).optional(),
deduction: z.number().min(0).optional(),
bonus: z.number().min(0).optional(),
socialEmp: z.number().min(0).optional(),
socialOrg: z.number().min(0).optional(),
housingEmp: z.number().min(0).optional(),
housingOrg: z.number().min(0).optional(),
baseSalary: z.number().optional(),
overtimePay: z.number().optional(),
allowance: z.number().optional(),
deduction: z.number().optional(),
bonus: z.number().optional(),
socialEmp: z.number().optional(),
socialOrg: z.number().optional(),
housingEmp: z.number().optional(),
housingOrg: z.number().optional(),
})
router.put('/batches/:batchId/entries/:employeeId', async (req: AuthRequest, res: Response, next: NextFunction) => {
@@ -546,13 +546,21 @@ router.put('/batches/:batchId/entries/:employeeId', async (req: AuthRequest, res
})
if (!entry) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '条目不存在' } })
// 合并输入项
// 合并输入项(包含细化薪资字段,避免编辑时丢失岗位工资/绩效工资等)
const inputs = {
baseSalary: data.baseSalary ?? entry.baseSalary,
overtimePay: data.overtimePay ?? entry.overtimePay,
allowance: data.allowance ?? entry.allowance,
deduction: data.deduction ?? entry.deduction,
bonus: data.bonus ?? entry.bonus,
positionSalary: entry.positionSalary || undefined,
performanceSalary: entry.performanceSalary || undefined,
senioritySalary: entry.senioritySalary || undefined,
transportAllowance: entry.transportAllowance || undefined,
mealAllowance: entry.mealAllowance || undefined,
housingAllowance: entry.housingAllowance || undefined,
communicationAllowance: entry.communicationAllowance || undefined,
otherDeduction: entry.otherDeduction || undefined,
}
// 构建社保覆盖参数(如果请求中包含社保字段)