136 lines
5.4 KiB
JavaScript
136 lines
5.4 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const Mortality = require('../models/Mortality');
|
|
const { captureAuditLog, filterAuditFields } = require('../middleware/auditLogger');
|
|
|
|
router.get('/:cycleId', async (req, res) => {
|
|
try {
|
|
const kandangId = req.query.kandangId ? parseInt(req.query.kandangId, 10) : null;
|
|
const records = await Mortality.getByCycle(req.params.cycleId, kandangId);
|
|
res.json({ success: true, data: records });
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
// GET aggregated totals across all kandangs
|
|
router.get('/:cycleId/totals', async (req, res) => {
|
|
try {
|
|
const totals = await Mortality.getTotalsByCycle(req.params.cycleId);
|
|
res.json({ success: true, data: totals });
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
router.get('/:cycleId/:day', async (req, res) => {
|
|
try {
|
|
const day = parseInt(req.params.day, 10);
|
|
if (isNaN(day)) return res.status(400).json({ success: false, error: 'Day must be a number' });
|
|
const kandangId = req.query.kandangId ? parseInt(req.query.kandangId, 10) : null;
|
|
const record = await Mortality.getByDay(req.params.cycleId, day, kandangId);
|
|
if (!record) return res.status(404).json({ success: false, error: 'Mortality record not found' });
|
|
res.json({ success: true, data: record });
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
router.put('/:cycleId/:day', async (req, res) => {
|
|
try {
|
|
const day = parseInt(req.params.day, 10);
|
|
const { mortalityCount, chickenCount, kandangId, panen, keterangan, afkir, beratPanen } = req.body;
|
|
|
|
// Validation
|
|
if (isNaN(day) || mortalityCount === undefined || mortalityCount < 0) {
|
|
return res.status(400).json({ success: false, error: 'Invalid mortality count' });
|
|
}
|
|
if (afkir !== undefined && afkir < 0) {
|
|
return res.status(400).json({ success: false, error: 'Afkir must be non-negative' });
|
|
}
|
|
if (panen !== undefined && panen < 0) {
|
|
return res.status(400).json({ success: false, error: 'Panen must be non-negative' });
|
|
}
|
|
if (beratPanen !== undefined && beratPanen < 0) {
|
|
return res.status(400).json({ success: false, error: 'Berat panen must be non-negative' });
|
|
}
|
|
if (keterangan && keterangan.length > 200) {
|
|
return res.status(400).json({ success: false, error: 'Keterangan must be 200 characters or less' });
|
|
}
|
|
|
|
const parsedKandangId = kandangId ? parseInt(kandangId, 10) : null;
|
|
const parsedAfkir = afkir !== undefined ? parseInt(afkir, 10) : 0;
|
|
const parsedPanen = panen !== undefined ? parseInt(panen, 10) : 0;
|
|
const parsedBeratPanen = beratPanen !== undefined ? parseFloat(beratPanen) : 0;
|
|
const parsedKeterangan = keterangan || null;
|
|
|
|
if (beratPanen !== undefined && Number.isNaN(parsedBeratPanen)) {
|
|
return res.status(400).json({ success: false, error: 'Berat panen must be a number' });
|
|
}
|
|
|
|
// Fetch old record for audit logging
|
|
const oldRecord = await Mortality.getByDay(req.params.cycleId, day, parsedKandangId);
|
|
const isCreate = !oldRecord;
|
|
|
|
// Perform update/insert
|
|
const record = await Mortality.upsert(
|
|
req.params.cycleId,
|
|
day,
|
|
mortalityCount,
|
|
true,
|
|
chickenCount,
|
|
parsedKandangId,
|
|
parsedPanen,
|
|
parsedKeterangan,
|
|
parsedAfkir,
|
|
parsedBeratPanen
|
|
);
|
|
|
|
// Capture audit log
|
|
const recordId = `${req.params.cycleId}-${day}${parsedKandangId ? `-${parsedKandangId}` : ''}`;
|
|
await captureAuditLog(
|
|
'mortality_records',
|
|
recordId,
|
|
isCreate ? 'CREATE' : 'UPDATE',
|
|
isCreate ? null : filterAuditFields(oldRecord),
|
|
filterAuditFields(record)
|
|
);
|
|
|
|
res.json({ success: true, data: record });
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
router.delete('/:cycleId/:day', async (req, res) => {
|
|
try {
|
|
const day = parseInt(req.params.day, 10);
|
|
if (isNaN(day)) return res.status(400).json({ success: false, error: 'Day must be a number' });
|
|
const kandangId = req.query.kandangId ? parseInt(req.query.kandangId, 10) : null;
|
|
|
|
// Fetch record before deleting for audit log
|
|
const oldRecord = await Mortality.getByDay(req.params.cycleId, day, kandangId);
|
|
|
|
const deleted = await Mortality.delete(req.params.cycleId, day, kandangId);
|
|
if (!deleted) return res.status(404).json({ success: false, error: 'Mortality record not found' });
|
|
|
|
// Capture audit log
|
|
if (oldRecord) {
|
|
const recordId = `${req.params.cycleId}-${day}${kandangId ? `-${kandangId}` : ''}`;
|
|
await captureAuditLog(
|
|
'mortality_records',
|
|
recordId,
|
|
'DELETE',
|
|
filterAuditFields(oldRecord),
|
|
null
|
|
);
|
|
}
|
|
|
|
res.json({ success: true, message: 'Mortality record deleted successfully' });
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|