import mysql from 'mysql2/promise'; import dotenv from 'dotenv'; dotenv.config(); const TYPE_PREFIX_MAP = { '서버': 'SVR', '가상서버(VM)': 'VM', '워크스테이션': 'WKS', '서버PC': 'PC', '개인PC': 'PC', '공용PC': 'PC', '노트북': 'NBK', '태블릿': 'TAB', 'NAS': 'NAS', 'DAS': 'DAS', '스토리지': 'STO', '스토리지 렉': 'STO', '스위치': 'NET', '방화벽': 'NET', '공유기': 'NET', '허브': 'NET', '네트워크': 'NET', '모니터': 'MNT', '프린터': 'PRT', '스캐너': 'SCN', '복합기': 'MFP', '빔프로젝터': 'PRJ', '화상회의장비': 'VCF', '업무지원장비': 'EQP', 'CPU': 'CPU', 'HDD': 'HDD', 'RAM': 'RAM', 'GPU': 'GPU', 'SSD': 'SSD', '메인보드': 'MBD', '파워서플라이': 'PWR', '쿨러': 'CLR', '케이스': 'CAS', 'PC부품': 'PRT', '드론': 'DRO', '측량장비': 'SUR', '보조기기': 'SUR', '공간정보장비': 'SUR', '책상': 'FRN', '의자': 'FRN', '캐비닛': 'FRN', '사무가구': 'FRN', '구독SW': 'SW', '영구SW': 'SW', '외부': 'SW', '내부': 'INT', '선물': 'GFT', 'VIP': 'VIP' }; function formatPurchaseDate(date) { if (!date) return '000000'; let s = String(date).replace(/[^0-9]/g, ''); if (s.length >= 6) { return s.substring(0, 6); } return '000000'; } async function reformatAllCodes() { const connection = await mysql.createConnection({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, port: parseInt(process.env.DB_PORT || '3306') }); try { const tables = [ 'asset_pc', 'asset_server', 'asset_network', 'asset_storage', 'asset_equipment', 'asset_survey', 'asset_pc_parts', 'asset_office_supplies', 'asset_sw_external', 'asset_sw_internal', 'asset_vip' ]; let allAssets = []; for (const table of tables) { try { const [rows] = await connection.query(`SELECT * FROM ${table}`); allAssets = allAssets.concat(rows.map(r => ({ ...r, sourceTable: table }))); } catch (err) { if (err.code === 'ER_NO_SUCH_TABLE') { console.log(`Skipping missing table: ${table}`); } else { console.error(`Error querying ${table}:`, err.message); } } } console.log(`Total assets loaded: ${allAssets.length}`); // Process each asset const processed = allAssets.map(a => { // 1. Determine prefix let prefix = 'AST'; if (a.asset_type && TYPE_PREFIX_MAP[a.asset_type]) { prefix = TYPE_PREFIX_MAP[a.asset_type]; } else if (a.category && TYPE_PREFIX_MAP[a.category]) { prefix = TYPE_PREFIX_MAP[a.category]; } else if (a.sourceTable === 'asset_sw_external') prefix = 'SW'; else if (a.sourceTable === 'asset_sw_internal') prefix = 'INT'; // 2. Determine YYYYMM const dateStr = a.purchase_date || a.start_date || ''; // start_date for SW const yyyymm = formatPurchaseDate(dateStr); return { ...a, prefix, yyyymm }; }); // Group by Prefix const groups = {}; processed.forEach(a => { if (!groups[a.prefix]) groups[a.prefix] = []; groups[a.prefix].push(a); }); // Start renaming for (const prefix in groups) { const items = groups[prefix]; // Sort logic to maintain some order (by date then id) items.sort((a, b) => { if (a.yyyymm !== b.yyyymm) return a.yyyymm.localeCompare(b.yyyymm); return String(a.id).localeCompare(String(b.id)); }); console.log(`Processing group ${prefix}: ${items.length} items`); // Temporary rename to avoid UNIQUE constraint conflicts during sequential updates for (const item of items) { const tempCode = `TEMP-${Math.random().toString(36).substring(2, 10)}-${item.id}`; await connection.query(`UPDATE ${item.sourceTable} SET asset_code = ? WHERE id = ?`, [tempCode, item.id]); } for (let i = 0; i < items.length; i++) { const item = items[i]; const serial = String(i + 1).padStart(4, '0'); // SVR-202209-0001 // Some formats might want 3 or 4 digits. Defaulting to 4. const newCode = `${prefix}-${item.yyyymm}-${serial}`; await connection.query(`UPDATE ${item.sourceTable} SET asset_code = ? WHERE id = ?`, [newCode, item.id]); } } console.log('✅ Asset codes reformatted successfully.'); } catch (err) { console.error('❌ Reformatting failed:', err); } finally { await connection.end(); } } reformatAllCodes();