Files
ITAM/batch_reformat_codes.js
Taehoon b2713a142d feat: enhance HW modal layout and Server list view columns
- 상세 모달 레이아웃 개선: 모델명과 메인보드 동일 행 배치, 중복 메인보드 필드 제거

- OS 컬럼 스키마 매핑 및 상세 모달 입력 폼 추가

- 모든 하드웨어(서버 포함)에서 HDD 1~4 노출되도록 pc-only 속성 제거

- 서버 리스트 뷰 레이아웃 개선: 자산유형(asset_type) 컬럼 추가 및 너비 조정

- 서버 리스트 모델/메인보드 통합 컬럼 노출 로직 개선 (model_name 우선 표시)

- 자산코드 일괄 재부여 스크립트(batch_reformat_codes.js) 추가 및 유니크 제약조건 회피 로직 반영
2026-05-26 19:26:44 +09:00

125 lines
4.5 KiB
JavaScript

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();