refactor: WorkProcess 业务逻辑复用原有 service

- HIRE 调用 createEmployee(含社保/公积金/薪资/部门记录)
- RENEW/CUSTOM_CONTRACT 调用 addContract(含重复检查、试用期验证、风险检测)
- TERMINATE/RESCIND 调用 createTerminationDraft + executeTermination(含风险评级、合规清单、社保截止)
- CONFIRM 增加 probationEndDate 更新和 runRiskDetection
- FLEXIBLE 调用 createEmployee + addContract
- 前端 TERMINATE/RESCIND 表单增加 reason 和 compensation 字段
- 原有 Roster 入口保持不变,两条路径共用同一套 service
This commit is contained in:
freedakgmail
2026-07-30 10:27:47 +08:00
parent 42e0c650a4
commit cea7eb07c4
2 changed files with 93 additions and 93 deletions
+89 -93
View File
@@ -1,6 +1,9 @@
import prisma from '../lib/prisma'
import { encrypt } from '../lib/crypto'
import crypto from 'crypto'
import { createDraft as createTerminationDraft, executeTermination, createResignation } from './termination.service'
import { createEmployee, addContract, batchRenew } from './contract.service'
import { runRiskDetection } from './risk.service'
// 13类流程定义
export const PROCESS_TYPES: Record<string, { label: string; description: string; icon: string }> = {
@@ -33,38 +36,25 @@ export const PROCESS_STATUS: Record<string, { label: string; color: string }> =
export async function executeWorkProcess(processId: string, type: string, formData: any, orgId: string, userId: string) {
switch (type) {
case 'HIRE': {
// 创建员工 + 合同
const { name, department, hireDate, monthlySalary, phone, idCardNumber, gender, contractStartDate, contractEndDate, contractType = 'FIXED' } = formData
const idCardHash = idCardNumber ? crypto.createHash('sha256').update(idCardNumber).digest('hex') : null
const employee = await prisma.employee.create({
data: {
orgId,
name,
department: department || '未分配',
hireDate: new Date(hireDate),
monthlySalary: encrypt(String(monthlySalary || 0)),
phone: phone || null,
idCardNumber: idCardNumber ? encrypt(idCardNumber) : null,
idCardHash,
gender: gender || null,
createdBy: userId,
},
const result = await createEmployee(orgId, userId, {
name,
department: department || '未分配',
hireDate,
monthlySalary: monthlySalary || 0,
phone,
idCardNumber,
gender,
contract: contractStartDate ? {
contractType,
startDate: contractStartDate,
endDate: contractEndDate || undefined,
contractYears: 3,
probationMonths: 0,
probationSalary: 0,
} : undefined,
})
if (contractStartDate) {
await prisma.laborContract.create({
data: {
orgId,
employeeId: employee.id,
startDate: new Date(contractStartDate),
endDate: contractEndDate ? new Date(contractEndDate) : null,
contractType: contractType as any,
signMethod: 'PAPER',
contractYears: 3,
createdBy: userId,
},
})
}
return { employeeId: employee.id }
return { employeeId: result.id }
}
case 'ONBOARD': {
const { employeeId, hireDate } = formData
@@ -79,17 +69,26 @@ export async function executeWorkProcess(processId: string, type: string, formDa
case 'CONFIRM': {
const { employeeId, confirmDate, regularSalary } = formData
if (employeeId) {
const updateData: any = {}
if (regularSalary) {
updateData.monthlySalary = encrypt(String(regularSalary))
}
if (confirmDate) {
updateData.probationEndDate = new Date(confirmDate)
}
if (Object.keys(updateData).length > 0) {
await prisma.employee.update({
where: { id: employeeId },
data: { monthlySalary: encrypt(String(regularSalary)) },
data: updateData,
})
await runRiskDetection(orgId)
}
}
return { employeeId }
}
case 'RENEW': {
const { employeeId, oldContractId, newStartDate, newEndDate, newSalary, contractType = 'FIXED', contractYears = 3 } = formData
// 截止旧合同
if (oldContractId) {
const oldEndDate = new Date(newStartDate)
oldEndDate.setDate(oldEndDate.getDate() - 1)
@@ -98,21 +97,16 @@ export async function executeWorkProcess(processId: string, type: string, formDa
data: { endDate: oldEndDate },
})
}
// 创建新合同(复用 addContract 的验证逻辑)
if (employeeId) {
const oldContract = oldContractId ? await prisma.laborContract.findUnique({ where: { id: oldContractId } }) : null
const contract = await prisma.laborContract.create({
data: {
orgId,
employeeId,
signDate: new Date(),
startDate: new Date(newStartDate),
endDate: newEndDate ? new Date(newEndDate) : null,
contractType: contractType as any,
signMethod: 'PAPER',
contractYears: Number(contractYears) || 3,
renewalCount: (oldContract?.renewalCount || 0) + 1,
createdBy: userId,
},
const result = await addContract(orgId, userId, {
employeeId,
startDate: newStartDate,
endDate: newEndDate || undefined,
contractType,
contractYears: Number(contractYears) || 3,
probationMonths: 0,
probationSalary: 0,
})
if (newSalary) {
await prisma.employee.update({
@@ -120,39 +114,54 @@ export async function executeWorkProcess(processId: string, type: string, formDa
data: { monthlySalary: encrypt(String(newSalary)) },
})
}
return { employeeId, newContractId: contract.id }
return { employeeId, newContractId: result.id }
}
return { employeeId }
}
case 'TERMINATE': {
const { employeeId, contractId, terminateDate } = formData
const { employeeId, contractId, terminateDate, reason = 'EXPIRED', compensation = 0 } = formData
// 截止合同
if (contractId) {
await prisma.laborContract.update({
where: { id: contractId },
data: { endDate: new Date(terminateDate) },
})
}
// 通过 termination service 创建解聘记录(含风险评级、合规清单)
if (employeeId) {
await prisma.employee.update({
where: { id: employeeId },
data: { status: 'RESIGNED' },
const draft = await createTerminationDraft(orgId, userId, {
employeeId,
type: 'TERMINATION',
reason,
terminationDate: terminateDate,
compensation,
})
// 直接执行(WorkProcess 流程审批已通过)
await executeTermination(orgId, draft.id, userId)
return { employeeId, terminationRecordId: draft.id }
}
return { employeeId }
}
case 'RESCIND': {
const { employeeId, contractId, rescindDate } = formData
const { employeeId, contractId, rescindDate, reason = 'NEGOTIATED', compensation = 0 } = formData
// 截止合同
if (contractId) {
await prisma.laborContract.update({
where: { id: contractId },
data: { endDate: new Date(rescindDate) },
})
}
// 通过 termination service 创建解聘记录(含风险评级、合规清单)
if (employeeId) {
await prisma.employee.update({
where: { id: employeeId },
data: { status: 'RESIGNED' },
const draft = await createTerminationDraft(orgId, userId, {
employeeId,
type: 'TERMINATION',
reason,
terminationDate: rescindDate,
compensation,
})
await executeTermination(orgId, draft.id, userId)
return { employeeId, terminationRecordId: draft.id }
}
return { employeeId }
}
@@ -179,53 +188,40 @@ export async function executeWorkProcess(processId: string, type: string, formDa
case 'CUSTOM_CONTRACT': {
const { employeeId, contractStartDate, contractEndDate, contractType = 'FIXED', signMethod = 'PAPER', contractYears = 3 } = formData
if (employeeId) {
const contract = await prisma.laborContract.create({
data: {
orgId,
employeeId,
signDate: new Date(),
startDate: new Date(contractStartDate),
endDate: contractEndDate ? new Date(contractEndDate) : null,
contractType: contractType as any,
signMethod: signMethod as any,
contractYears: Number(contractYears) || 3,
createdBy: userId,
},
const result = await addContract(orgId, userId, {
employeeId,
startDate: contractStartDate,
endDate: contractEndDate || undefined,
contractType,
signMethod,
contractYears: Number(contractYears) || 3,
probationMonths: 0,
probationSalary: 0,
})
return { employeeId, newContractId: contract.id }
return { employeeId, newContractId: result.id }
}
return {}
}
case 'FLEXIBLE': {
const { name, phone, idCardNumber, department, agreementStartDate, agreementEndDate, payMethod } = formData
const idCardHash = idCardNumber ? crypto.createHash('sha256').update(idCardNumber).digest('hex') : null
const employee = await prisma.employee.create({
data: {
orgId,
name,
department: department || '灵活用工',
hireDate: new Date(agreementStartDate),
monthlySalary: encrypt('0'),
phone: phone || null,
idCardNumber: idCardNumber ? encrypt(idCardNumber) : null,
idCardHash,
createdBy: userId,
},
const empResult = await createEmployee(orgId, userId, {
name,
department: department || '灵活用工',
hireDate: agreementStartDate,
monthlySalary: 0,
phone,
idCardNumber,
})
const contract = await prisma.laborContract.create({
data: {
orgId,
employeeId: employee.id,
signDate: new Date(),
startDate: new Date(agreementStartDate),
endDate: agreementEndDate ? new Date(agreementEndDate) : null,
contractType: 'LABOR',
signMethod: 'PAPER',
contractYears: 1,
createdBy: userId,
},
const contractResult = await addContract(orgId, userId, {
employeeId: empResult.id,
startDate: agreementStartDate,
endDate: agreementEndDate || undefined,
contractType: 'LABOR',
contractYears: 1,
probationMonths: 0,
probationSalary: 0,
})
return { employeeId: employee.id, newContractId: contract.id }
return { employeeId: empResult.id, newContractId: contractResult.id }
}
case 'INFO_SUBMIT': {
const { employeeId, ...updateFields } = formData
+4
View File
@@ -108,11 +108,15 @@ const FORM_FIELDS: Record<string, { key: string; label: string; type: 'text' | '
{ key: 'employeeId', label: '员工ID', type: 'text' },
{ key: 'contractId', label: '合同ID', type: 'text' },
{ key: 'terminateDate', label: '终止日期', type: 'date' },
{ key: 'reason', label: '终止原因', type: 'select', options: ['EXPIRED', 'NEGOTIATED', 'FAULT', 'NONFAULT', 'LAYOFF'] },
{ key: 'compensation', label: '经济补偿金', type: 'number' },
],
RESCIND: [
{ key: 'employeeId', label: '员工ID', type: 'text' },
{ key: 'contractId', label: '合同ID', type: 'text' },
{ key: 'rescindDate', label: '解除日期', type: 'date' },
{ key: 'reason', label: '解除原因', type: 'select', options: ['NEGOTIATED', 'FAULT', 'NONFAULT', 'LAYOFF'] },
{ key: 'compensation', label: '经济补偿金', type: 'number' },
],
LEAVING_CERT: [
{ key: 'employeeName', label: '员工姓名', type: 'text' },