feat: 20260815 系统优化 - 全部31项问题修复(P0×6+P1×14+P2×9+P3×2)

P0紧急修复(6项):
- 草稿保存完整恢复所有字段(含socialAvgWage)
- 补偿金批次从compensationBreakdown读取
- 违法解除风险确认UI
- 合同结束日期前后校验(前后端双保险)

P1高优先级(14项):
- 离职日期联动社保/公积金截止月(15号规则)
- 合规检查+工作交接改为软阻断(生成待办)
- 补偿月数(N/N+1/2N/自定义)+计算基数(近12月/合同/自定义)
- 解聘并入花名册操作栏(类型选择跳转向导)
- 合同续签开始日期自动推导(原合同结束日+1天)
- 年龄合规筛查(童工阻断/未成年工/退休警告)
- 编辑入职日期后状态联动(待入职↔在职)
- 转正移植到花名册操作栏+薪资回写
- 男职工无法选择三期

P2体验优化(9项):
- "劳动合同"调整为"用工关系"
- 费用结算新增剩余年假折算(300%日工资)
- 身份证号全域改为"证件号码"(前后端18个文件)
- 手机号查重
- 开具证明+合同续签移植到花名册操作栏
- 批量转正+批量开具证明
- 去掉用工办理模块

P3规划(2项):
- 组织架构+审批流(Department/Position/ApprovalFlow/ApprovalInstance)
- 客服工作台(Ticket/ChatSession+SUPPORT角色)

新增模型: Department/Position/ApprovalFlow/ApprovalInstance/Ticket/TicketMessage/ChatSession/ChatMessage
新增字段: Employee.departmentId/supervisorId
新增角色: SUPPORT

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 12:37:27 +08:00
parent 8cfdd566af
commit e1b5ae9aab
46 changed files with 3455 additions and 206 deletions
+38 -4
View File
@@ -1,7 +1,7 @@
import prisma from '../lib/prisma'
import { encrypt } from '../lib/crypto'
import { encrypt, decrypt } from '../lib/crypto'
import { createDraft as createTerminationDraft, executeTermination } from './termination.service'
import { createEmployee, addContract } from './contract.service'
import { createEmployee, addContract, prevMonth } from './contract.service'
import { runRiskDetection } from './risk.service'
// 13类流程定义
@@ -69,10 +69,44 @@ export async function executeWorkProcess(processId: string, type: string, formDa
const { employeeId, regularSalary } = formData
if (employeeId) {
if (regularSalary) {
const employee = await prisma.employee.findFirst({ where: { id: employeeId, orgId } })
const oldSalary = employee ? Number(decrypt(employee.monthlySalary)) || 0 : 0
const newSalary = Number(regularSalary) || 0
await prisma.employee.update({
where: { id: employeeId },
data: { monthlySalary: encrypt(String(regularSalary)) },
})
// 记录薪资变更(试用期薪资 → 转正薪资)
if (oldSalary !== newSalary) {
const now = new Date()
const nowMonth = now.toISOString().slice(0, 7)
await prisma.salaryChangeRecord.updateMany({
where: { employeeId, endMonth: null },
data: { endMonth: prevMonth(nowMonth) },
})
await prisma.salaryChangeRecord.create({
data: {
orgId,
employeeId,
oldSalary,
newSalary,
effectiveDate: now,
effectiveMonth: nowMonth,
endMonth: null,
changeType: 'CONFIRM',
reason: '试用期转正薪资调整',
createdBy: userId,
},
})
}
// 校验转正薪资与最新合同试用期薪资是否一致(提示性校验)
const latestContract = await prisma.laborContract.findFirst({
where: { employeeId, orgId },
orderBy: { createdAt: 'desc' },
})
if (latestContract?.probationSalary && latestContract.probationSalary !== newSalary) {
console.warn(`[CONFIRM] 转正薪资 ¥${newSalary} 与合同试用期薪资 ¥${latestContract.probationSalary} 不一致,员工: ${employeeId}`)
}
await runRiskDetection(orgId)
}
}
@@ -275,13 +309,13 @@ ${body}
const templates: Record<string, (data: any, org: string) => string> = {
INCOME_CERT: (data, org) => wrapHtml('收入证明', `
<div class="body">兹证明 ${data.employeeName || '___'}身份证号${data.idCardNumber || '___'})系我单位员工,自 ${data.hireDate || '___'} 起在我单位工作,现任 ${data.position || '___'} 职务。</div>
<div class="body">兹证明 ${data.employeeName || '___'}证件号码${data.idCardNumber || '___'})系我单位员工,自 ${data.hireDate || '___'} 起在我单位工作,现任 ${data.position || '___'} 职务。</div>
<div class="body">该员工近一年平均月收入为人民币 ${data.monthlyIncome || '___'} 元(税前)。</div>
<div class="body">本证明仅用于 ${data.purpose || '___'},不作其他用途。</div>
<div class="body">特此证明。</div>
<div class="sign">${org}<br/>${new Date().toLocaleDateString('zh-CN')}</div>`),
LEAVING_CERT: (data, org) => wrapHtml('离职证明', `
<div class="body">兹证明 ${data.employeeName || '___'}身份证号${data.idCardNumber || '___'})自 ${data.hireDate || '___'}${data.leaveDate || '___'} 在我单位工作,最后职务为 ${data.position || '___'}。</div>
<div class="body">兹证明 ${data.employeeName || '___'}证件号码${data.idCardNumber || '___'})自 ${data.hireDate || '___'}${data.leaveDate || '___'} 在我单位工作,最后职务为 ${data.position || '___'}。</div>
<div class="body">该员工已于 ${data.leaveDate || '___'} 与我单位解除劳动关系,双方已办妥交接手续。</div>
<div class="body">特此证明。</div>
<div class="sign">${org}<br/>${new Date().toLocaleDateString('zh-CN')}</div>`),