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) {