import pkg from 'xlsx'; import * as fs from 'fs'; import * as path from 'path'; const { readFile, utils } = pkg; const randomId = () => Math.random().toString(36).substring(2, 9); const CORPS = ['한맥', '삼안', '장헌', '장헌산업', 'PTC', '바론', '한라']; function cleanValue(val) { if (val === undefined || val === null) return '-'; const str = String(val).trim(); return str === '' ? '-' : str; } try { // 1. 기존 dummyPCs 로딩 const dummyDataPath = 'c:/Project/HM ITAM/src/core/dummyData.ts'; const content = fs.readFileSync(dummyDataPath, 'utf-8'); const matchPCs = content.match(/export const dummyPCs: any\[\] = (\[[\s\S]*?\]);/); if (!matchPCs) { console.error('Failed to parse dummyPCs from dummyData.ts'); process.exit(1); } const dummyPCs = JSON.parse(matchPCs[1]); console.log(`Loaded ${dummyPCs.length} existing PCs from dummyData.ts`); // 2. SampleData_SVR.xlsx 파싱 const workbook = readFile('c:/Project/HM ITAM/SampleData_SVR.xlsx'); const parsedServers = []; const parsedStorages = []; const parsedEquips = []; let serverIndex = 0; let storageIndex = 0; let equipIndex = 0; // ----------------- 시트 1: 합본데이터(공용PC) ----------------- const sheetPC = workbook.Sheets['합본데이터(공용PC)']; const rawPC = utils.sheet_to_json(sheetPC, { header: 1 }); const rowsPC = rawPC.slice(1).filter(row => row.some(val => val !== undefined && val !== null && String(val).trim() !== '')); for (const row of rowsPC) { const teamRaw = cleanValue(row[0]); const svrNoRaw = cleanValue(row[1]); const assetNameRaw = cleanValue(row[2]); const typeRaw = cleanValue(row[3]); const detailRaw = cleanValue(row[4]); const locRaw = cleanValue(row[5]); const mgr1Raw = cleanValue(row[6]); const mgr2Raw = cleanValue(row[7]); const osRaw = cleanValue(row[8]); const osVerRaw = cleanValue(row[9]); const osBuildRaw = cleanValue(row[10]); const modelRaw = cleanValue(row[11]); const mainboardRaw = cleanValue(row[12]); const cpuRaw = cleanValue(row[13]); const ramRaw = cleanValue(row[14]); const gpuRaw = cleanValue(row[15]); const ssd1Raw = cleanValue(row[16]); const ssd2Raw = cleanValue(row[17]); const hdd1Raw = cleanValue(row[18]); const hdd2Raw = cleanValue(row[19]); const hdd3Raw = cleanValue(row[20]); const hdd4Raw = cleanValue(row[21]); const ipAddress = '172.16.10.' + (50 + (serverIndex % 150)); const randomCorp = CORPS[serverIndex % CORPS.length]; // 서비스 분류 판단 let service_type = '내부서비스'; const detailUpper = detailRaw.toUpperCase(); const assetUpper = assetNameRaw.toUpperCase(); const teamUpper = teamRaw.toUpperCase(); if (teamUpper.includes('회의실') || assetUpper.includes('회의실') || assetUpper.includes('사이니지')) { service_type = '회의용/공용'; } else if ( detailUpper.includes('SAAS') || detailUpper.includes('웹서비스') || detailUpper.includes('운영') || detailUpper.includes('WAS') || detailUpper.includes('MYSTATION') || detailUpper.includes('CLOUD') || detailUpper.includes('홈페이지') || detailUpper.includes('WEB') || detailUpper.includes('외주') || assetUpper.includes('CLOUD') || assetUpper.includes('웹서비스') || assetUpper.includes('운영') ) { service_type = '외부서비스'; } // 방치 의심 판단 const is_inactive = ( detailUpper.includes('원격 및 로컬접근 불가') || detailUpper.includes('철수예정') || detailUpper.includes('미사용') || detailUpper.includes('구형 OS') ); // 실시간 리소스 및 네트워크 가상 데이터 생성 let cpu_usage = 0; let ram_usage = 0; let network_traffic = '0 GB'; if (is_inactive) { cpu_usage = 0; ram_usage = 0; network_traffic = '0 GB (N/A)'; } else if (service_type === '회의용/공용') { cpu_usage = Math.floor(Math.random() * 10) + 2; // 2%~12% ram_usage = Math.floor(Math.random() * 15) + 5; // 5%~20% network_traffic = (Math.random() * 1.5 + 0.1).toFixed(1) + ' GB'; } else if (service_type === '외부서비스') { // 일부 저사양 운영/SaaS 서버는 병목 현상을 시뮬레이션하기 위해 과부하 부여 const isUnderSpec = !gpuRaw.toUpperCase().includes('RTX 30') && !gpuRaw.toUpperCase().includes('RTX 40') && (cpuRaw.toUpperCase().includes('I5') || ramRaw.toUpperCase().includes('16GB') || cpuRaw === '-'); if (isUnderSpec) { cpu_usage = Math.floor(Math.random() * 15) + 81; // 81%~95% (과부하) ram_usage = Math.floor(Math.random() * 10) + 86; // 86%~95% } else { cpu_usage = Math.floor(Math.random() * 30) + 40; // 40%~70% ram_usage = Math.floor(Math.random() * 20) + 60; // 60%~80% } network_traffic = (Math.random() * 1500 + 300).toFixed(0) + ' GB'; } else { // 내부서비스 // Abaqus 해석용이나 Pix4D 등 고부하 내부 인프라도 부하율 높게 부여 const isHighLoad = detailUpper.includes('ABAQUS') || detailUpper.includes('PIX4D') || detailUpper.includes('영상 렌더링') || detailUpper.includes('TERRA'); if (isHighLoad) { cpu_usage = Math.floor(Math.random() * 20) + 70; // 70%~90% ram_usage = Math.floor(Math.random() * 20) + 75; // 75%~95% } else { cpu_usage = Math.floor(Math.random() * 35) + 15; // 15%~50% ram_usage = Math.floor(Math.random() * 30) + 20; // 20%~50% } network_traffic = (Math.random() * 300 + 10).toFixed(0) + ' GB'; } const assetItem = { id: randomId(), asset_type: typeRaw !== '-' ? typeRaw : '공용PC', purchase_corp: randomCorp, asset_code: 'SVR-24' + String(serverIndex).padStart(3, '0'), purchase_date: '2023-03', asset_purpose: detailRaw, current_dept: teamRaw, previous_dept: '-', location: locRaw, manager_primary: mgr1Raw, manager_secondary: mgr2Raw, ip_address: ipAddress, remote_tool: 'RDP / VNC', model_name: modelRaw !== '-' ? modelRaw : (mainboardRaw !== '-' ? mainboardRaw : '사내 표준 공용PC'), os: osRaw !== '-' ? `${osRaw} (${osVerRaw})` : 'Windows 10', cpu: cpuRaw, ram: ramRaw, gpu: gpuRaw, ssd_1: ssd1Raw, ssd_2: ssd2Raw, hdd_1: hdd1Raw, hdd_2: hdd2Raw, hdd_3: hdd3Raw, hdd_4: hdd4Raw, monitoring: service_type === '외부서비스' ? '대상' : '비대상', purchase_amount: gpuRaw.toUpperCase().includes('RTX 4080') || gpuRaw.toUpperCase().includes('RTX 3090') ? '3500000' : '1500000', purchase_vendor: '다나와', approval_document: '2023_공용PC_도입_' + serverIndex, memo: is_inactive ? '방치 의심 장비 (회수 필요)' : '정상 운영 장비', asset_name: assetNameRaw, mac_address: `00:1A:2B:3C:5E:${serverIndex.toString(16).toUpperCase().padStart(2, '0')}`, hw_status: is_inactive ? '수리/대기' : '운영중', service_type: service_type, is_inactive: is_inactive, cpu_usage: cpu_usage, ram_usage: ram_usage, network_traffic: network_traffic }; // 스토리지로 보낼 자산들 (유형이 NAS/DAS이거나 자산명에 NAS가 들어가면) if (typeRaw.toUpperCase().includes('NAS') || typeRaw.toUpperCase().includes('DAS') || assetUpper.includes('NAS') || assetUpper.includes('DAS')) { assetItem.asset_code = 'STO-24' + String(storageIndex).padStart(3, '0'); assetItem.volume = hdd1Raw !== '-' ? hdd1Raw : '10TB'; parsedStorages.push(assetItem); storageIndex++; } else { parsedServers.push(assetItem); serverIndex++; } } // ----------------- 시트 2: 합본데이터(NAS) ----------------- const sheetNAS = workbook.Sheets['합본데이터(NAS)']; const rawNAS = utils.sheet_to_json(sheetNAS, { header: 1 }); const rowsNAS = rawNAS.slice(1).filter(row => row.some(val => val !== undefined && val !== null && String(val).trim() !== '')); for (const row of rowsNAS) { const teamRaw = cleanValue(row[0]); const svrNoRaw = cleanValue(row[1]); const assetNameRaw = cleanValue(row[2]); const typeRaw = cleanValue(row[3]); const detailRaw = cleanValue(row[4]); const locRaw = cleanValue(row[5]); const mgr1Raw = cleanValue(row[6]); const mgr2Raw = cleanValue(row[7]); const toolRaw = cleanValue(row[8]); const ipRaw = cleanValue(row[9]); const ip2Raw = cleanValue(row[10]); const idRaw = cleanValue(row[11]); const pwRaw = cleanValue(row[12]); const osRaw = cleanValue(row[15]); const osVerRaw = cleanValue(row[16]); const osBuildRaw = cleanValue(row[17]); const modelRaw = cleanValue(row[18]); const cpuRaw = cleanValue(row[19]); const ramRaw = cleanValue(row[20]); const gpuRaw = cleanValue(row[21]); const ssd1Raw = cleanValue(row[22]); const ssd2Raw = cleanValue(row[23]); const hdd1Raw = cleanValue(row[24]); const hdd2Raw = cleanValue(row[25]); const hdd3Raw = cleanValue(row[26]); const hdd4Raw = cleanValue(row[27]); const randomCorp = CORPS[storageIndex % CORPS.length]; // NAS는 기본적으로 내부 백업/공유용 인프라 const service_type = '내부서비스'; const is_inactive = false; // NAS 실시간 리소스 가상 데이터 const cpu_usage = Math.floor(Math.random() * 25) + 15; // 15%~40% const ram_usage = Math.floor(Math.random() * 35) + 30; // 30%~65% const network_traffic = (Math.random() * 600 + 50).toFixed(0) + ' GB'; const assetItem = { id: randomId(), asset_type: typeRaw !== '-' ? typeRaw : '공용 NAS', purchase_corp: randomCorp, asset_code: 'STO-24' + String(storageIndex).padStart(3, '0'), purchase_date: '2022-08', asset_purpose: detailRaw, current_dept: teamRaw !== '-' ? teamRaw : '디자인팀', previous_dept: '-', location: locRaw, manager_primary: mgr1Raw, manager_secondary: mgr2Raw, ip_address: ipRaw !== '-' ? ipRaw : '172.16.42.' + (100 + storageIndex), remote_tool: toolRaw !== '-' ? toolRaw : 'Web GUI', model_name: modelRaw !== '-' ? modelRaw : 'Synology 공용 NAS', os: osRaw !== '-' ? `${osRaw} ${osVerRaw}` : 'DSM 7.x', cpu: cpuRaw, ram: ramRaw, gpu: gpuRaw, ssd_1: ssd1Raw, ssd_2: ssd2Raw, hdd_1: hdd1Raw, hdd_2: hdd2Raw, hdd_3: hdd3Raw, hdd_4: hdd4Raw, monitoring: '비대상', purchase_amount: '4500000', purchase_vendor: '시놀로지 총판', approval_document: '2022_스토리지_도입_' + storageIndex, memo: '스토리지 서버 공유 자산', asset_name: assetNameRaw, mac_address: `00:1A:2B:3C:5F:${storageIndex.toString(16).toUpperCase().padStart(2, '0')}`, hw_status: '운영중', service_type: service_type, is_inactive: is_inactive, volume: hdd1Raw !== '-' ? hdd1Raw : '24TB', cpu_usage: cpu_usage, ram_usage: ram_usage, network_traffic: network_traffic }; parsedStorages.push(assetItem); storageIndex++; } console.log(`Parsed Servers: ${parsedServers.length} units`); console.log(`Parsed Storages: ${parsedStorages.length} units`); // 3. 파일 다시 쓰기 const newDummyDataFileContent = `import { HardwareAsset, SoftwareAsset, SWUser, HardwareLog } from './excelHandler'; // 유틸리티: 랜덤 문자열 const randomId = () => Math.random().toString(36).substring(2, 9); // 유틸리티: 랜덤 년월 (YYYY-MM) (최근 10년) const randomPurchaseYM = () => { const currentYear = new Date().getFullYear(); const year = currentYear - Math.floor(Math.random() * 10); const month = String(Math.floor(Math.random() * 12) + 1).padStart(2, '0'); return \`\${year}-\${month}\`; }; // 유틸리티: 랜덤 YYYY-MM-DD const randomDateStr = (maxYearsAgo = 10) => { const currentYear = new Date().getFullYear(); const year = currentYear - Math.floor(Math.random() * maxYearsAgo); const month = String(Math.floor(Math.random() * 12) + 1).padStart(2, '0'); const day = String(Math.floor(Math.random() * 28) + 1).padStart(2, '0'); return \`\${year}-\${month}-\${day}\`; }; const CORPS = ['한맥', '삼안', '장헌', '장헌산업', 'PTC', '바론', '한라']; const getRandomCorp = () => CORPS[Math.floor(Math.random() * CORPS.length)]; // ──────────────────────────────────────────────────────── // 1. SampleData_PC.xlsx 에서 파싱된 PC 데이터 주입 // ──────────────────────────────────────────────────────── export const dummyPCs: any[] = ${JSON.stringify(dummyPCs, null, 2)}; // ──────────────────────────────────────────────────────── // 2. 기타 자산 더미 데이터 (서버, 스토리지, 소프트웨어 등 - 엑셀 파싱 연동) // ──────────────────────────────────────────────────────── export const dummyServers: any[] = ${JSON.stringify(parsedServers, null, 2)}; export const dummyStorages: any[] = ${JSON.stringify(parsedStorages, null, 2)}; export const dummyEquips: any[] = Array.from({ length: 12 }).map((_, i) => ({ id: randomId(), asset_type: '전산비품', purchase_corp: getRandomCorp(), asset_code: \`EQ-24\${String(i).padStart(3, '0')}\`, asset_name: \`네트워크 스위치 \${i+1}\`, location: '전산실 랙 1', manager_primary: '네트워크담당자', ip_address: \`192.168.10.\${200 + i}\`, mac_address: \`00:1A:2B:3C:51:\${String(i).padStart(2, '0')}\`, os: 'Cisco IOS', purchase_date: randomPurchaseYM(), purchase_amount: '150000', purchase_vendor: '다나와', approval_document: \`2024_비품구매_\${i}\`, memo: '사내망 확장용', asset_purpose: '네트워크 분배' })); export const dummyMobiles: any[] = Array.from({ length: 15 }).map((_, i) => ({ id: randomId(), asset_type: '모바일기기', purchase_corp: getRandomCorp(), asset_code: \`MOB-24\${String(i).padStart(3, '0')}\`, asset_name: \`테스트용 단말기 \${i+1}\`, location: '개발2팀', manager_primary: '테스터', os: i % 2 === 0 ? 'Android 14' : 'iOS 17', purchase_date: randomPurchaseYM(), purchase_amount: '900000', purchase_vendor: '삼성전자/애플', approval_document: \`2024_모바일구매_\${i}\`, memo: '앱 호환성 테스트 전용', asset_purpose: 'QA 테스트', ip_address: \`192.168.1.\${10 + i}\`, mac_address: \`00:1A:2B:3C:50:\${String(i).padStart(2, '0')}\` })); export const dummySubSw: any[] = Array.from({ length: 10 }).map((_, i) => ({ id: randomId(), sw_type: '구독SW', sw_field: '업무용/협업', purchase_corp: getRandomCorp(), current_dept: '전사', product_name: \`Microsoft 365 E\${3 + (i%2)}\`, purchase_date: randomDateStr(3), start_date: randomDateStr(1), expired_date: randomDateStr(0), purchase_amount: '150000', asset_count: 50 + i * 5, email_account: \`admin\${i}@hmcorp.com\`, purchase_vendor: '소프트웨어인라이프', memo: '연간 계약 갱신 필요' })); export const dummyPermSw: any[] = Array.from({ length: 5 }).map((_, i) => ({ id: randomId(), sw_type: '영구SW', sw_field: '디자인/설계', purchase_corp: getRandomCorp(), current_dept: '디자인팀', product_name: \`AutoCAD 202\${i%4}\`, purchase_date: randomDateStr(5), start_date: randomDateStr(5), expired_date: '2099-12-31', purchase_amount: '3000000', asset_count: 2, email_account: \`design\${i}@hmcorp.com\`, purchase_vendor: '오토데스크 파트너', memo: 'USB 동글키 보관중' })); export const dummyCloud: any[] = Array.from({ length: 5 }).map((_, i) => ({ id: randomId(), sw_type: '클라우드', asset_mfr: i % 2 === 0 ? 'AWS' : 'GCP', purchase_corp: getRandomCorp(), current_dept: '개발팀', product_name: \`컴퓨팅 인스턴스 Type \${i}\`, email_account: \`awsadmin\${i}@hmcorp.com\`, purchase_method: '법인카드(신한 1234)', purchase_amount: \`\${500000 + i * 100000}\`, asset_count: 1, purchase_vendor: 'AWS/GCP', memo: '환율 변동에 따라 매월 상이함' })); export const dummyDomain: any[] = Array.from({ length: 5 }).map((_, i) => ({ id: randomId(), asset_type: '도메인', purchase_corp: getRandomCorp(), product_name: \`사내 운영 서비스 \${i+1}\`, domain_address: \`service\${i+1}.hmcorp.com\`, start_date: randomDateStr(4), expired_date: randomDateStr(0), purchase_amount: '22000', manager_primary: '인프라팀장', manager_secondary: '인프라담당자', memo: '가비아 자동갱신 설정 완료' })); export const dummySwUsers: any[] = Array.from({ length: 15 }).map((_, i) => ({ id: randomId(), sw_id: dummySubSw[0]?.id || randomId(), purchase_corp: getRandomCorp(), current_dept: '경영지원팀', user_current: \`홍길동\${i}\`, memo: \`SW신청서_2400\${i}\` })); export const dummyLogs: any[] = Array.from({ length: 10 }).map((_, i) => ({ id: randomId(), assetId: dummyPCs[0]?.id || randomId(), date: randomDateStr(1), details: i % 2 === 0 ? '메모리 추가 증설 (16GB -> 32GB)' : '디스플레이 파손 수리', user: 'IT지원팀', cost: i % 2 === 0 ? 80000 : 150000, })); `; fs.writeFileSync(dummyDataPath, newDummyDataFileContent, 'utf-8'); console.log('✅ dummyData.ts file updated successfully with SVR dataset.'); } catch (e) { console.error('❌ Failed to update dummy data:', e); }