import { writeFile } from 'node:fs/promises'; // Organization names were observed on Workdesk. Membership, employees and // every count below are synthetic, not an export of production HR data. const groups = [ ['business-management', '사업관리', 'office', []], ['business-planning', '경영기획', 'office', ['경영기획 셀', '사업관리 셀']], ['talent-growth', '인재성장', 'office', ['HR기획 셀', '자산관리 셀']], ['integrated-system', '통합시스템 Div', 'div', ['IS 1팀', 'IS 2팀', 'IS 3팀']], ['design-planning', '디자인기획', 'office', ['UX 셀', '영상 셀', '편집 셀']], ['solution-sales', '솔루션영업', 'office', ['S/W 셀']], ]; const affiliations = [ ['hanmac', '(주)한맥기술'], ['saman', '(주)삼안'], ['jangheon', '(주)장헌'], ['jangheon-industry', '장헌산업'], ['ptc', 'PTC'], ['halla', '한라산업개발'], ['baron', '바론컨설턴트'], ].map(([id, name]) => ({ id, name })); const organizations = [{ id: 'general-planning', parentId: null, name: '총괄기획실', type: 'root', leaderId: 'mock-leader-00', displayOrder: 0 }]; // Invented display names only; never sourced from a Workdesk employee capture. const names = [ '김솔', '이도윤', '박하준', '정지우', '최예린', '한준서', '오수아', '강민서', '윤시우', '서다은', '배지안', '임서준', '송하린', '조유찬', '신도하', '문예은', '권지호', '안채원', '유시온', '홍서아', '고은우', '남하윤', '백도현', '노유나', '장태오', '양서진', '진서율', '구민재', '전하은', '심이준', '차소율', '우지율', '손예준', '함다온', '허지유', '황서우', '성유빈', '곽지후', '류다인', '하주원', '이봄', ]; const employees = [{ id: 'mock-leader-00', organizationId: 'general-planning', affiliationId: 'hanmac', name: names[0], position: '경영진', jobTitle: '실장', profileImage: null, workStatus: 'active' }]; let person = 1; for (const [index, [id, name, type, cells]] of groups.entries()) { const leaderId = `mock-leader-${String(index + 1).padStart(2, '0')}`; organizations.push({ id, parentId: 'general-planning', name, type, leaderId, displayOrder: index }); employees.push({ id: leaderId, organizationId: id, affiliationId: ['hanmac', 'saman', 'baron'][index % 3], name: names[employees.length], position: '수석', jobTitle: type === 'div' ? '디비전장' : '팀장', profileImage: null, workStatus: 'active' }); const employeeOrganizations = cells.length ? cells.map((cell, cellIndex) => { const childId = `${id}-${cellIndex + 1}`; organizations.push({ id: childId, parentId: id, name: cell, type: cell.includes('팀') ? 'team' : 'cell', leaderId: null, displayOrder: cellIndex }); return childId; }) : [id]; for (const childId of employeeOrganizations) for (let member = 0; member < (cells.length ? 3 : 1); member++) { const employeeId = `mock-employee-${String(person).padStart(2, '0')}`; const isTeamLeader = childId.startsWith('integrated-system-') && member === 0; employees.push({ id: employeeId, organizationId: childId, affiliationId: ['hanmac', 'saman', 'ptc', 'baron'][person % 4], name: names[employees.length], position: ['책임', '선임', '연구'][member % 3], jobTitle: isTeamLeader ? '팀장' : null, profileImage: null, workStatus: person === 3 ? 'dispatched' : person === 25 ? 'onLeave' : 'active' }); if (isTeamLeader) organizations.find(item => item.id === childId).leaderId = employeeId; person++; } } const fixture = { schemaVersion: '0.1-draft', organizations, employees, affiliations, relations: [], presentation: { title: '총괄기획실 조직도', description: '실제 조직명 · 가상 직원 정보 및 인원 통계 · 운영 인원수가 아닙니다.', hubText: '협업 · 소통 허브', groups: { showEmployees: true, showSummary: true, showDispatched: true, showOnLeave: true, showAffiliations: true }, organizationOrder: ['general-planning', ...groups.map(([id]) => id)], }, metadata: { asOfDate: '2026-10-12', dataVersion: 'p1-virtual-employees-v1', updateNote: '운영 HR 정보와 무관한 가상 구성' }, }; await writeFile(new URL('./data-p1.json', import.meta.url), `${JSON.stringify(fixture, null, 2)}\n`); console.log(`P1 fixture: ${organizations.length} organizations / ${employees.length} synthetic employees`);