From 3ac333891cafc75119217cec0cf712f30cad29a1 Mon Sep 17 00:00:00 2001 From: selfrelease Date: Sun, 16 Aug 2026 15:24:49 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8A=B3=E5=8A=A1=E5=8D=8F=E8=AE=AE/?= =?UTF-8?q?=E5=AE=9E=E4=B9=A0=E5=8D=8F=E8=AE=AE=E4=BA=BA=E5=91=98=E8=96=AA?= =?UTF-8?q?=E8=B5=84=E8=AE=A1=E7=AE=97=E5=BC=BA=E5=88=B6=E7=A4=BE=E4=BF=9D?= =?UTF-8?q?=E5=85=AC=E7=A7=AF=E9=87=91=E4=B8=BA0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit calcBatchEntry 查询员工时 include contracts,判断合同类型: - LABOR(劳务协议)/ INTERNSHIP(实习协议)→ 社保公积金基数强制0,跳过社保计算 - 其他合同类型 → 正常计算 无论哪种批次创建模式(copy_last/blank_employees/custom等), 劳务协议人员的社保公积金都为0。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- backend/src/services/payroll.service.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/backend/src/services/payroll.service.ts b/backend/src/services/payroll.service.ts index b03da19..554020d 100644 --- a/backend/src/services/payroll.service.ts +++ b/backend/src/services/payroll.service.ts @@ -206,9 +206,16 @@ export async function calcBatchEntry( batchType: string = 'REGULAR', options?: { skipSocial?: boolean; overrideSocial?: { socialEmp?: number; socialOrg?: number; housingEmp?: number; housingOrg?: number }; prevDeferred?: { socialEmp?: number; housingEmp?: number; minWage?: number } }, ) { - const employee = await prisma.employee.findFirst({ where: { id: employeeId, orgId } }) + const employee = await prisma.employee.findFirst({ + where: { id: employeeId, orgId }, + include: { contracts: { orderBy: { createdAt: 'desc' }, take: 1 } }, + }) if (!employee) throw { code: 'NOT_FOUND', message: '员工不存在' } + // 劳务协议/实习协议人员:不缴纳社保公积金,基数强制 0 + const latestContract = employee.contracts[0] + const isNoSocialContract = latestContract && ['LABOR', 'INTERNSHIP'].includes(latestContract.contractType) + // 通过员工账户查年度标准(新逻辑),回退到旧配置(兼容) const { socialAccount, housingAccount } = await getEmployeeAccounts(orgId, employeeId) let socialConfig: any = null @@ -236,15 +243,15 @@ export async function calcBatchEntry( }) } - // 社保基数:优先用员工核定基数(含0,劳务协议人员基数为0不交社保),未设置时回退到基本工资 - const socialBase = employee.socialInsBase != null ? employee.socialInsBase : inputs.baseSalary - const housingBase = employee.housingFundBase != null ? employee.housingFundBase : inputs.baseSalary + // 社保基数:劳务协议/实习协议人员强制 0;否则优先用员工核定基数(含0),未设置时回退到基本工资 + const socialBase = isNoSocialContract ? 0 : (employee.socialInsBase != null ? employee.socialInsBase : inputs.baseSalary) + const housingBase = isNoSocialContract ? 0 : (employee.housingFundBase != null ? employee.housingFundBase : inputs.baseSalary) let socialEmp = 0, socialOrg = 0, housingEmp = 0, housingOrg = 0 - // 年终奖/奖金批次、补偿金批次:不扣社保公积金 + // 年终奖/奖金批次、补偿金批次、劳务协议/实习协议人员:不扣社保公积金 // 其他批次:计算当月应缴全额,减去已归档批次已扣金额,差额为本批次应扣 - if (batchType !== 'BONUS' && batchType !== 'SEVERANCE' && !options?.skipSocial) { + if (batchType !== 'BONUS' && batchType !== 'SEVERANCE' && !options?.skipSocial && !isNoSocialContract) { // 1. 计算当月应缴社保公积金全额 let fullSocialEmp = 0, fullSocialOrg = 0, fullHousingEmp = 0, fullHousingOrg = 0 if (socialConfig) {