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
This commit is contained in:
94
generate_codes.js
Normal file
94
generate_codes.js
Normal file
@@ -0,0 +1,94 @@
|
||||
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')
|
||||
});
|
||||
|
||||
console.log('📡 Fetching data from DB...');
|
||||
const [pcs] = await pool.query('SELECT * FROM asset_pc');
|
||||
const [servers] = await pool.query('SELECT * FROM asset_server');
|
||||
|
||||
const getPrefix = (type) => {
|
||||
const t = type || '';
|
||||
if (t.includes('서버 렉') || t.includes('워크스테이션')) return 'SVR';
|
||||
if (t.includes('스토리지 렉')) return 'STO';
|
||||
if (t.includes('공용PC') || t.includes('개인PC') || t.includes('서버PC') || t === 'PC') return 'PC';
|
||||
return 'ETC';
|
||||
};
|
||||
|
||||
const parseYYYYMM = (dateStr) => {
|
||||
if (!dateStr) return '000000';
|
||||
const clean = dateStr.replace(/[^0-9]/g, '');
|
||||
if (clean.length >= 6) return clean.substring(0, 6);
|
||||
return '000000';
|
||||
};
|
||||
|
||||
const processList = (list) => {
|
||||
// 1. Prepare data with sorting keys and groups
|
||||
const mapped = list.map(item => {
|
||||
const prefix = getPrefix(item.asset_type);
|
||||
const yyyymm = parseYYYYMM(item.purchase_date);
|
||||
// Sort by: purchase_date -> model_name -> mainboard -> os -> id (stability)
|
||||
const sortKey = [
|
||||
item.purchase_date || '9999-99-99',
|
||||
item.model_name || '',
|
||||
item.mainboard || '',
|
||||
item.os || '',
|
||||
item.id
|
||||
].join('|');
|
||||
|
||||
return { ...item, prefix, yyyymm, sortKey };
|
||||
});
|
||||
|
||||
// 2. Sort the list
|
||||
mapped.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
||||
|
||||
// 3. Assign new codes
|
||||
const counters = {};
|
||||
return mapped.map(item => {
|
||||
const groupKey = `${item.prefix}-${item.yyyymm}`;
|
||||
counters[groupKey] = (counters[groupKey] || 0) + 1;
|
||||
const serial = String(counters[groupKey]).padStart(4, '0');
|
||||
const newCode = `${groupKey}-${serial}`;
|
||||
|
||||
return {
|
||||
asset_code: newCode,
|
||||
category: item.category,
|
||||
asset_type: item.asset_type,
|
||||
asset_purpose: item.asset_purpose || '',
|
||||
memo: `[Legacy: ${item.asset_code || 'N/A'}] ${item.memo || ''}`.trim()
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
console.log('🔄 Processing codes...');
|
||||
const finalServers = processList(servers);
|
||||
const finalPcs = processList(pcs);
|
||||
|
||||
console.log('📊 Generating Excel...');
|
||||
const wb = XLSX.utils.book_new();
|
||||
const wsServers = XLSX.utils.json_to_sheet(finalServers);
|
||||
const wsPcs = XLSX.utils.json_to_sheet(finalPcs);
|
||||
|
||||
XLSX.utils.book_append_sheet(wb, wsServers, 'asset_server');
|
||||
XLSX.utils.book_append_sheet(wb, wsPcs, 'asset_pc');
|
||||
|
||||
const fileName = 'Asset_Code_Preview_20260602.xlsx';
|
||||
XLSX.writeFile(wb, fileName);
|
||||
|
||||
console.log(`✅ Completed! File saved as: ${fileName}`);
|
||||
await pool.end();
|
||||
}
|
||||
|
||||
run().catch(console.error);
|
||||
Reference in New Issue
Block a user