d79e3baa34
- 面包屑导航组件,集成至TopNav header - 侧边栏菜单分组间距增大,分组间分隔线 - 制度公示员工阅读签收:PolicyReadRecord模型、portal路由、管理端阅读统计 - 修复Policies.tsx民主程序推进bug(字段名/API路径/参数) - 用工文本模板变量名英文转中文显示 - 通知类型TYPE_LABELS补全(RISK_ALERT/SOCIAL_INS/OVERTIME_ALERT/PAYSLIP_READY) - 通知示例数据补充 - h2标题统一为text-sm font-medium - 新增run.md
90 lines
4.8 KiB
TypeScript
90 lines
4.8 KiB
TypeScript
/**
|
||
* 批量补齐现有示例数据的证据链
|
||
* 运行: npx tsx scripts/seed-evidence.ts
|
||
*/
|
||
|
||
import prisma from '../src/lib/prisma'
|
||
import { sha256 } from '../src/lib/crypto'
|
||
|
||
async function main() {
|
||
const orgId = 'cmry97x7l0000trrp5f9jgng5'
|
||
const systemUserId = 'system-seed'
|
||
let count = 0
|
||
|
||
// 清除旧的 seed 数据
|
||
await prisma.evidenceChain.deleteMany({ where: { createdBy: systemUserId } })
|
||
console.log('Cleared old seed evidence chains')
|
||
|
||
// 1. 员工入职证据链
|
||
const employees = await prisma.employee.findMany({ select: { id: true, name: true, hireDate: true, createdAt: true } })
|
||
for (const emp of employees) {
|
||
const events = [{ action: '员工入职登记', timestamp: emp.createdAt.toISOString(), ip: '127.0.0.1', userAgent: 'system-seed' }]
|
||
const hash = sha256(JSON.stringify(events) + orgId + 'ONBOARD' + emp.id)
|
||
await prisma.evidenceChain.create({
|
||
data: { orgId, category: 'ONBOARD', refId: emp.id, employeeId: emp.id, events: events as any, hash, createdBy: systemUserId, createdAt: emp.createdAt },
|
||
}).catch(() => {})
|
||
count++
|
||
}
|
||
console.log('ONBOARD:', employees.length)
|
||
|
||
// 2. 合同签订证据链
|
||
const contracts = await prisma.laborContract.findMany({ select: { id: true, employeeId: true, createdAt: true } })
|
||
for (const c of contracts) {
|
||
const events = [{ action: '合同签订', timestamp: c.createdAt.toISOString(), ip: '127.0.0.1', userAgent: 'system-seed' }]
|
||
const hash = sha256(JSON.stringify(events) + orgId + 'CONTRACT_SIGN' + c.id)
|
||
await prisma.evidenceChain.create({
|
||
data: { orgId, category: 'CONTRACT_SIGN', refId: c.id, employeeId: c.employeeId, events: events as any, hash, createdBy: systemUserId, createdAt: c.createdAt },
|
||
}).catch(() => {})
|
||
count++
|
||
}
|
||
console.log('CONTRACT_SIGN:', contracts.length)
|
||
|
||
// 3. 工资条确认证据链
|
||
const payslips = await prisma.payslip.findMany({ where: { confirmedAt: { not: null } }, select: { id: true, employeeId: true, confirmedAt: true } })
|
||
for (const p of payslips) {
|
||
const events = [{ action: '工资条确认', timestamp: p.confirmedAt!.toISOString(), ip: '127.0.0.1', userAgent: 'employee-portal' }]
|
||
const hash = sha256(JSON.stringify(events) + orgId + 'PAYSLIP_CONFIRM' + p.id)
|
||
await prisma.evidenceChain.create({
|
||
data: { orgId, category: 'PAYSLIP_CONFIRM', refId: p.id, employeeId: p.employeeId, events: events as any, hash, createdBy: p.employeeId, createdAt: p.confirmedAt! },
|
||
}).catch(() => {})
|
||
count++
|
||
}
|
||
console.log('PAYSLIP_CONFIRM:', payslips.length)
|
||
|
||
// 4. 违纪记录证据链
|
||
const disciplinaries = await prisma.disciplinaryRecord.findMany({ select: { id: true, employeeId: true, createdAt: true, violationType: true, severity: true } })
|
||
const violationMap: Record<string, string> = { LATE: '迟到', ABSENT: '旷工', INSUBORDINATION: '不服从管理', OTHER: '其他违规' }
|
||
for (const d of disciplinaries) {
|
||
const desc = violationMap[d.violationType] || d.violationType
|
||
const events = [{ action: `违纪记录创建(${desc})`, timestamp: d.createdAt.toISOString(), ip: '127.0.0.1', userAgent: 'system-seed' }]
|
||
const hash = sha256(JSON.stringify(events) + orgId + 'DISCIPLINARY' + d.id)
|
||
await prisma.evidenceChain.create({
|
||
data: { orgId, category: 'DISCIPLINARY', refId: d.id, employeeId: d.employeeId, events: events as any, hash, createdBy: systemUserId, createdAt: d.createdAt },
|
||
}).catch(() => {})
|
||
count++
|
||
}
|
||
console.log('DISCIPLINARY:', disciplinaries.length)
|
||
|
||
// 5. 解聘证据链
|
||
const terminations = await prisma.terminationRecord.findMany({ select: { id: true, employeeId: true, createdAt: true, reason: true, status: true } })
|
||
const reasonMap: Record<string, string> = { NEGOTIATED: '协商解除', UNILATERAL: '单方解除', EXPIRY: '合同到期', RESIGNATION: '员工辞职', OTHER: '其他' }
|
||
const statusMap: Record<string, string> = { DRAFT: '草稿', PENDING_APPROVAL: '待审批', APPROVED: '已审批', EXECUTED: '已执行', CANCELLED: '已撤销' }
|
||
for (const t of terminations) {
|
||
const reasonText = reasonMap[t.reason] || t.reason
|
||
const statusText = statusMap[t.status] || t.status
|
||
const events = [{ action: `解聘流程(${reasonText}·${statusText})`, timestamp: t.createdAt.toISOString(), ip: '127.0.0.1', userAgent: 'system-seed' }]
|
||
const hash = sha256(JSON.stringify(events) + orgId + 'TERMINATION' + t.id)
|
||
await prisma.evidenceChain.create({
|
||
data: { orgId, category: 'TERMINATION', refId: t.id, employeeId: t.employeeId, events: events as any, hash, createdBy: systemUserId, createdAt: t.createdAt },
|
||
}).catch(() => {})
|
||
count++
|
||
}
|
||
console.log('TERMINATION:', terminations.length)
|
||
|
||
const total = await prisma.evidenceChain.count()
|
||
console.log(`\n总计插入 ${count} 条,数据库现有 ${total} 条证据链`)
|
||
await prisma.$disconnect()
|
||
}
|
||
|
||
main().catch(console.error)
|