fix: 补充社保截止月自动推导+草稿schema字段+面包屑文案

测试验证发现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>
This commit is contained in:
selfrelease
2026-08-15 17:26:14 +08:00
parent 101cfcf508
commit 1f545fb489
4 changed files with 35 additions and 3 deletions
+1
View File
@@ -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
@@ -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(),
})
+29 -2
View File
@@ -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,
@@ -15,7 +15,7 @@ const ROUTE_MAP: Record<string, BreadcrumbItem> = {
'/': { 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: '解聘补偿' },