88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
/**
|
||
* 一次性校正脚本:按花名册自动激活 + 同步角色(全量)
|
||
*
|
||
* 规则(与 lib/auto-personnel-rules.ts 一致):
|
||
* - 有活跃绑定 + 花名册在职(非 RESIGNED)→ 自动激活(status=active, isActive=true)
|
||
* - M 级(levelType='M')或 isLeadership → DEPT_ADMIN;否则 USER
|
||
* - 不降级 SYSTEM_ADMIN / ADMIN(人工授予的高权限保持不变)
|
||
*
|
||
* 用法:npx tsx --env-file=.env scripts/backfill-auto-personnel.ts # 预演(默认)
|
||
* npx tsx --env-file=.env scripts/backfill-auto-personnel.ts --apply # 实际写入
|
||
*/
|
||
import { prisma } from '@/lib/prisma'
|
||
import {
|
||
getAuthoritativePersonnelForUser,
|
||
shouldAutoActivate,
|
||
deriveRoleFromPersonnel,
|
||
} from '@/lib/auto-personnel-rules'
|
||
|
||
const APPLY = process.argv.includes('--apply')
|
||
|
||
;(async () => {
|
||
console.log(APPLY ? '=== 实际写入模式 ===' : '=== 预演模式(不写入)===')
|
||
|
||
const users = await prisma.user.findMany({
|
||
where: { archivedAt: null },
|
||
select: { id: true, username: true, realName: true, role: true, status: true, isActive: true },
|
||
orderBy: { username: 'asc' },
|
||
})
|
||
console.log(`账号总数(未归档): ${users.length}\n`)
|
||
|
||
let wouldActivate = 0
|
||
let wouldRoleChange = 0
|
||
const plan: string[] = []
|
||
|
||
for (const u of users) {
|
||
const personnel = await getAuthoritativePersonnelForUser(u.id)
|
||
if (!personnel) continue // 无绑定,跳过
|
||
|
||
const changes: string[] = []
|
||
|
||
// 激活判定
|
||
const shouldActivate = shouldAutoActivate(personnel)
|
||
const currentStatus = u.status || (u.isActive ? 'active' : 'pending')
|
||
if (shouldActivate && currentStatus !== 'active') {
|
||
wouldActivate++
|
||
changes.push(`激活: ${currentStatus} -> active`)
|
||
}
|
||
|
||
// 角色派生
|
||
const derived = deriveRoleFromPersonnel(personnel)
|
||
if (u.role !== 'SYSTEM_ADMIN' && u.role !== 'ADMIN' && u.role !== derived) {
|
||
wouldRoleChange++
|
||
changes.push(`角色: ${u.role} -> ${derived}`)
|
||
}
|
||
|
||
if (changes.length > 0) {
|
||
plan.push(`${u.realName ?? u.username} (${u.username}): ${changes.join(', ')}`)
|
||
|
||
if (APPLY) {
|
||
await prisma.user.update({
|
||
where: { id: u.id },
|
||
data: {
|
||
...(shouldActivate && currentStatus !== 'active'
|
||
? { status: 'active', isActive: true, statusChangedAt: new Date(), statusChangedBy: 'auto-花名册在册' }
|
||
: {}),
|
||
...(u.role !== 'SYSTEM_ADMIN' && u.role !== 'ADMIN' && u.role !== derived
|
||
? { role: derived }
|
||
: {}),
|
||
},
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log(`计划激活: ${wouldActivate} 人`)
|
||
console.log(`计划角色变更: ${wouldRoleChange} 人`)
|
||
console.log('\n明细:')
|
||
for (const line of plan) console.log(` ${line}`)
|
||
|
||
if (APPLY) {
|
||
console.log(`\n已写入 ${plan.length} 条记录`)
|
||
} else {
|
||
console.log('\n(预演结束,未写入任何数据。加 --apply 实际执行)')
|
||
}
|
||
|
||
await prisma.$disconnect()
|
||
})().catch((e) => { console.error(e); process.exit(1) })
|