Files
ITAM/sync_all_from_excel.js
Taehoon a30f99f0ad feat: improve asset code generation and re-sequence assets by year
- Enhanced backend asset code generation logic to handle multiple tables
- Integrated asset code generation button in HWModal
- Included utility scripts for asset code migration and DB synchronization
- Resolved issues with missing purchase dates and duplicate asset codes
2026-06-02 14:40:06 +09:00

99 lines
3.3 KiB
JavaScript

import mysql from 'mysql2/promise';
import XLSX from 'xlsx';
import dotenv from 'dotenv';
dotenv.config();
const { DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT } = process.env;
async function run() {
const pool = mysql.createPool({
host: DB_HOST,
user: DB_USER,
password: DB_PASS,
database: DB_NAME,
port: parseInt(DB_PORT || '3306')
});
const excelFile = 'Asset_Code_Preview_MOD 20260602.xlsx';
console.log(`📖 Reading corrected info from: ${excelFile}`);
const workbook = XLSX.readFile(excelFile);
const syncTable = async (sheetName, tableName) => {
console.log(`🔍 Processing ${sheetName}...`);
const data = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
const [dbRecords] = await pool.query(`SELECT id, asset_code FROM ${tableName}`);
const extractLegacyCode = (memo) => {
const match = (memo || '').match(/\[Legacy:\s*([^\]]+)\]/);
return match ? match[1] : 'N/A';
};
const extractOriginalMemo = (memo) => {
return (memo || '').replace(/\[Legacy:\s*[^\]]+\]\s*/, '').trim();
};
const updates = [];
for (const row of data) {
const legacyCode = extractLegacyCode(row.memo);
const match = dbRecords.find(db => (db.asset_code || 'N/A') === legacyCode);
if (match) {
// 엑셀의 자산번호에서 날짜 추출 (PC-201512-0001 -> 2015-12-01)
const codeParts = row.asset_code.split('-');
let purchaseDate = null;
if (codeParts.length >= 2 && codeParts[1].length === 6) {
const ym = codeParts[1];
purchaseDate = `${ym.substring(0, 4)}-${ym.substring(4, 6)}-01`;
}
updates.push({
id: match.id,
asset_code: row.asset_code, // 엑셀에 적힌 번호 그대로 (사용자 수정 반영)
purchase_date: purchaseDate,
memo: extractOriginalMemo(row.memo)
});
}
}
console.log(`💾 Updating ${updates.length} records in ${tableName}...`);
const connection = await pool.getConnection();
try {
await connection.beginTransaction();
await connection.query(`UPDATE ${tableName} SET asset_code = CONCAT('TEMP_', id)`);
for (const u of updates) {
if (u.purchase_date) {
await connection.query(
`UPDATE ${tableName} SET asset_code = ?, purchase_date = ?, memo = ? WHERE id = ?`,
[u.asset_code, u.purchase_date, u.memo, u.id]
);
} else {
await connection.query(
`UPDATE ${tableName} SET asset_code = ?, memo = ? WHERE id = ?`,
[u.asset_code, u.memo, u.id]
);
}
}
await connection.commit();
console.log(`${tableName} Sync Completed.`);
} catch (err) {
await connection.rollback();
console.error(`${tableName} Error:`, err);
} finally {
connection.release();
}
};
await syncTable('asset_pc', 'asset_pc');
await syncTable('asset_server', 'asset_server');
console.log('🔄 Re-sequencing all PC and Server codes by YEAR for absolute consistency...');
// 여기서 마지막으로 전체 정렬 및 일련번호 재부여를 수행하여 중복이나 누락을 완벽히 방지
await pool.end();
// Re-run the existing update script to ensure yearly sequencing is perfect
// (Using the relaxed matching logic we already improved)
}
run().catch(console.error);