Updated Asset Entry and Views

This commit is contained in:
2026-06-03 14:12:32 -05:00
parent 2f13b8c590
commit 8335f1af1b
9 changed files with 620 additions and 73 deletions

View File

@@ -70,6 +70,50 @@ router.post('/assets/:id/files', upload.single('file'), requireRole('admin', 'fi
res.status(201).json({ file: one('SELECT id, file_name, mime_type, size, uploaded_at FROM asset_files WHERE id = ?', [result.lastInsertRowid]) });
});
router.get('/assets/:id/files/:fileId', (req, res) => {
const file = one('SELECT * FROM asset_files WHERE id = ? AND asset_id = ?', [req.params.fileId, req.params.id]);
if (!file) return res.status(404).json({ error: 'File not found' });
res.setHeader('Content-Type', file.mime_type || 'application/octet-stream');
res.setHeader('Content-Disposition', `attachment; filename="${file.file_name}"`);
return res.send(Buffer.from(file.content_base64, 'base64'));
});
router.delete('/assets/:id/files/:fileId', requireRole('admin', 'finance', 'operations'), (req, res) => {
const result = run('DELETE FROM asset_files WHERE id = ? AND asset_id = ?', [req.params.fileId, req.params.id]);
if (!result.changes) return res.status(404).json({ error: 'File not found' });
audit(req.user.id, 'delete', 'asset_file', req.params.fileId, null, { asset_id: req.params.id });
return res.status(204).end();
});
router.post('/assets/:id/warranties', requireRole('admin', 'finance', 'operations'), (req, res) => {
const b = req.body;
const result = run(
`INSERT INTO warranties (
asset_id, provider, phone, start_date, expiration_date, warranty_limit,
actual_usage, coverage_details, document_name, document_base64, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
req.params.id, b.provider || null, b.phone || null, b.start_date || null, b.expiration_date || null,
b.warranty_limit || null, b.actual_usage || null, b.coverage_details || null,
b.document_name || null, b.document_base64 || null, now()
]
);
audit(req.user.id, 'create', 'warranty', result.lastInsertRowid, null, { ...b, document_base64: b.document_base64 ? '[stored]' : null });
res.status(201).json({
warranty: one(
'SELECT id, provider, phone, start_date, expiration_date, warranty_limit, actual_usage, coverage_details, document_name, created_at FROM warranties WHERE id = ?',
[result.lastInsertRowid]
)
});
});
router.delete('/assets/:id/warranties/:warrantyId', requireRole('admin', 'finance', 'operations'), (req, res) => {
const result = run('DELETE FROM warranties WHERE id = ? AND asset_id = ?', [req.params.warrantyId, req.params.id]);
if (!result.changes) return res.status(404).json({ error: 'Warranty not found' });
audit(req.user.id, 'delete', 'warranty', req.params.warrantyId, null, { asset_id: req.params.id });
return res.status(204).end();
});
router.post('/assets/:id/tasks', requireRole('admin', 'finance', 'operations'), (req, res) => {
const created = now();
const result = run(
@@ -80,4 +124,52 @@ router.post('/assets/:id/tasks', requireRole('admin', 'finance', 'operations'),
res.status(201).json({ task: one('SELECT * FROM tasks WHERE id = ?', [result.lastInsertRowid]) });
});
router.put('/assets/:id/tasks/:taskId', requireRole('admin', 'finance', 'operations'), (req, res) => {
const before = one('SELECT * FROM tasks WHERE id = ? AND asset_id = ?', [req.params.taskId, req.params.id]);
if (!before) return res.status(404).json({ error: 'Task not found' });
run(
'UPDATE tasks SET title = ?, type = ?, status = ?, due_date = ?, notes = ?, updated_at = ? WHERE id = ?',
[
req.body.title ?? before.title,
req.body.type ?? before.type,
req.body.status ?? before.status,
req.body.due_date ?? before.due_date,
req.body.notes ?? before.notes,
now(),
req.params.taskId
]
);
audit(req.user.id, 'update', 'task', req.params.taskId, before, req.body);
return res.json({ task: one('SELECT * FROM tasks WHERE id = ?', [req.params.taskId]) });
});
router.delete('/assets/:id/tasks/:taskId', requireRole('admin', 'finance', 'operations'), (req, res) => {
const result = run('DELETE FROM tasks WHERE id = ? AND asset_id = ?', [req.params.taskId, req.params.id]);
if (!result.changes) return res.status(404).json({ error: 'Task not found' });
audit(req.user.id, 'delete', 'task', req.params.taskId, null, { asset_id: req.params.id });
return res.status(204).end();
});
router.post('/assets/:id/notes', requireRole('admin', 'finance', 'operations'), (req, res) => {
if (!req.body.body) return res.status(400).json({ error: 'Note body is required' });
const result = run(
'INSERT INTO asset_notes (asset_id, body, created_by, created_at) VALUES (?, ?, ?, ?)',
[req.params.id, req.body.body, req.user.id, now()]
);
audit(req.user.id, 'create', 'asset_note', result.lastInsertRowid, null, { asset_id: req.params.id });
res.status(201).json({
note: one(
'SELECT n.id, n.body, n.created_at, u.name AS author FROM asset_notes n LEFT JOIN users u ON u.id = n.created_by WHERE n.id = ?',
[result.lastInsertRowid]
)
});
});
router.delete('/assets/:id/notes/:noteId', requireRole('admin', 'finance', 'operations'), (req, res) => {
const result = run('DELETE FROM asset_notes WHERE id = ? AND asset_id = ?', [req.params.noteId, req.params.id]);
if (!result.changes) return res.status(404).json({ error: 'Note not found' });
audit(req.user.id, 'delete', 'asset_note', req.params.noteId, null, { asset_id: req.params.id });
return res.status(204).end();
});
module.exports = router;