Files
ITAM/server.js

244 lines
7.7 KiB
JavaScript

import express from 'express';
import cors from 'cors';
import mysql from 'mysql2/promise';
import dotenv from 'dotenv';
import path from 'path';
import { fileURLToPath } from 'url';
dotenv.config();
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
app.use(cors());
app.use(express.json({ limit: '50mb' }));
// MySQL Connection Pool
const pool = mysql.createPool({
host: process.env.DB_HOST || 'localhost',
user: process.env.DB_USER || 'itam_user',
password: process.env.DB_PASSWORD || 'itam_pw',
database: process.env.DB_NAME || 'itam_db',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
// Helper for DB updates
async function ensureTables() {
try {
// Cloud_Assets Table
await pool.query(`
CREATE TABLE IF NOT EXISTS cloud_assets (
id VARCHAR(50) PRIMARY KEY,
platform_name VARCHAR(100),
corp VARCHAR(50),
dept VARCHAR(100),
purpose VARCHAR(255),
account_name VARCHAR(100),
payment_method VARCHAR(50),
payment_date VARCHAR(50),
card_number VARCHAR(50),
monthly_fee VARCHAR(50),
note TEXT
)
`);
// Logs Table
await pool.query(`
CREATE TABLE IF NOT EXISTS asset_logs (
id VARCHAR(50) PRIMARY KEY,
asset_id VARCHAR(50),
date VARCHAR(20),
details TEXT,
user VARCHAR(50),
INDEX(asset_id)
)
`);
console.log('✅ Cloud & Logs tables ensured.');
} catch (err) {
console.error('❌ Error ensuring tables:', err);
}
}
ensureTables();
// --- API Endpoints ---
// Get Master Data (Multi-tab)
app.get('/api/master-data', async (req, res) => {
try {
const [pc] = await pool.query('SELECT * FROM pc_assets');
const [server] = await pool.query('SELECT * FROM server_assets');
const [storage] = await pool.query('SELECT * FROM storage_assets');
const [equip] = await pool.query('SELECT * FROM equip_assets');
const [mobile] = await pool.query('SELECT * FROM mobile_assets');
const [subSw] = await pool.query('SELECT * FROM sw_sub_assets');
const [permSw] = await pool.query('SELECT * FROM sw_perm_assets');
const [cloud] = await pool.query('SELECT * FROM cloud_assets');
const [swUsers] = await pool.query('SELECT * FROM sw_users');
const [logs] = await pool.query('SELECT * FROM asset_logs ORDER BY date DESC');
res.json({
pc, server, storage, equip, mobile,
subSw, permSw, cloud,
swUsers,
logs
});
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Save Hardware Asset (PC, Server, Storage, etc.)
app.post('/api/hardware/save', async (req, res) => {
const asset = req.body;
const type = asset.type;
let table = '';
if (type === '개인PC' || type === 'PC') table = 'pc_assets';
else if (type === '서버') table = 'server_assets';
else if (type === '스토리지') table = 'storage_assets';
else if (type === '모바일' || type === '모바일기기') table = 'mobile_assets';
else table = 'equip_assets';
try {
// Check if exists
const [rows] = await pool.query(`SELECT id FROM ${table} WHERE id = ?`, [asset.id]);
const data = { ...asset };
delete data.id;
delete data.type;
if (rows.length > 0) {
await pool.query(`UPDATE ${table} SET ? WHERE id = ?`, [data, asset.id]);
} else {
await pool.query(`INSERT INTO ${table} SET ?`, [{ id: asset.id, ...data }]);
}
res.json({ success: true });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Save Software Asset
app.post('/api/software/save', async (req, res) => {
const asset = req.body;
const table = asset.type === '구독SW' ? 'sw_sub_assets' : (asset.type === '영구SW' ? 'sw_perm_assets' : 'cloud_assets');
try {
const [rows] = await pool.query(`SELECT id FROM ${table} WHERE id = ?`, [asset.id]);
const data = { ...asset };
delete data.id;
delete data.type;
if (rows.length > 0) {
await pool.query(`UPDATE ${table} SET ? WHERE id = ?`, [data, asset.id]);
} else {
await pool.query(`INSERT INTO ${table} SET ?`, [{ id: asset.id, ...data }]);
}
res.json({ success: true });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Delete Asset
app.delete('/api/asset/:type/:id', async (req, res) => {
const { type, id } = req.params;
let table = '';
if (type === '개인PC' || type === 'PC') table = 'pc_assets';
else if (type === '서버') table = 'server_assets';
else if (type === '스토리지') table = 'storage_assets';
else if (type === '모바일' || type === '모바일기기') table = 'mobile_assets';
else if (type === '전산비품' || type === '기타자산') table = 'equip_assets';
else if (type === '구독SW') table = 'sw_sub_assets';
else if (type === '영구SW') table = 'sw_perm_assets';
else if (type === '클라우드') table = 'cloud_assets';
try {
await pool.query(`DELETE FROM ${table} WHERE id = ?`, [id]);
// Also delete logs and users if needed
if (table.includes('sw')) await pool.query('DELETE FROM sw_users WHERE sw_id = ?', [id]);
await pool.query('DELETE FROM asset_logs WHERE asset_id = ?', [id]);
res.json({ success: true });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Log Save
app.post('/api/logs/save', async (req, res) => {
const log = req.body;
try {
const [rows] = await pool.query('SELECT id FROM asset_logs WHERE id = ?', [log.id]);
if (rows.length > 0) {
await pool.query('UPDATE asset_logs SET ? WHERE id = ?', [log, log.id]);
} else {
await pool.query('INSERT INTO asset_logs SET ?', [log]);
}
res.json({ success: true });
} catch (err) { res.status(500).json({ error: err.message }); }
});
// SW User Save
app.post('/api/sw-users/save', async (req, res) => {
const user = req.body;
try {
const [rows] = await pool.query('SELECT id FROM sw_users WHERE id = ?', [user.id]);
if (rows.length > 0) {
await pool.query('UPDATE sw_users SET ? WHERE id = ?', [user, user.id]);
} else {
await pool.query('INSERT INTO sw_users SET ?', [user]);
}
res.json({ success: true });
} catch (err) { res.status(500).json({ error: err.message }); }
});
app.post('/api/sw-users/batch', async (req, res) => {
const { swId, users } = req.body;
try {
await pool.query('DELETE FROM sw_users WHERE sw_id = ?', [swId]);
for (const u of users) {
await pool.query('INSERT INTO sw_users SET ?', { ...u, sw_id: swId });
}
res.json({ success: true });
} catch (err) { res.status(500).json({ error: err.message }); }
});
// 자산번호 생성 API
app.get('/api/generate-asset-code', async (req, res) => {
const { prefix } = req.query;
if (!prefix) return res.status(400).json({ error: 'Prefix is required' });
try {
const tables = [
'pc_assets', 'server_assets', 'storage_assets', 'equip_assets', 'mobile_assets',
'sw_sub_assets', 'sw_perm_assets'
];
let maxNum = 0;
for (const table of tables) {
const [rows] = await pool.query(`SELECT asset_code FROM ${table} WHERE asset_code LIKE ?`, [`${prefix}%`]);
rows.forEach(r => {
const numPart = r.asset_code.replace(prefix, '');
const num = parseInt(numPart);
if (!isNaN(num) && num > maxNum) maxNum = num;
});
}
const nextCode = `${prefix}${(maxNum + 1).toString().padStart(3, '0')}`;
res.json({ nextCode });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`🚀 ITAM Dedicated API Server running on http://localhost:${PORT}`);
});