From 1f545fb489a69a5c9bcb2e778b83756ea528d3c4 Mon Sep 17 00:00:00 2001 From: selfrelease Date: Sat, 15 Aug 2026 17:26:14 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A1=A5=E5=85=85=E7=A4=BE=E4=BF=9D?= =?UTF-8?q?=E6=88=AA=E6=AD=A2=E6=9C=88=E8=87=AA=E5=8A=A8=E6=8E=A8=E5=AF=BC?= =?UTF-8?q?+=E8=8D=89=E7=A8=BFschema=E5=AD=97=E6=AE=B5+=E9=9D=A2=E5=8C=85?= =?UTF-8?q?=E5=B1=91=E6=96=87=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 测试验证发现3个问题并修复: 1. TASK-007 社保联动:Organization.socialInsCutoffDay 字段缺失, createDraft 未自动推导社保/公积金截止月。 - 新增 Organization.socialInsCutoffDay 字段(默认15日) - createDraft 中根据离职日期与截止日比较,自动推导截止月 - cutoffDay 日前离职 → 截止月=离职月-1,日后 → 截止月=离职月 2. TASK-002 补偿金合计:createTerminationDraftSchema 缺少 compensationBreakdown 和 checklistOverrides 字段,导致 zod parse 时被过滤。已补充字段声明。 3. TASK-028 去掉用工办理:Breadcrumb 中 /work-process 标签仍为 "用工办理",已改为"批量流程"。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- backend/prisma/schema.prisma | 1 + backend/src/schemas/termination.schema.ts | 4 +++ backend/src/services/termination.service.ts | 31 +++++++++++++++++-- frontend/src/components/layout/Breadcrumb.tsx | 2 +- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index b0f01e3..ff57145 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -140,6 +140,7 @@ model Organization { esignTrainingEnabled Boolean @default(false) // 培训记录电子签 esignPerformanceEnabled Boolean @default(false) // 绩效考核电子签 esignDisciplinaryEnabled Boolean @default(false) // 违纪记录电子签 + socialInsCutoffDay Int @default(15) // 社保/公积金截止日:每月该日前离职→截止月=离职月-1,该日后→截止月=离职月 createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/backend/src/schemas/termination.schema.ts b/backend/src/schemas/termination.schema.ts index 826cf00..66ffd01 100644 --- a/backend/src/schemas/termination.schema.ts +++ b/backend/src/schemas/termination.schema.ts @@ -44,7 +44,9 @@ export const createTerminationDraftSchema = z.object({ reason: z.string().max(200).optional(), terminationDate: z.string().optional(), compensation: z.number().min(0).optional(), + compensationBreakdown: z.any().optional(), handoverItems: z.array(z.any()).optional(), + checklistOverrides: z.any().optional(), remark: z.string().max(500).optional(), }) @@ -52,6 +54,8 @@ export const updateTerminationDraftSchema = z.object({ reason: z.string().max(200).optional(), terminationDate: z.string().optional(), compensation: z.number().min(0).optional(), + compensationBreakdown: z.any().optional(), handoverItems: z.array(z.any()).optional(), + checklistOverrides: z.any().optional(), remark: z.string().max(500).optional(), }) diff --git a/backend/src/services/termination.service.ts b/backend/src/services/termination.service.ts index b5508eb..3845dfc 100644 --- a/backend/src/services/termination.service.ts +++ b/backend/src/services/termination.service.ts @@ -8,6 +8,13 @@ function dateToMonth(date: Date): string { return `${y}-${m}` } +/** 计算上一个月,格式 YYYY-MM */ +function prevMonth(month: string): string { + const [y, m] = month.split('-').map(Number) + if (m === 1) return `${y - 1}-12` + return `${y}-${String(m - 1).padStart(2, '0')}` +} + export interface ChecklistItem { key: string label: string @@ -572,6 +579,26 @@ export async function createDraft(orgId: string, userId: string, data: any) { const { level } = assessRisk(employee, data.reason || 'NEGOTIATED') + // 自动推导社保/公积金截止月(基于组织 socialInsCutoffDay 配置) + let socialInsEndMonth = data.socialInsEndMonth || null + let housingFundEndMonth = data.housingFundEndMonth || null + if (data.terminationDate && !socialInsEndMonth) { + const org = await prisma.organization.findUnique({ where: { id: orgId }, select: { socialInsCutoffDay: true } }) + const cutoffDay = org?.socialInsCutoffDay ?? 15 + const termDate = new Date(data.terminationDate) + const termDay = termDate.getDate() + const termMonth = dateToMonth(termDate) + // cutoffDay 日前离职 → 截止月 = 离职月 - 1;cutoffDay 日后离职 → 截止月 = 离职月 + if (termDay <= cutoffDay) { + const prevMon = prevMonth(termMonth) + socialInsEndMonth = prevMon + housingFundEndMonth = prevMon + } else { + socialInsEndMonth = termMonth + housingFundEndMonth = termMonth + } + } + const record = await prisma.terminationRecord.create({ data: { orgId, @@ -581,8 +608,8 @@ export async function createDraft(orgId: string, userId: string, data: any) { terminationDate: data.terminationDate ? new Date(data.terminationDate) : new Date(), resignationReason: data.resignationReason || null, compensation: data.compensation || 0, - socialInsEndMonth: data.socialInsEndMonth || null, - housingFundEndMonth: data.housingFundEndMonth || null, + socialInsEndMonth, + housingFundEndMonth, riskLevel: level, checklist: data.checklist || {}, remark: data.remark || null, diff --git a/frontend/src/components/layout/Breadcrumb.tsx b/frontend/src/components/layout/Breadcrumb.tsx index cf45252..705f5a9 100644 --- a/frontend/src/components/layout/Breadcrumb.tsx +++ b/frontend/src/components/layout/Breadcrumb.tsx @@ -15,7 +15,7 @@ const ROUTE_MAP: Record = { '/': { group: '工作台', label: '总览' }, '/calendar': { group: '工作台', label: '工作日历' }, '/roster': { group: '员工管理', label: '花名册' }, - '/work-process': { group: '员工管理', label: '用工办理' }, + '/work-process': { group: '员工管理', label: '批量流程' }, '/attendance': { group: '员工管理', label: '考勤确认' }, '/leave-approval': { group: '员工管理', label: '休假审批' }, '/termination': { group: '员工管理', label: '解聘补偿' },