Add production workstation management API
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
const express = require('express');
|
||||
const { authenticateAPIKey, verifyToken } = require('../auth');
|
||||
const { addProductionOrderDefect, createProductionOrders, importTinyProductCompositionExport, listProductionOrders, listProductionPlans, listProductionWorkstations, updateProductionOrderExecution, updateProductionOrderStatus, updateProductionPlan, updateProductionPlanStatus, upsertTinyProductionOrderDetail } = require('../services/productionOrderService');
|
||||
const { addProductionOrderDefect, createProductionOrders, createProductionWorkstation, importTinyProductCompositionExport, listProductionOrders, listProductionPlans, listProductionWorkstations, updateProductionOrderExecution, updateProductionOrderStatus, updateProductionPlan, updateProductionPlanStatus, updateProductionWorkstation, upsertTinyProductionOrderDetail } = require('../services/productionOrderService');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -35,12 +35,28 @@ router.get('/production-plans', verifyToken, async (req, res) => {
|
||||
|
||||
router.get('/production-workstations', verifyToken, async (req, res) => {
|
||||
try {
|
||||
res.json(await listProductionWorkstations());
|
||||
res.json(await listProductionWorkstations({ includeInactive: req.query?.includeInactive === 'true' }));
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/production-workstations', verifyToken, async (req, res) => {
|
||||
try {
|
||||
res.status(201).json(await createProductionWorkstation(req.body || {}));
|
||||
} catch (error) {
|
||||
res.status(error.statusCode || 500).json({ error: error.message || 'Internal Server Error' });
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/production-workstations/:id', verifyToken, async (req, res) => {
|
||||
try {
|
||||
res.json(await updateProductionWorkstation(req.params.id, req.body || {}));
|
||||
} catch (error) {
|
||||
res.status(error.statusCode || 500).json({ error: error.message || 'Internal Server Error' });
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/production-plans/:id', verifyToken, async (req, res) => {
|
||||
try {
|
||||
res.json(await updateProductionPlan(req.params.id, req.body || {}));
|
||||
|
||||
@@ -51,6 +51,14 @@ const formatDate = (value) => {
|
||||
|
||||
const normalizeText = (value) => String(value || '').trim();
|
||||
|
||||
const normalizeWorkstationCode = (value) => normalizeText(value)
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-+|-+$/g, '')
|
||||
.slice(0, 60);
|
||||
|
||||
const normalizeQuantity = (value) => {
|
||||
const normalizedValue = typeof value === 'string' && value.includes(',')
|
||||
? value.replace(/\./g, '').replace(',', '.')
|
||||
@@ -1826,14 +1834,79 @@ const updateProductionOrderExecution = async (id, payload = {}) => {
|
||||
return getOrderById(id);
|
||||
};
|
||||
|
||||
const listProductionWorkstations = async () => {
|
||||
const mapWorkstation = (row) => ({
|
||||
id: Number(row.id),
|
||||
code: row.code || '',
|
||||
name: row.name || '',
|
||||
color: row.color || '#38bdf8',
|
||||
sortOrder: Number(row.sort_order || 0),
|
||||
isActive: Boolean(row.is_active)
|
||||
});
|
||||
|
||||
const listProductionWorkstations = async ({ includeInactive = false } = {}) => {
|
||||
const result = await pool.query(`
|
||||
SELECT id, code, name, color, sort_order, is_active
|
||||
FROM production_workstations
|
||||
WHERE is_active = TRUE
|
||||
${includeInactive ? '' : 'WHERE is_active = TRUE'}
|
||||
ORDER BY sort_order, name;
|
||||
`);
|
||||
return result.rows.map(row => ({ id: Number(row.id), code: row.code, name: row.name, color: row.color, sortOrder: Number(row.sort_order), isActive: Boolean(row.is_active) }));
|
||||
return result.rows.map(mapWorkstation);
|
||||
};
|
||||
|
||||
const normalizeWorkstationPayload = (payload = {}) => {
|
||||
const name = normalizeText(payload.name).slice(0, 160);
|
||||
const code = normalizeWorkstationCode(payload.code || name);
|
||||
const color = /^#[0-9a-f]{6}$/i.test(normalizeText(payload.color)) ? normalizeText(payload.color) : '#38bdf8';
|
||||
const sortOrder = Number.isFinite(Number(payload.sortOrder)) ? Math.max(0, Math.trunc(Number(payload.sortOrder))) : 0;
|
||||
const isActive = payload.isActive !== false;
|
||||
if (!name || !code) {
|
||||
const error = new Error('Informe o nome do posto de trabalho.');
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
return { name, code, color, sortOrder, isActive };
|
||||
};
|
||||
|
||||
const createProductionWorkstation = async (payload = {}) => {
|
||||
const workstation = normalizeWorkstationPayload(payload);
|
||||
try {
|
||||
const result = await pool.query(`
|
||||
INSERT INTO production_workstations (code, name, color, sort_order, is_active, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, CURRENT_TIMESTAMP)
|
||||
RETURNING id, code, name, color, sort_order, is_active;
|
||||
`, [workstation.code, workstation.name, workstation.color, workstation.sortOrder, workstation.isActive]);
|
||||
return mapWorkstation(result.rows[0]);
|
||||
} catch (error) {
|
||||
if (error?.code === '23505') {
|
||||
error.message = 'Já existe um posto de trabalho com este código.';
|
||||
error.statusCode = 409;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const updateProductionWorkstation = async (id, payload = {}) => {
|
||||
const workstation = normalizeWorkstationPayload(payload);
|
||||
try {
|
||||
const result = await pool.query(`
|
||||
UPDATE production_workstations
|
||||
SET code = $1, name = $2, color = $3, sort_order = $4, is_active = $5, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $6
|
||||
RETURNING id, code, name, color, sort_order, is_active;
|
||||
`, [workstation.code, workstation.name, workstation.color, workstation.sortOrder, workstation.isActive, id]);
|
||||
if (!result.rowCount) {
|
||||
const error = new Error('Posto de trabalho não encontrado.');
|
||||
error.statusCode = 404;
|
||||
throw error;
|
||||
}
|
||||
return mapWorkstation(result.rows[0]);
|
||||
} catch (error) {
|
||||
if (error?.code === '23505') {
|
||||
error.message = 'Já existe um posto de trabalho com este código.';
|
||||
error.statusCode = 409;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const addProductionOrderDefect = async (id, payload = {}) => {
|
||||
@@ -1864,6 +1937,7 @@ const addProductionOrderDefect = async (id, payload = {}) => {
|
||||
|
||||
module.exports = {
|
||||
createProductionOrders,
|
||||
createProductionWorkstation,
|
||||
deleteManualProductComposition,
|
||||
getProductComposition,
|
||||
importTinyProductCompositionExport,
|
||||
@@ -1877,6 +1951,7 @@ module.exports = {
|
||||
upsertTinyProductionOrderDetail,
|
||||
updateProductionPlan,
|
||||
updateProductionPlanStatus,
|
||||
updateProductionWorkstation,
|
||||
addProductionOrderDefect,
|
||||
updateProductionOrderExecution,
|
||||
updateProductionOrderStatus
|
||||
|
||||
Reference in New Issue
Block a user