diff --git a/backend/src/services/contract.service.ts b/backend/src/services/contract.service.ts index 742325f..7b7f1ba 100644 --- a/backend/src/services/contract.service.ts +++ b/backend/src/services/contract.service.ts @@ -433,33 +433,36 @@ export async function createEmployee(orgId: string, userId: string, data: any) { }, }) - await tx.employeeSocialInsRecord.create({ - data: { - orgId, - employeeId: emp.id, - startMonth: socialInsStartMonth, - endMonth: null, - base: socialInsBase, - changeType: 'ONBOARDING', - createdBy: userId, - city: data.city || '北京', - accountId: data.socialAccountId || null, - }, - }) + // 劳务/实习协议不创建社保公积金记录 + if (!isNoSocialContract) { + await tx.employeeSocialInsRecord.create({ + data: { + orgId, + employeeId: emp.id, + startMonth: socialInsStartMonth, + endMonth: null, + base: socialInsBase, + changeType: 'ONBOARDING', + createdBy: userId, + city: data.city || '北京', + accountId: data.socialAccountId || null, + }, + }) - await tx.employeeHousingFundRecord.create({ - data: { - orgId, - employeeId: emp.id, - startMonth: housingFundStartMonth, - endMonth: null, - base: housingFundBase, - changeType: 'ONBOARDING', - createdBy: userId, - city: data.city || '北京', - accountId: data.housingAccountId || null, - }, - }) + await tx.employeeHousingFundRecord.create({ + data: { + orgId, + employeeId: emp.id, + startMonth: housingFundStartMonth, + endMonth: null, + base: housingFundBase, + changeType: 'ONBOARDING', + createdBy: userId, + city: data.city || '北京', + accountId: data.housingAccountId || null, + }, + }) + } await tx.salaryChangeRecord.create({ data: { @@ -555,12 +558,14 @@ export async function rehireEmployee(orgId: string, userId: string, id: string, const performanceSalaryNum = data.performanceSalary != null ? Number(data.performanceSalary) : (employee.performanceSalary ? Number(decrypt(employee.performanceSalary)) || 0 : 0) const newMonthlySalary = data.baseSalary != null ? baseSalaryNum + performanceSalaryNum : salaryNum const city = data.city || employee.city || '北京' - const rawSocialInsBase = data.socialInsBase != null ? Number(data.socialInsBase) : salaryNum - const rawHousingFundBase = data.housingFundBase != null ? Number(data.housingFundBase) : salaryNum - const socialInsBase = await clampSocialInsBase(orgId, rawSocialInsBase, city) - const housingFundBase = await clampHousingFundBase(orgId, rawHousingFundBase, city) - const socialInsStartMonth = data.socialInsStartMonth || newHireMonth - const housingFundStartMonth = data.housingFundStartMonth || newHireMonth + // 劳务协议/实习协议:不缴纳社保公积金 + const isNoSocialContract = data.contract && ['LABOR', 'INTERNSHIP'].includes(data.contract.contractType) + const rawSocialInsBase = isNoSocialContract ? 0 : (data.socialInsBase != null ? Number(data.socialInsBase) : salaryNum) + const rawHousingFundBase = isNoSocialContract ? 0 : (data.housingFundBase != null ? Number(data.housingFundBase) : salaryNum) + const socialInsBase = isNoSocialContract ? 0 : await clampSocialInsBase(orgId, rawSocialInsBase, city) + const housingFundBase = isNoSocialContract ? 0 : await clampHousingFundBase(orgId, rawHousingFundBase, city) + const socialInsStartMonth = isNoSocialContract ? '' : (data.socialInsStartMonth || newHireMonth) + const housingFundStartMonth = isNoSocialContract ? '' : (data.housingFundStartMonth || newHireMonth) const prevHireMonth = prevMonth(newHireMonth) // 关闭旧社保缴费记录 @@ -612,33 +617,36 @@ export async function rehireEmployee(orgId: string, userId: string, id: string, }, }) - // 创建新社保缴费记录 - await prisma.employeeSocialInsRecord.create({ - data: { - orgId, - employeeId: id, - startMonth: socialInsStartMonth, - endMonth: null, - base: socialInsBase, - changeType: 'REHIRE', - createdBy: userId, - city: data.city || employee.city || '北京', - }, - }) + // 劳务/实习协议不创建社保公积金记录 + if (!isNoSocialContract) { + // 创建新社保缴费记录 + await prisma.employeeSocialInsRecord.create({ + data: { + orgId, + employeeId: id, + startMonth: socialInsStartMonth, + endMonth: null, + base: socialInsBase, + changeType: 'REHIRE', + createdBy: userId, + city: data.city || employee.city || '北京', + }, + }) - // 创建新公积金缴费记录 - await prisma.employeeHousingFundRecord.create({ - data: { - orgId, - employeeId: id, - startMonth: housingFundStartMonth, - endMonth: null, - base: housingFundBase, - changeType: 'REHIRE', - createdBy: userId, - city: data.city || employee.city || '北京', - }, - }) + // 创建新公积金缴费记录 + await prisma.employeeHousingFundRecord.create({ + data: { + orgId, + employeeId: id, + startMonth: housingFundStartMonth, + endMonth: null, + base: housingFundBase, + changeType: 'REHIRE', + createdBy: userId, + city: data.city || employee.city || '北京', + }, + }) + } // 创建新薪资记录 await prisma.salaryChangeRecord.create({ @@ -792,11 +800,43 @@ export async function updateEmployee(orgId: string, id: string, data: any) { if (data.isWorkInjured !== undefined) updateData.isWorkInjured = data.isWorkInjured if (data.socialInsBase !== undefined) { const city = data.city || employee.city || '北京' - updateData.socialInsBase = await clampSocialInsBase(orgId, Number(data.socialInsBase), city) + // 查询最新合同类型,劳务/实习协议强制基数为0 + const latestContract = await prisma.laborContract.findFirst({ + where: { employeeId: id }, + orderBy: { createdAt: 'desc' }, + select: { contractType: true }, + }) + const isNoSocial = latestContract && ['LABOR', 'INTERNSHIP'].includes(latestContract.contractType) + if (isNoSocial) { + updateData.socialInsBase = 0 + // 关闭在保社保记录 + const nowMonth = new Date().toISOString().slice(0, 7) + await prisma.employeeSocialInsRecord.updateMany({ + where: { employeeId: id, endMonth: null }, + data: { endMonth: nowMonth, changeType: 'TERMINATION' }, + }) + } else { + updateData.socialInsBase = await clampSocialInsBase(orgId, Number(data.socialInsBase), city) + } } if (data.housingFundBase !== undefined) { const city = data.city || employee.city || '北京' - updateData.housingFundBase = await clampHousingFundBase(orgId, Number(data.housingFundBase), city) + const latestContract = await prisma.laborContract.findFirst({ + where: { employeeId: id }, + orderBy: { createdAt: 'desc' }, + select: { contractType: true }, + }) + const isNoSocial = latestContract && ['LABOR', 'INTERNSHIP'].includes(latestContract.contractType) + if (isNoSocial) { + updateData.housingFundBase = 0 + const nowMonth = new Date().toISOString().slice(0, 7) + await prisma.employeeHousingFundRecord.updateMany({ + where: { employeeId: id, endMonth: null }, + data: { endMonth: nowMonth, changeType: 'TERMINATION' }, + }) + } else { + updateData.housingFundBase = await clampHousingFundBase(orgId, Number(data.housingFundBase), city) + } } if (data.specialDeduction !== undefined) updateData.specialDeduction = data.specialDeduction if (data.city !== undefined) updateData.city = data.city