feat: 已离职/解聘员工可重新入职
1. 后端新增 rehireEmployee 函数和 POST /employees/:id/rehire 接口 2. 校验:仅已离职员工可重新入职,新入职日期须晚于上次离职日期 3. 复用员工已有基本信息,只需填写新入职日期和劳动合同 4. 前端花名册已离职员工显示「重新入职」按钮+弹窗(RehireModal)
This commit is contained in:
@@ -203,6 +203,72 @@ export async function createEmployee(orgId: string, userId: string, data: any) {
|
||||
return { id: employee.id }
|
||||
}
|
||||
|
||||
// 重新入职:复用已有员工基本信息,更新入职日期和状态,可选创建新合同
|
||||
export async function rehireEmployee(orgId: string, userId: string, id: string, data: any) {
|
||||
const employee = await prisma.employee.findFirst({
|
||||
where: { id, orgId },
|
||||
include: { terminations: { orderBy: { terminationDate: 'desc' }, take: 1 } },
|
||||
})
|
||||
if (!employee) {
|
||||
throw { code: 'NOT_FOUND', message: '员工不存在' }
|
||||
}
|
||||
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
const isResigned = employee.terminations.some((t) => t.terminationDate <= today)
|
||||
if (!isResigned) {
|
||||
throw { code: 'CONFLICT', message: '该员工当前在职,无需重新入职' }
|
||||
}
|
||||
|
||||
const newHireDate = new Date(data.hireDate)
|
||||
const latestTerm = employee.terminations[0]
|
||||
if (latestTerm && newHireDate <= latestTerm.terminationDate) {
|
||||
throw { code: 'VALIDATION_ERROR', message: '新入职日期必须晚于上次离职/解聘日期' }
|
||||
}
|
||||
|
||||
await prisma.employee.update({
|
||||
where: { id },
|
||||
data: {
|
||||
hireDate: newHireDate,
|
||||
status: 'ACTIVE',
|
||||
isPregnant: data.isPregnant || false,
|
||||
isInMedicalPeriod: data.isInMedicalPeriod || false,
|
||||
isWorkInjured: data.isWorkInjured || false,
|
||||
},
|
||||
})
|
||||
|
||||
if (data.contract && data.contract.contractType !== 'UNSIGNED') {
|
||||
const contractMonths = data.contract.endDate
|
||||
? Math.ceil(daysBetween(new Date(data.contract.endDate), new Date(data.contract.startDate)) / 30.44)
|
||||
: data.contract.contractYears * 12
|
||||
|
||||
const probationCheck = validateProbation(contractMonths, data.contract.probationMonths)
|
||||
if (!probationCheck.valid) {
|
||||
throw { code: 'VALIDATION_ERROR', message: probationCheck.message }
|
||||
}
|
||||
|
||||
await prisma.laborContract.create({
|
||||
data: {
|
||||
orgId,
|
||||
employeeId: id,
|
||||
signDate: data.contract.signDate ? new Date(data.contract.signDate) : null,
|
||||
startDate: new Date(data.contract.startDate),
|
||||
endDate: data.contract.endDate ? new Date(data.contract.endDate) : null,
|
||||
contractType: data.contract.contractType,
|
||||
signMethod: data.contract.signMethod || 'PAPER',
|
||||
contractYears: data.contract.contractYears || 3,
|
||||
probationMonths: data.contract.probationMonths || 0,
|
||||
probationSalary: data.contract.probationSalary || 0,
|
||||
createdBy: userId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
await runRiskDetection(orgId)
|
||||
|
||||
return { id }
|
||||
}
|
||||
|
||||
export async function updateEmployee(orgId: string, id: string, data: any) {
|
||||
const employee = await prisma.employee.findFirst({ where: { id, orgId } })
|
||||
if (!employee) {
|
||||
|
||||
Reference in New Issue
Block a user