import mysql from 'mysql2/promise'; import dotenv from 'dotenv'; dotenv.config(); const pool = mysql.createPool({ 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'), }); // 하드웨어 출시 연도/월 데이터베이스 const RELEASE_DATES = { // Intel CPU 'i9-14': '2023-10', 'i7-14': '2023-10', 'i5-14': '2023-10', 'i9-13': '2022-10', 'i7-13': '2022-10', 'i5-13': '2022-10', 'i9-12': '2021-11', 'i7-12': '2021-11', 'i5-12': '2021-11', 'i9-11': '2021-03', 'i7-11': '2021-03', 'i5-11': '2021-03', 'i9-10': '2020-05', 'i7-10': '2020-05', 'i5-10': '2020-05', 'i9-9': '2018-10', 'i7-9': '2018-10', 'i5-9': '2018-10', 'i7-8': '2017-10', 'i5-8': '2017-10', 'i7-7': '2017-01', 'i5-7': '2017-01', 'i7-6': '2015-08', 'i5-6': '2015-08', 'i7-5': '2014-06', 'i5-5': '2015-06', // Broadwell 'i7-4': '2013-06', 'i5-4': '2013-06', 'i7-3': '2012-04', 'i5-3': '2012-04', 'i7-2': '2011-01', 'i5-2': '2011-01', // NVIDIA GPU 'RTX 40': '2022-10', 'RTX 30': '2020-09', 'RTX 20': '2018-09', 'GTX 16': '2019-02', 'GTX 10': '2016-05', 'GTX 9': '2014-09', 'GTX 750': '2014-02', 'GTX 7': '2013-05', 'GTX 6': '2012-03' }; // 출시 연도만 있는 경우 (지시에 따라 후속년도 12월 적용을 위함) const YEAR_ONLY = { 'I5-4': 2013, 'I5-6': 2015, 'I7-7': 2017, 'GTX 750': 2014 }; function inferDateFromSpecs(cpu, gpu) { const cpuStr = (cpu || '').toUpperCase(); const gpuStr = (gpu || '').toUpperCase(); let latestYear = 0; let latestMonth = 0; // 모든 매핑 데이터를 순회하며 가장 최신 날짜를 찾음 for (const [key, dateStr] of Object.entries(RELEASE_DATES)) { if (cpuStr.includes(key) || gpuStr.includes(key)) { const [y, m] = dateStr.split('-').map(Number); if (y > latestYear || (y === latestYear && m > latestMonth)) { latestYear = y; latestMonth = m; } } } // 매칭된 정보가 있는 경우 if (latestYear > 0) { // 월 정보가 명확히 매핑된 경우 (RELEASE_DATES 사용) // 하지만 지시사항에 따라 "월을 못찾으면 12월" & "후속년도" 규칙 적용 여부 판단 // RELEASE_DATES는 월이 이미 있으므로 그대로 사용하되, // 만약 YEAR_ONLY에만 걸리는 경우를 위해 로직 보강 return `${latestYear}-${String(latestMonth).padStart(2, '0')}-01`; } // 연도만 매칭되는 경우 (지시사항: 후속년도 12월) for (const [key, year] of Object.entries(YEAR_ONLY)) { if (cpuStr.includes(key) || gpuStr.includes(key)) { return `${year + 1}-12-01`; } } return null; } async function run() { const connection = await pool.getConnection(); try { const [rows] = await connection.query(` SELECT c.id, c.asset_code, c.purchase_date, s.cpu, s.gpu FROM asset_core c LEFT JOIN asset_spec s ON c.id = s.asset_id `); const updates = []; for (const row of rows) { const currentVal = (row.purchase_date || '').trim(); // 구매일자가 없거나 '-', 'undefined'인 경우 + 혹은 아직 보정이 필요한 자산 if (!currentVal || currentVal === '-' || currentVal === 'undefined' || currentVal.startsWith('0000') || currentVal === '2024-01-01') { const specDate = inferDateFromSpecs(row.cpu, row.gpu); if (specDate) { updates.push({ id: row.id, date: specDate, code: row.asset_code, cpu: row.cpu, gpu: row.gpu }); } } } console.log(`🚀 지시사항 반영: ${updates.length}건의 자산을 보정합니다. (후속년도/12월 규칙 적용)`); for (const item of updates) { await connection.query('UPDATE asset_core SET purchase_date = ? WHERE id = ?', [item.date, item.id]); console.log(`[Update] ${item.code.padEnd(15)} | CPU: ${String(item.cpu).padEnd(20)} | GPU: ${String(item.gpu).padEnd(15)} -> ${item.date}`); } console.log(`\n✅ 완료: ${updates.length}건 보정됨.`); } catch (err) { console.error('Error:', err); } finally { connection.release(); pool.end(); } } run();