diff --git a/backend/src/routes/import.routes.ts b/backend/src/routes/import.routes.ts index 4b797fa..6da98a2 100644 --- a/backend/src/routes/import.routes.ts +++ b/backend/src/routes/import.routes.ts @@ -267,6 +267,34 @@ router.post('/excel', authMiddleware, requireAdmin, upload.single('file'), async if (idCheck.upgraded) idCard = idCheck.upgraded } + // 同企业内身份证查重 + if (idCard) { + const idCardExists = await prisma.employee.findFirst({ + where: { orgId, idCardHash: sha256(idCard) }, + select: { id: true, name: true }, + }) + if (idCardExists) { + result.skipped++ + result.errors.push(`员工第${i + 2}行:证件号码已存在(${idCardExists.name}),跳过`) + result.details.push({ sheet: '员工信息', row: i + 2, name, status: 'skipped', message: '证件号码已存在' }) + continue + } + } + // 同企业内手机号查重 + const importPhone = val(getField(r, '手机号')) + if (importPhone) { + const phoneExists = await prisma.employee.findFirst({ + where: { orgId, phone: importPhone }, + select: { id: true, name: true }, + }) + if (phoneExists) { + result.skipped++ + result.errors.push(`员工第${i + 2}行:手机号已存在(${phoneExists.name}),跳过`) + result.details.push({ sheet: '员工信息', row: i + 2, name, status: 'skipped', message: '手机号已存在' }) + continue + } + } + // 社保基数:值为 0 或「无」表示不参保 const socialInsBaseVal = num(getField(r, '社保基数')) const socialInsOptOut = val(getField(r, '社保基数')) === '无' || val(getField(r, '社保基数')) === '不缴' diff --git a/backend/src/services/contract.service.ts b/backend/src/services/contract.service.ts index 68362a5..808deeb 100644 --- a/backend/src/services/contract.service.ts +++ b/backend/src/services/contract.service.ts @@ -536,6 +536,27 @@ export async function updateEmployee(orgId: string, id: string, data: any) { throw { code: 'NOT_FOUND', message: '员工不存在' } } + // 手机号查重(同组织内排除自身,phone 唯一影响员工端登录) + if (data.phone !== undefined && data.phone) { + const phoneExists = await prisma.employee.findFirst({ + where: { orgId, phone: data.phone, NOT: { id } }, + select: { id: true, name: true, department: true, status: true }, + }) + if (phoneExists) { + throw { code: 'DUPLICATE_PHONE', message: `手机号已存在:${phoneExists.name}(${phoneExists.department}),同企业内手机号不可重复` } + } + } + // 身份证查重(同组织内排除自身) + if (data.idCardNumber !== undefined && data.idCardNumber) { + const idCardExists = await prisma.employee.findFirst({ + where: { orgId, idCardHash: sha256(data.idCardNumber), NOT: { id } }, + select: { id: true, name: true, department: true, status: true }, + }) + if (idCardExists) { + throw { code: 'DUPLICATE_ID_CARD', message: `证件号码已存在:${idCardExists.name}(${idCardExists.department}),同企业内身份证号不可重复` } + } + } + const updateData: any = {} if (data.name !== undefined) updateData.name = data.name if (data.department !== undefined) updateData.department = data.department