Add editable registrations

This commit is contained in:
Cauê Faleiros
2026-08-11 10:28:29 -03:00
parent f274616b80
commit 2b618a015e
4 changed files with 251 additions and 43 deletions

View File

@@ -11,7 +11,9 @@ const {
listCategories,
listConsumptionReferences,
listProducts,
updateCategory
updateCategory,
updateConsumptionReference,
updateProduct
} = require('../services/catalogService');
const { importTinyProductCompositionExport } = require('../services/productionOrderService');
@@ -74,6 +76,14 @@ router.post('/catalog/products', verifyToken, async (req, res, next) => {
}
});
router.put('/catalog/products/:id', verifyToken, async (req, res, next) => {
try {
res.json(await updateProduct(req.params.id, req.body || {}));
} catch (error) {
next(error);
}
});
router.delete('/catalog/products/:id', verifyToken, async (req, res, next) => {
try {
await deleteProduct(req.params.id);
@@ -99,6 +109,14 @@ router.post('/catalog/consumption-references', verifyToken, async (req, res, nex
}
});
router.put('/catalog/consumption-references/:id', verifyToken, async (req, res, next) => {
try {
res.json(await updateConsumptionReference(req.params.id, req.body || {}));
} catch (error) {
next(error);
}
});
router.post('/catalog/product-compositions/import', verifyToken, async (req, res, next) => {
try {
res.status(201).json(await importTinyProductCompositionExport(req.body || {}));

View File

@@ -205,6 +205,56 @@ const createProduct = async (payload) => {
return products.find(product => product.id === result.rows[0].id);
};
const updateProduct = async (id, payload) => {
const type = normalizeProductType(payload.type);
const sku = normalizeText(payload.sku).toUpperCase();
const name = normalizeText(payload.name);
if (!sku || !name) {
const error = new Error('SKU e nome do produto são obrigatórios.');
error.statusCode = 400;
throw error;
}
const result = await pool.query(`
UPDATE catalog_products
SET type = $2,
sku = $3,
name = $4,
category_id = $5,
composition = $6,
notes = $7,
gramature = $8,
material_yield = $9,
width_cm = $10,
color = $11,
subcategory = $12,
sizes = $13,
updated_at = CURRENT_TIMESTAMP
WHERE id = $1
RETURNING id;
`, [
id,
type,
sku,
name,
Number(payload.categoryId) || null,
normalizeText(payload.composition) || null,
normalizeText(payload.notes) || null,
normalizeNumber(payload.gramature),
normalizeNumber(payload.materialYield),
normalizeNumber(payload.widthCm),
normalizeText(payload.color) || null,
normalizeText(payload.subcategory) || null,
normalizeStringArray(payload.sizes)
]);
if (!result.rows.length) {
const error = new Error('Produto não encontrado.');
error.statusCode = 404;
throw error;
}
const products = await listProducts();
return products.find(product => product.id === result.rows[0].id);
};
const deleteProduct = async (id) => {
await pool.query('DELETE FROM catalog_products WHERE id = $1', [id]);
};
@@ -275,6 +325,66 @@ const createConsumptionReference = async (payload) => {
return references.find(reference => reference.id === result.rows[0].id);
};
const updateConsumptionReference = async (id, payload) => {
const productId = Number(payload.productId);
if (!productId) {
const error = new Error('Produto é obrigatório.');
error.statusCode = 400;
throw error;
}
const sizeYields = normalizeNumericMap(payload.sizeYields);
const sizeAreas = normalizeNumericMap(payload.sizeAreas);
const generalYield = normalizeNumber(payload.generalYield);
const calculatedYield = Object.values(sizeYields).length
? Object.values(sizeYields).reduce((total, value) => total + value, 0) / Object.values(sizeYields).length
: null;
const consumptionQuantity = normalizeNumber(payload.consumptionQuantity);
if (!generalYield && !calculatedYield && !consumptionQuantity) {
const error = new Error('Informe o rendimento ou consumo por peça.');
error.statusCode = 400;
throw error;
}
const result = await pool.query(`
UPDATE consumption_references
SET product_id = $2,
material_product_id = $3,
color = $4,
general_yield = $5,
size_yields = $6::jsonb,
size_areas = $7::jsonb,
gramature = $8,
efficiency_percent = $9,
rib_g_per_piece = $10,
material_cost_per_kg = $11,
consumption_quantity = $12,
consumption_unit = $13,
updated_at = CURRENT_TIMESTAMP
WHERE id = $1
RETURNING id;
`, [
id,
productId,
Number(payload.materialProductId) || null,
normalizeText(payload.color) || null,
generalYield || calculatedYield,
JSON.stringify(sizeYields),
JSON.stringify(sizeAreas),
normalizeNumber(payload.gramature),
normalizeNumber(payload.efficiencyPercent),
normalizeNumber(payload.ribGPerPiece),
normalizeNumber(payload.materialCostPerKg),
consumptionQuantity,
normalizeText(payload.consumptionUnit) || null
]);
if (!result.rows.length) {
const error = new Error('Referência de consumo não encontrada.');
error.statusCode = 404;
throw error;
}
const references = await listConsumptionReferences();
return references.find(reference => reference.id === result.rows[0].id);
};
const deleteConsumptionReference = async (id) => {
await pool.query('DELETE FROM consumption_references WHERE id = $1', [id]);
};
@@ -300,5 +410,7 @@ module.exports = {
listCategories,
listConsumptionReferences,
listProducts,
updateCategory
updateCategory,
updateConsumptionReference,
updateProduct
};