340 lines
13 KiB
JavaScript

const express = require('express');
const router = express.Router();
const db = require('../../db');
const { hasRole } = require('../../middleware/authMiddleware');
// ==========================================
// 1. Asset Management
// ==========================================
// Get All Assets
router.get('/assets', async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM assets ORDER BY created_at DESC');
res.json(rows);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Get Asset by ID
router.get('/assets/:id', async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM assets WHERE id = ?', [req.params.id]);
if (rows.length === 0) return res.status(404).json({ error: 'Asset not found' });
const asset = rows[0];
// Fetch sub-assets (children)
const [children] = await db.query('SELECT id, name, category, status, location FROM assets WHERE parent_id = ?', [req.params.id]);
asset.children = children;
// Fetch parent name if exists
if (asset.parent_id) {
const [parentRows] = await db.query('SELECT name FROM assets WHERE id = ?', [asset.parent_id]);
if (parentRows.length > 0) {
asset.parent_name = parentRows[0].name;
}
}
res.json(asset);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Create Asset
router.post('/assets', async (req, res) => {
const { id, parent_id, name, category, model_name, serial_number, manufacturer, location, purchase_date, manager, status, specs, purchase_price, image_url, quantity } = req.body;
try {
const sql = `
INSERT INTO assets (id, parent_id, name, category, model_name, serial_number, manufacturer, location, purchase_date, manager, status, specs, purchase_price, image_url, quantity)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
await db.query(sql, [id, parent_id || null, name, category, model_name, serial_number, manufacturer, location, purchase_date, manager, status, specs, purchase_price, image_url, quantity || 1]);
res.status(201).json({ message: 'Asset created', id });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Update Asset
router.put('/assets/:id', async (req, res) => {
const { parent_id, name, category, model_name, serial_number, manufacturer, location, purchase_date, manager, status, specs, purchase_price, image_url, quantity } = req.body;
try {
const sql = `
UPDATE assets
SET parent_id=?, name=?, category=?, model_name=?, serial_number=?, manufacturer=?, location=?, purchase_date=?, manager=?, status=?, specs=?, purchase_price=?, image_url=?, quantity=?
WHERE id=?
`;
const [result] = await db.query(sql, [parent_id || null, name, category, model_name, serial_number, manufacturer, location, purchase_date, manager, status, specs, purchase_price, image_url, quantity || 1, req.params.id]);
if (result.affectedRows === 0) return res.status(404).json({ error: 'Asset not found' });
res.json({ message: 'Asset updated' });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// ==========================================
// 2. Maintenance History
// ==========================================
// Get All Maintenance Records for an Asset
router.get('/assets/:asset_id/maintenance', async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM maintenance_history WHERE asset_id = ? ORDER BY maintenance_date DESC', [req.params.asset_id]);
res.json(rows);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Get Single Maintenance Record by ID
router.get('/maintenance/:id', async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM maintenance_history WHERE id = ?', [req.params.id]);
if (rows.length === 0) return res.status(404).json({ error: 'Maintenance record not found' });
const record = rows[0];
// Fetch used parts
const [parts] = await db.query(`
SELECT mp.*, a.name as part_name, a.model_name
FROM maintenance_parts mp
JOIN assets a ON mp.part_id = a.id
WHERE mp.maintenance_id = ?
`, [record.id]);
record.parts = parts;
res.json(record);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Create Maintenance Record
router.post('/assets/:asset_id/maintenance', async (req, res) => {
const { maintenance_date, type, content, images, parts } = req.body; // parts: [{ part_id, quantity }]
const { asset_id } = req.params;
const connection = await db.getConnection();
try {
await connection.beginTransaction();
const sql = `
INSERT INTO maintenance_history (asset_id, maintenance_date, type, content, images)
VALUES (?, ?, ?, ?, ?)
`;
const [result] = await connection.query(sql, [asset_id, maintenance_date, type, content, JSON.stringify(images || [])]);
const maintenanceId = result.insertId;
if (parts && Array.isArray(parts) && parts.length > 0) {
for (const part of parts) {
// 1. Deduct quantity from assets
await connection.query('UPDATE assets SET quantity = quantity - ? WHERE id = ?', [part.quantity, part.part_id]);
// 2. Add to maintenance_parts
await connection.query(
'INSERT INTO maintenance_parts (maintenance_id, part_id, quantity) VALUES (?, ?, ?)',
[maintenanceId, part.part_id, part.quantity]
);
}
}
await connection.commit();
res.status(201).json({ message: 'Maintenance record created', id: maintenanceId });
} catch (err) {
await connection.rollback();
console.error(err);
res.status(500).json({ error: 'Database error' });
} finally {
connection.release();
}
});
// Update Maintenance Record
router.put('/maintenance/:id', async (req, res) => {
const { maintenance_date, type, content, images, parts } = req.body;
const maintenanceId = req.params.id;
const connection = await db.getConnection();
try {
await connection.beginTransaction();
// 1. Update basic info
const sql = `
UPDATE maintenance_history
SET maintenance_date=?, type=?, content=?, images=?
WHERE id=?
`;
const [result] = await connection.query(sql, [maintenance_date, type, content, JSON.stringify(images || []), maintenanceId]);
if (result.affectedRows === 0) {
await connection.rollback();
return res.status(404).json({ error: 'Maintenance record not found' });
}
// 2. Handle Parts Update (Restore old -> Apply new)
if (parts) {
// Get existing parts to restore stock
const [existingParts] = await connection.query('SELECT * FROM maintenance_parts WHERE maintenance_id = ?', [maintenanceId]);
for (const part of existingParts) {
await connection.query('UPDATE assets SET quantity = quantity + ? WHERE id = ?', [part.quantity, part.part_id]);
}
// Remove existing links
await connection.query('DELETE FROM maintenance_parts WHERE maintenance_id = ?', [maintenanceId]);
// Add new parts and deduct stock
if (Array.isArray(parts) && parts.length > 0) {
for (const part of parts) {
await connection.query('UPDATE assets SET quantity = quantity - ? WHERE id = ?', [part.quantity, part.part_id]);
await connection.query(
'INSERT INTO maintenance_parts (maintenance_id, part_id, quantity) VALUES (?, ?, ?)',
[maintenanceId, part.part_id, part.quantity]
);
}
}
}
await connection.commit();
res.json({ message: 'Maintenance record updated' });
} catch (err) {
await connection.rollback();
console.error(err);
res.status(500).json({ error: 'Database error' });
} finally {
connection.release();
}
});
// Delete Maintenance Record
router.delete('/maintenance/:id', async (req, res) => {
const connection = await db.getConnection();
try {
await connection.beginTransaction();
// 1. Restore stock for used parts
const [usedParts] = await connection.query('SELECT * FROM maintenance_parts WHERE maintenance_id = ?', [req.params.id]);
for (const part of usedParts) {
await connection.query('UPDATE assets SET quantity = quantity + ? WHERE id = ?', [part.quantity, part.part_id]);
}
// 2. Delete record (Cascading delete will remove maintenance_parts rows, but we manually restored stock first)
const [result] = await connection.query('DELETE FROM maintenance_history WHERE id = ?', [req.params.id]);
if (result.affectedRows === 0) {
await connection.rollback();
return res.status(404).json({ error: 'Maintenance record not found' });
}
await connection.commit();
res.json({ message: 'Maintenance record deleted' });
} catch (err) {
await connection.rollback();
console.error(err);
res.status(500).json({ error: 'Database error' });
} finally {
connection.release();
}
});
// ==========================================
// 3. Manuals
// ==========================================
// Get Manuals for an Asset
router.get('/assets/:asset_id/manuals', async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM asset_manuals WHERE asset_id = ? ORDER BY created_at DESC', [req.params.asset_id]);
res.json(rows);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Add Manual to Asset
router.post('/assets/:asset_id/manuals', async (req, res) => {
const { file_name, file_url } = req.body;
const { asset_id } = req.params;
try {
const sql = `INSERT INTO asset_manuals (asset_id, file_name, file_url) VALUES (?, ?, ?)`;
const [result] = await db.query(sql, [asset_id, file_name, file_url]);
res.status(201).json({ message: 'Manual added', id: result.insertId });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Delete Manual
router.delete('/manuals/:id', async (req, res) => {
try {
const [result] = await db.query('DELETE FROM asset_manuals WHERE id = ?', [req.params.id]);
if (result.affectedRows === 0) return res.status(404).json({ error: 'Manual not found' });
res.json({ message: 'Manual deleted' });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// ==========================================
// 4. Accessories
// ==========================================
// Get Accessories for an Asset
router.get('/assets/:asset_id/accessories', async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM asset_accessories WHERE asset_id = ? ORDER BY created_at ASC', [req.params.asset_id]);
res.json(rows);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Add Accessory to Asset
router.post('/assets/:asset_id/accessories', async (req, res) => {
const { name, spec, quantity } = req.body;
const { asset_id } = req.params;
try {
const sql = `INSERT INTO asset_accessories (asset_id, name, spec, quantity) VALUES (?, ?, ?, ?)`;
const [result] = await db.query(sql, [asset_id, name, spec, quantity || 1]);
res.status(201).json({ message: 'Accessory added', id: result.insertId });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Delete Accessory
router.delete('/accessories/:id', async (req, res) => {
try {
const [result] = await db.query('DELETE FROM asset_accessories WHERE id = ?', [req.params.id]);
if (result.affectedRows === 0) return res.status(404).json({ error: 'Accessory not found' });
res.json({ message: 'Accessory deleted' });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
module.exports = router;