From b2784ac279e21415fda2a1bfbc8ddcce454a6c5e Mon Sep 17 00:00:00 2001 From: chenpei Date: Fri, 14 Aug 2026 18:38:54 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=96=B0=E5=A2=9E=E8=8A=B1=E5=90=8D?= =?UTF-8?q?=E4=B8=8E=E7=AD=89=E7=BA=A7=E4=B8=80=E8=87=B4=E6=80=A7=E5=AE=A1?= =?UTF-8?q?=E8=AE=A1=E8=84=9A=E6=9C=AC=EF=BC=88=E6=8E=92=E6=9F=A5=E5=90=8C?= =?UTF-8?q?=E5=90=8D=E4=B8=B2=E6=A1=A3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/audit-flower-mismatch.ts | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 scripts/audit-flower-mismatch.ts diff --git a/scripts/audit-flower-mismatch.ts b/scripts/audit-flower-mismatch.ts new file mode 100644 index 0000000..afcc4b3 --- /dev/null +++ b/scripts/audit-flower-mismatch.ts @@ -0,0 +1,49 @@ +/** + * 串档排查脚本(只读): + * 找出"无花名(外部/离职人员)却带有 M 级等级/负责人标志"的可疑档案。 + * + * 规则(用户确认):有花名 = 正式员工;无花名 = 外部人员/离职人员。 + * 正式员工才应有 M/P 等级;无花名的档案若带等级,极可能是花名册同名串档。 + * + * 用法:npx tsx --env-file=.env scripts/audit-flower-mismatch.ts + */ +import { PrismaClient } from '@prisma/client' +const prisma = new PrismaClient() + +;(async () => { + console.log('=== 花名与等级一致性审计(只读)===\n') + + // 有绑定且带等级但无花名的档案(疑似串档) + const suspicious = await prisma.performanceSurveyEmployeeProfile.findMany({ + where: { + positionLevel: { not: null }, + OR: [{ flowerName: null }, { flowerName: '' }], + }, + select: { + id: true, displayName: true, realName: true, flowerName: true, jobNumber: true, + dingtalkUserId: true, departmentPath: true, positionLevel: true, levelType: true, + isLeadership: true, employmentState: true, + }, + orderBy: { departmentPath: 'asc' }, + }) + + // 过滤:只看有素材库绑定的人(无绑定的花名册人员即使无花名带等级也不是我们关注的) + const boundIds = new Set( + (await prisma.userEmployeeBinding.findMany({ + where: { status: 'ACTIVE' }, + select: { employeeProfileId: true }, + })).map((b) => b.employeeProfileId), + ) + const relevant = suspicious.filter((p) => boundIds.has(p.id)) + + console.log(`无花名但带等级 + 有绑定的档案: ${relevant.length} 条\n`) + for (const p of relevant) { + console.log(`【${p.displayName}】真名=${p.realName ?? '?'} 花名=${p.flowerName ?? '(无)'} 工号=${p.jobNumber ?? '?'}`) + console.log(` 部门=${p.departmentPath ?? '?'}`) + console.log(` 等级=${p.positionLevel}(${p.levelType ?? '?'}) 负责人=${p.isLeadership} 在职=${p.employmentState}`) + console.log(` 钉钉ID=${p.dingtalkUserId ?? '(无)'} 档案ID=${p.id}\n`) + } + + console.log('=== 审计结束(未写入任何数据)===') + await prisma.$disconnect() +})().catch((e) => { console.error(e); process.exit(1) })