From cea7eb07c468ff32378482d5cd491c9b1ca4358d Mon Sep 17 00:00:00 2001 From: freedakgmail Date: Thu, 30 Jul 2026 10:27:47 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20WorkProcess=20=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=A4=8D=E7=94=A8=E5=8E=9F=E6=9C=89=20servic?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - HIRE 调用 createEmployee(含社保/公积金/薪资/部门记录) - RENEW/CUSTOM_CONTRACT 调用 addContract(含重复检查、试用期验证、风险检测) - TERMINATE/RESCIND 调用 createTerminationDraft + executeTermination(含风险评级、合规清单、社保截止) - CONFIRM 增加 probationEndDate 更新和 runRiskDetection - FLEXIBLE 调用 createEmployee + addContract - 前端 TERMINATE/RESCIND 表单增加 reason 和 compensation 字段 - 原有 Roster 入口保持不变,两条路径共用同一套 service --- backend/src/services/work-process.service.ts | 182 +++++++++---------- frontend/src/pages/WorkProcess.tsx | 4 + 2 files changed, 93 insertions(+), 93 deletions(-) diff --git a/backend/src/services/work-process.service.ts b/backend/src/services/work-process.service.ts index 0cc9687..72bcdf5 100644 --- a/backend/src/services/work-process.service.ts +++ b/backend/src/services/work-process.service.ts @@ -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 = { @@ -33,38 +36,25 @@ export const PROCESS_STATUS: Record = 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 diff --git a/frontend/src/pages/WorkProcess.tsx b/frontend/src/pages/WorkProcess.tsx index bf556dd..8fe6380 100644 --- a/frontend/src/pages/WorkProcess.tsx +++ b/frontend/src/pages/WorkProcess.tsx @@ -108,11 +108,15 @@ const FORM_FIELDS: Record