const XLSX = require('xlsx'); const mysql = require('mysql2/promise'); const dotenv = require('dotenv'); const path = require('path'); dotenv.config({ path: path.join(__dirname, '../.env') }); const { DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT } = process.env; // 용량 정제 함수 function parseCapacity(val) { if (!val || val === '0' || val === 0) return null; let str = String(val).toUpperCase(); // 1. 괄호와 그 안의 내용 제거 str = str.replace(/\(.*\)/g, '').trim(); // 2. 숫자와 단위 분리 const numMatch = str.match(/[\d.]+/); if (!numMatch) return null; let num = parseFloat(numMatch[0]); let unit = 'GB'; // 기본 단위 if (str.includes('TB')) { unit = 'TB'; } else if (str.includes('GB')) { // 4자리수 GB인 경우 TB로 전환 (지시사항 1번) if (num >= 1000) { num = num / 1000; unit = 'TB'; } else { unit = 'GB'; } } else { // 단위가 명시되지 않은 경우 숫자의 크기로 판단 if (num >= 1000) { num = num / 1000; unit = 'TB'; } } return { capacity: parseFloat(num.toFixed(2)), unit: unit }; } async function importAssets() { const connection = await mysql.createConnection({ host: DB_HOST, user: DB_USER, password: DB_PASS, database: DB_NAME, port: parseInt(DB_PORT || '3306') }); console.log('🚀 [Step 1] 데이터 로드 및 사전 준비 (정제 로직 강화)...'); const workbook = XLSX.readFile('asset_pc (2026.06.15).xlsx'); const sheet = workbook.Sheets[workbook.SheetNames[0]]; const rawData = XLSX.utils.sheet_to_json(sheet); // system_users 데이터 맵 const [userRows] = await connection.query('SELECT emp_no, user_name, dept_name, position, status FROM system_users'); const userMap = new Map(); userRows.forEach(u => userMap.set(String(u.emp_no), u)); // 기존 자산 중복 체크용 (emp_no + asset_type + category + user_current) const [existingAssets] = await connection.query('SELECT emp_no, asset_type, category, user_current FROM asset_core'); const existingSet = new Set(); existingAssets.forEach(a => { existingSet.add(`${a.emp_no || ''}|${a.asset_type}|${a.category}|${a.user_current}`); }); console.log(`📊 처리 대상 데이터: ${rawData.length}건`); let skipCount = 0; let insertCount = 0; let errorCount = 0; for (let i = 0; i < rawData.length; i++) { const row = rawData[i]; const empNo = row.emp_no ? String(row.emp_no) : ''; // 사번 없는 행 처리 (지시사항 3번) const assetType = row.asset_type || '개인PC'; const category = row.category || 'PC'; const userCurrent = row.user_current || ''; // 중복 체크 const dupKey = `${empNo}|${assetType}|${category}|${userCurrent}`; if (existingSet.has(dupKey)) { skipCount++; continue; } // [Step 2] 데이터 정제 const matchedUser = empNo ? userMap.get(empNo) : null; const userName = matchedUser ? matchedUser.user_name : userCurrent; const deptName = matchedUser ? matchedUser.dept_name : (row.current_dept || ''); const position = matchedUser ? matchedUser.position : ''; const d1 = parseInt(row.purchase_date_1) || 0; const d2 = parseInt(row.purchase_date_2) || 0; const purchaseDate = Math.max(d1, d2) > 0 ? String(Math.max(d1, d2)) : ''; const assetId = `PC_20260615_${String(i + 1).padStart(4, '0')}`; const now = new Date().toISOString().replace('T', ' ').substring(0, 19); try { // [Step 3] DB 입력 // A. asset_core await connection.query( `INSERT INTO asset_core (id, asset_code, category, asset_type, current_role, asset_purpose, service_type, purchase_date, memo, current_dept, user_current, emp_no, user_position, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [assetId, assetId, category, assetType, row.current_role || '', row.asset_purpose || '', row.service_type || '', purchaseDate, row.memo || '', deptName, userName, empNo, position, now, now] ); // B. asset_spec await connection.query( `INSERT INTO asset_spec (asset_id, mainboard, cpu, ram, gpu) VALUES (?, ?, ?, ?, ?)`, [assetId, row.mainboard || '', row.cpu || '', row.ram || '', row.gpu || ''] ); // C. asset_volume const volCols = [ { key: 'SDD1', type: 'SSD', slot: 1 }, { key: 'SDD2', type: 'SSD', slot: 2 }, { key: 'HDD1', type: 'HDD', slot: 3 }, { key: 'HDD2', type: 'HDD', slot: 4 }, { key: 'HDD3', type: 'HDD', slot: 5 }, { key: 'HDD4', type: 'HDD', slot: 6 } ]; for (const col of volCols) { const rawVol = row[col.key]; const parsed = parseCapacity(rawVol); if (parsed) { await connection.query( `INSERT INTO asset_volume (asset_id, disk_type, capacity, unit, slot_no) VALUES (?, ?, ?, ?, ?)`, [assetId, col.type, parsed.capacity, parsed.unit, col.slot] ); } } insertCount++; existingSet.add(dupKey); } catch (err) { errorCount++; console.error(`❌ [Row ${i + 2}] ${empNo || 'Public'}: ${err.message}`); } } console.log(`\n✨ 작업 완료!`); console.log(`- 신규 입력: ${insertCount}건`); console.log(`- 중복 스킵: ${skipCount}건`); console.log(`- 오류 실패: ${errorCount}건`); await connection.end(); } importAssets().catch(console.error);