import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const KEYS = ['ccDaily', 'ccWeekly', 'ccMonthly'] as const; function rolesOf(emp: { users: { roles: { role: { code: string } }[] }[] }) { return [...new Set(emp.users.flatMap((u) => u.roles.map((r) => r.role.code)))]; } function isDirector(emp: { title?: string | null; jobRole?: string | null; users: { roles: { role: { code: string } }[] }[] }) { if (/总监/.test(`${emp.title || ''}${emp.jobRole || ''}`)) return true; return rolesOf(emp).some((r) => r.endsWith('_director') || r === 'biz_director' || r === 'owner'); } function parseIds(raw?: string | null) { if (!raw) return []; return [...new Set(raw.split(/[,,、\s]+/).filter((s) => UUID_RE.test(s)))]; } async function main() { const depts = await prisma.department.findMany({ where: { tenantId: '1' }, select: { id: true, parentId: true } }); const byId = new Map(depts.map((d) => [d.id, d])); const people = await prisma.employee.findMany({ where: { tenantId: '1' }, include: { users: { select: { roles: { select: { role: { select: { code: true } } } } } } }, }); const byDept = new Map(); for (const e of people) { const list = byDept.get(e.departmentId) || []; list.push(e); byDept.set(e.departmentId, list); } function scopeDeptIds(start: string, selfId: string) { const scope: string[] = []; const seen = new Set(); let cur: string | null | undefined = start; while (cur && !seen.has(cur)) { seen.add(cur); scope.push(cur); const hasDir = (byDept.get(cur) || []).some((e) => e.id !== selfId && isDirector(e)); if (hasDir) break; cur = byId.get(cur)?.parentId; } return new Set(scope); } let n = 0; for (const emp of people) { const scope = scopeDeptIds(emp.departmentId, emp.id); const dirs = people.filter((d) => scope.has(d.departmentId) && d.id !== emp.id && d.id !== emp.managerId && isDirector(d)); const dirIds = dirs.map((d) => d.id); const allowed = new Set(dirIds); const data: Partial> = {}; for (const key of KEYS) { const cur = parseIds(emp[key]); let next = cur.filter((id) => allowed.has(id)); if (!next.length && dirIds.length && cur.some((id) => id === emp.managerId || !allowed.has(id))) { next = dirIds; } const joined = next.length ? next.join(',') : null; if (joined !== (emp[key] || null)) data[key] = joined; } if (!Object.keys(data).length) continue; await prisma.employee.update({ where: { id: emp.id }, data }); n += 1; console.log(`${emp.name}: ${JSON.stringify(data)}`); } console.log(`updated ${n} / ${people.length} employee cc fields`); } main() .then(async () => prisma.$disconnect()) .catch(async (e) => { console.error(e); await prisma.$disconnect(); process.exit(1); });