448 lines
17 KiB
JavaScript
448 lines
17 KiB
JavaScript
import pkg from 'xlsx';
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
const { readFile, utils } = pkg;
|
|
|
|
// 임시 ID 생성 및 도우미 함수
|
|
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 {
|
|
const workbook = readFile('c:/Project/HM ITAM/SampleData_PC.xlsx');
|
|
const sheet = workbook.Sheets[workbook.SheetNames[0]];
|
|
|
|
// header: 1로 읽어 2차원 배열을 획득
|
|
const rawRows = utils.sheet_to_json(sheet, { header: 1 });
|
|
|
|
// 첫 번째 행은 헤더이므로 제외
|
|
const dataRows = rawRows.slice(1);
|
|
|
|
const parsedPCs = [];
|
|
let pcIndex = 0;
|
|
let designKihuckCount = 0;
|
|
|
|
for (const row of dataRows) {
|
|
// 빈 행 건너뛰기 (성명, 부서, 팀명 모두 비어있으면 데이터가 없는 행으로 판단)
|
|
if (!row[0] && !row[1] && !row[2] && !row[3] && !row[4]) {
|
|
continue;
|
|
}
|
|
|
|
const deptRaw = cleanValue(row[0]);
|
|
const teamRaw = cleanValue(row[1]);
|
|
const corpRaw = cleanValue(row[2]); // C열: 소속 (NEW)
|
|
const jobRaw = cleanValue(row[3]); // D열: 직무 (밀림)
|
|
const nameRaw = cleanValue(row[4]); // E열: 성명 (밀림)
|
|
|
|
// 특정 사용자 제외 필터
|
|
if (nameRaw === '한치영' || nameRaw === '공용') {
|
|
continue;
|
|
}
|
|
|
|
const posRaw = cleanValue(row[5]); // F열: 직급 (밀림)
|
|
const mainboardRaw = cleanValue(row[6]); // G열: 메인보드 (밀림)
|
|
const cpuRaw = cleanValue(row[7]); // H열: CPU (밀림)
|
|
const cpuYearRaw = row[8]; // I열: CPU 출시연도 (밀림)
|
|
const gpuRaw = cleanValue(row[9]); // J열: GPU (밀림)
|
|
const gpuYearRaw = row[10]; // K열: GPU 출시연도 (밀림)
|
|
const ramRaw = cleanValue(row[11]); // L열: RAM (밀림)
|
|
const ssd1Raw = cleanValue(row[12]);// M열: SDD1 (밀림)
|
|
const ssd2Raw = cleanValue(row[13]);// N열: SDD2 (밀림)
|
|
const hdd1Raw = cleanValue(row[14]);// O열: HDD1 (밀림)
|
|
const hdd2Raw = cleanValue(row[15]);// P열: HDD2 (밀림)
|
|
const hdd3Raw = cleanValue(row[16]);// Q열: HDD3 (밀림)
|
|
const hdd4Raw = cleanValue(row[17]);// R열: HDD4 (밀림)
|
|
|
|
// W열(22번째 인덱스) -> 구매일자
|
|
const dateRaw = cleanValue(row[22]);
|
|
// X열(23번째 인덱스) -> 비고
|
|
const memoRaw = cleanValue(row[23]);
|
|
|
|
// 1. 법인 매핑 (엑셀 C열의 실제 소속 우선 사용, 없을 시 순환 지정)
|
|
const purchase_corp = corpRaw !== '-' ? corpRaw : CORPS[pcIndex % CORPS.length];
|
|
|
|
// 2. 재고PC 판단 및 상태 설정
|
|
const isStock = teamRaw === '재고PC';
|
|
const hw_status = isStock ? '창고보관' : '운영중';
|
|
|
|
// 3. 성명 정제
|
|
let user_current = nameRaw;
|
|
if (isStock) {
|
|
// 재고PC인 경우 직무 컬럼(row[3])에 성명이 들어가 있음
|
|
user_current = jobRaw !== '-' ? jobRaw : '재고장비';
|
|
}
|
|
|
|
// 4. 직무 정제
|
|
let user_position = jobRaw;
|
|
if (isStock) {
|
|
user_position = '재고PC';
|
|
} else if (user_position === '-' || user_position === 'undefined' || !user_position || ['안용주', '김민수', '심영표', '이수창A', '조병철', '윤진호', '김대영', '박정웅', '김유식'].includes(user_position)) {
|
|
// 직무가 유효하지 않거나 이름인 경우 정제
|
|
if (nameRaw === '장종찬' || posRaw === '사장') {
|
|
user_position = '기획자';
|
|
} else if (nameRaw === '노트북' || nameRaw === '공용') {
|
|
user_position = '기획자';
|
|
} else {
|
|
// 팀명/부서 기준 매핑
|
|
const combined = (deptRaw + ' ' + teamRaw).toUpperCase();
|
|
if (combined.includes('개발') || combined.includes('SOLUTION') || combined.includes('WEB') || combined.includes('ERP')) {
|
|
user_position = '개발자';
|
|
} else if (combined.includes('BIM') || combined.includes('구조') || combined.includes('설계') || combined.includes('터널') || combined.includes('상하수도') || combined.includes('수자원') || combined.includes('건설') || combined.includes('CM')) {
|
|
user_position = '엔지니어';
|
|
} else if (combined.includes('디자인') || combined.includes('GRAPHICS')) {
|
|
user_position = '디자이너';
|
|
} else {
|
|
user_position = '기획자';
|
|
}
|
|
}
|
|
}
|
|
|
|
// 만약 직무가 'BIM모델러' 인 경우, 그대로 유지
|
|
if (jobRaw === 'BIM모델러') {
|
|
user_position = 'BIM모델러';
|
|
}
|
|
|
|
// 개발자/디자이너 세부 직무 분리 로직 적용
|
|
if (user_position === '개발자') {
|
|
const nameUpper = nameRaw.trim();
|
|
const teamUpper = teamRaw.toUpperCase();
|
|
|
|
if (nameUpper === '조찬영' || nameUpper === '김용연') {
|
|
user_position = 'AI 개발자';
|
|
} else if (
|
|
teamUpper.includes('그래픽스') ||
|
|
teamUpper.includes('MODELER') ||
|
|
teamUpper.includes('HMEG') ||
|
|
teamUpper.includes('EG-BIM') ||
|
|
teamUpper.includes('GSIM') ||
|
|
teamUpper.includes('STRANA')
|
|
) {
|
|
user_position = '3D 개발자';
|
|
} else if (
|
|
teamUpper.includes('WEB') ||
|
|
teamUpper.includes('솔루션개발') ||
|
|
teamUpper.includes('ERP') ||
|
|
teamUpper.includes('전산')
|
|
) {
|
|
user_position = '웹 개발자';
|
|
} else {
|
|
user_position = '프로그램 개발자';
|
|
}
|
|
} else if (user_position === '디자이너') {
|
|
const teamUpper = teamRaw.toUpperCase();
|
|
if (teamUpper.includes('디자인셀')) {
|
|
user_position = 'UXUI 디자이너';
|
|
} else if (teamUpper.includes('디자인기획')) {
|
|
// 디자인기획팀 소속 중 약 40%는 3D 디자이너, 60%는 편집 디자이너
|
|
if (designKihuckCount % 10 < 4) {
|
|
user_position = '3D 디자이너';
|
|
} else {
|
|
user_position = '편집 디자이너';
|
|
}
|
|
designKihuckCount++;
|
|
} else {
|
|
user_position = '편집 디자이너';
|
|
}
|
|
}
|
|
|
|
// 5. 구매일자 포맷 가공 (YYYY-MM)
|
|
let purchase_date = '2022-01'; // 기본값
|
|
if (dateRaw !== '-') {
|
|
if (dateRaw.length === 6 && !isNaN(dateRaw)) {
|
|
purchase_date = `${dateRaw.substring(0, 4)}-${dateRaw.substring(4, 6)}`;
|
|
} else if (dateRaw.length === 4 && !isNaN(dateRaw)) {
|
|
purchase_date = `${dateRaw}-01`;
|
|
} else {
|
|
purchase_date = dateRaw;
|
|
}
|
|
} else if (cpuYearRaw && !isNaN(cpuYearRaw)) {
|
|
purchase_date = `${cpuYearRaw}-01`;
|
|
}
|
|
|
|
// 6. 도입 금액(purchase_amount) 책정
|
|
let purchase_amount = '1500000';
|
|
const cpuUpper = cpuRaw.toUpperCase();
|
|
const gpuUpper = gpuRaw.toUpperCase();
|
|
|
|
if (cpuUpper.includes('I9') || cpuUpper.includes('RYZEN 9') || cpuUpper.includes('RYZEN9') || gpuUpper.includes('4080') || gpuUpper.includes('4090')) {
|
|
purchase_amount = '3500000';
|
|
} else if (cpuUpper.includes('I7') || cpuUpper.includes('RYZEN 7') || cpuUpper.includes('RYZEN7') || gpuUpper.includes('3070') || gpuUpper.includes('4070') || gpuUpper.includes('A2000')) {
|
|
purchase_amount = '2200000';
|
|
} else if (cpuUpper.includes('I5') || cpuUpper.includes('RYZEN 5') || cpuUpper.includes('RYZEN5') || gpuUpper.includes('3060') || gpuUpper.includes('2060')) {
|
|
purchase_amount = '1500000';
|
|
} else if (cpuYearRaw && parseInt(cpuYearRaw) < 2020) {
|
|
purchase_amount = '800000';
|
|
} else {
|
|
purchase_amount = '950000';
|
|
}
|
|
|
|
// 7. MAC 주소 생성 (16진수 포맷)
|
|
const mac_address = `00:1A:2B:3C:4D:${pcIndex.toString(16).toUpperCase().padStart(2, '0')}`;
|
|
|
|
parsedPCs.push({
|
|
id: randomId(),
|
|
asset_type: '개인PC',
|
|
purchase_corp,
|
|
asset_code: 'PC-24' + String(pcIndex).padStart(3, '0'),
|
|
purchase_date,
|
|
user_current,
|
|
user_position,
|
|
current_dept: teamRaw !== '-' ? teamRaw : deptRaw,
|
|
previous_dept: pcIndex % 8 === 0 ? '기획팀' : '-',
|
|
location: '서울본사 7층',
|
|
manager_primary: '김IT',
|
|
manager_secondary: '이IT',
|
|
model_name: mainboardRaw !== '-' ? mainboardRaw : '사내 표준 데스크톱',
|
|
os: 'Windows 11 Pro',
|
|
cpu: cpuRaw,
|
|
gpu: gpuRaw,
|
|
ram: ramRaw,
|
|
ssd_1: ssd1Raw,
|
|
ssd_2: ssd2Raw,
|
|
ssd_3: '-',
|
|
hdd_1: hdd1Raw,
|
|
hdd_2: hdd2Raw,
|
|
hdd_3: hdd3Raw,
|
|
hdd_4: hdd4Raw,
|
|
mainboard: mainboardRaw,
|
|
ip_address: '192.168.0.' + (10 + (pcIndex % 240)),
|
|
purchase_amount,
|
|
purchase_vendor: 'LG전자/삼성전자/HP',
|
|
approval_document: '2024_상반기_PC구매_' + pcIndex,
|
|
memo: memoRaw !== '-' ? memoRaw : (isStock ? '재고 보유 분' : '임직원 지급용'),
|
|
asset_name: `개인PC ${pcIndex + 1}`,
|
|
mac_address,
|
|
hw_status
|
|
});
|
|
|
|
pcIndex++;
|
|
}
|
|
|
|
console.log(`Successfully parsed ${parsedPCs.length} PCs from excel file.`);
|
|
|
|
// dummyData.ts 의 나머지 데이터(dummyServers 등)를 포함하여 전체 파일을 새로 씁니다.
|
|
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(parsedPCs, null, 2)};
|
|
|
|
// ────────────────────────────────────────────────────────
|
|
// 2. 기타 자산 더미 데이터 (서버, 스토리지, 소프트웨어 등)
|
|
// ────────────────────────────────────────────────────────
|
|
|
|
export const dummyServers: any[] = Array.from({ length: 15 }).map((_, i) => ({
|
|
id: randomId(),
|
|
asset_type: '서버',
|
|
type2: i % 2 === 0 ? '물리' : '가상',
|
|
purchase_corp: getRandomCorp(),
|
|
asset_code: \`SRV-24\${String(i).padStart(3, '0')}\`,
|
|
purchase_date: randomPurchaseYM(),
|
|
asset_purpose: i % 2 === 0 ? '운영 웹 서버' : '사내망 DB 서버',
|
|
current_dept: '인프라팀',
|
|
previous_dept: '-',
|
|
location: 'IDC 센터 1-A',
|
|
manager_primary: '박서버',
|
|
manager_secondary: '최백업',
|
|
ip_address: \`10.0.0.\${10 + i}\`,
|
|
ip_address_2: \`192.168.100.\${10 + i}\`,
|
|
remote_tool: 'RDP / SSH',
|
|
remote_id: \`admin_\${i}\`,
|
|
remote_pw: '********',
|
|
model_name: 'Dell PowerEdge R750',
|
|
os: 'Ubuntu 22.04 LTS',
|
|
cpu: 'Intel Xeon Gold 6330',
|
|
ram: '128GB',
|
|
gpu: i % 3 === 0 ? 'NVIDIA A100' : '-',
|
|
ssd_1: '1TB NVMe',
|
|
ssd_2: '1TB NVMe',
|
|
hdd_1: '4TB HDD',
|
|
monitoring: 'Zabbix Agent',
|
|
purchase_amount: '8500000',
|
|
purchase_vendor: '델테크놀로지스',
|
|
approval_document: \`2024_IDC_확장품의_\sign\${i}\`,
|
|
memo: '서버 랙 3번 위치',
|
|
asset_name: \`운영 서버 \${i+1}\`,
|
|
mac_address: \`00:1A:2B:3C:4E:\${String(i).padStart(2, '0')}\`,
|
|
hw_status: '운영중'
|
|
}));
|
|
|
|
export const dummyStorages: any[] = Array.from({ length: 8 }).map((_, i) => ({
|
|
id: randomId(),
|
|
asset_type: '스토리지',
|
|
purchase_corp: getRandomCorp(),
|
|
asset_code: \`STR-24\${String(i).padStart(3, '0')}\`,
|
|
asset_name: \`공용 스토리지 \${i+1}\`,
|
|
location: 'IDC 센터 1-A',
|
|
model_name: 'Synology RS4021xs+',
|
|
volume: '100TB',
|
|
manager_primary: '박서버',
|
|
manager_secondary: '최백업',
|
|
ip_address: \`10.0.0.\${50 + i}\`,
|
|
mac_address: \`00:1A:2B:3C:4F:\${String(i).padStart(2, '0')}\`,
|
|
purchase_date: randomPurchaseYM(),
|
|
purchase_amount: '12000000',
|
|
purchase_vendor: '시놀로지코리아',
|
|
approval_document: \`2024_스토리지구매_\${i}\`,
|
|
memo: '부서별 백업본 저장용',
|
|
os: 'Synology DSM',
|
|
asset_purpose: '데이터 백업',
|
|
hw_status: '운영중'
|
|
}));
|
|
|
|
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('c:/Project/HM ITAM/src/core/dummyData.ts', newDummyDataFileContent, 'utf-8');
|
|
console.log('✅ dummyData.ts file updated successfully.');
|
|
} catch (e) {
|
|
console.error('❌ Failed to update dummy data:', e);
|
|
}
|