129 lines
3.9 KiB
JavaScript
129 lines
3.9 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const ManualFeedSack = require('../models/ManualFeedSack');
|
|
const { convertKeysToCamelCase } = require('../utils/caseConverter');
|
|
const {
|
|
isBeforeCutoffTime,
|
|
getPreviousDate,
|
|
createResponseMetadata
|
|
} = require('../utils/dateUtils');
|
|
|
|
/**
|
|
* GET /api/manual-feed-sack?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD
|
|
* Get all manual entries for a date range
|
|
*/
|
|
router.get('/', async (req, res) => {
|
|
try {
|
|
let { startDate, endDate } = req.query;
|
|
|
|
if (!startDate || !endDate) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Missing required query parameters: startDate, endDate'
|
|
});
|
|
}
|
|
|
|
// Apply D-1 filter if querying single day and before cutoff (17:00 WIB)
|
|
let isD1Applied = false;
|
|
if (startDate === endDate && isBeforeCutoffTime()) {
|
|
startDate = getPreviousDate(startDate);
|
|
endDate = startDate;
|
|
isD1Applied = true;
|
|
}
|
|
|
|
const entries = await ManualFeedSack.getByDateRange(startDate, endDate);
|
|
|
|
// Transform to camelCase and ensure date is a string
|
|
const transformedEntries = entries.map(entry => ({
|
|
...convertKeysToCamelCase(entry),
|
|
date: entry.date instanceof Date
|
|
? entry.date.toISOString().split('T')[0]
|
|
: typeof entry.date === 'string'
|
|
? entry.date.split('T')[0]
|
|
: entry.date
|
|
}));
|
|
|
|
res.json({
|
|
success: true,
|
|
data: transformedEntries,
|
|
meta: createResponseMetadata(isD1Applied)
|
|
});
|
|
} catch (error) {
|
|
console.error('Error fetching manual feed sack entries:', error);
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* PUT /api/manual-feed-sack
|
|
* Upsert manual entry
|
|
*/
|
|
router.put('/', async (req, res) => {
|
|
try {
|
|
const { date, cameraName, count, createdBy, keterangan } = req.body;
|
|
|
|
// Validation
|
|
if (!date || !cameraName || count === undefined) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Missing required fields: date, cameraName, count'
|
|
});
|
|
}
|
|
|
|
if (count < 0) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Count cannot be negative'
|
|
});
|
|
}
|
|
|
|
// Validate keterangan length
|
|
if (keterangan && keterangan.length > 200) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Keterangan cannot exceed 200 characters'
|
|
});
|
|
}
|
|
|
|
const entry = await ManualFeedSack.upsert(
|
|
date,
|
|
cameraName,
|
|
count,
|
|
createdBy,
|
|
keterangan || null
|
|
);
|
|
|
|
// Transform to camelCase and ensure date is a string
|
|
const transformedEntry = {
|
|
...convertKeysToCamelCase(entry),
|
|
date: entry.date instanceof Date
|
|
? entry.date.toISOString().split('T')[0]
|
|
: typeof entry.date === 'string'
|
|
? entry.date.split('T')[0]
|
|
: entry.date
|
|
};
|
|
|
|
res.json({ success: true, data: transformedEntry });
|
|
} catch (error) {
|
|
console.error('Error saving manual feed sack entry:', error);
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* DELETE /api/manual-feed-sack/:date/:cameraName
|
|
* Delete manual entry
|
|
*/
|
|
router.delete('/:date/:cameraName', async (req, res) => {
|
|
try {
|
|
const { date, cameraName } = req.params;
|
|
await ManualFeedSack.delete(date, cameraName);
|
|
res.json({ success: true });
|
|
} catch (error) {
|
|
console.error('Error deleting manual feed sack entry:', error);
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|