Files
dashboard/backend/routes/manualFeedSack.js
T
Alberto-Audrix 32a36cceff
CI / lint-and-test (push) Canceled after 0s
first commit
2026-07-28 08:55:05 +07:00

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;