Files
graphs/backend/services/cuttingSettingsService.js
2026-07-08 09:32:28 -03:00

129 lines
4.2 KiB
JavaScript

const { pool } = require('../db');
const FAMILY_KEYS = ['BLCS', 'BLOS', 'BLMC', 'BLPM'];
const FAMILY_KEY_SET = new Set(FAMILY_KEYS);
const normalizeFamilyKey = (value) => {
const familyKey = String(value || '').trim().toUpperCase();
return FAMILY_KEY_SET.has(familyKey) ? familyKey : '';
};
const normalizeNumber = (value) => {
const number = Number(value);
return Number.isFinite(number) && number > 0 ? number : null;
};
const normalizeText = (value) => String(value || '').replace(/\s+/g, ' ').trim();
const normalizeFamilyYields = (familyYields = {}) => {
return FAMILY_KEYS.reduce((normalized, familyKey) => {
const unitsPerRoll = normalizeNumber(familyYields[familyKey]);
if (unitsPerRoll) normalized[familyKey] = unitsPerRoll;
return normalized;
}, {});
};
const normalizeProductOverrides = (productOverrides = {}) => {
return Object.entries(productOverrides).reduce((normalized, [productId, override]) => {
const normalizedProductId = normalizeText(productId);
if (!normalizedProductId || !override || typeof override !== 'object') return normalized;
const familyKey = normalizeFamilyKey(override.familyKey);
const color = normalizeText(override.color);
const size = normalizeText(override.size).toUpperCase();
if (!familyKey && !color && !size) return normalized;
normalized[normalizedProductId] = {
familyKey,
color,
size
};
return normalized;
}, {});
};
const listCuttingSettings = async () => {
const [familyResult, overrideResult] = await Promise.all([
pool.query(`
SELECT family_key, units_per_roll
FROM cutting_family_rules
WHERE units_per_roll IS NOT NULL AND units_per_roll > 0
ORDER BY family_key
`),
pool.query(`
SELECT product_id, family_key, color, size
FROM cutting_product_overrides
ORDER BY product_id
`)
]);
return {
familyYields: familyResult.rows.reduce((settings, row) => {
settings[row.family_key] = Number(row.units_per_roll);
return settings;
}, {}),
productOverrides: overrideResult.rows.reduce((settings, row) => {
settings[row.product_id] = {
familyKey: row.family_key || '',
color: row.color || '',
size: row.size || ''
};
return settings;
}, {})
};
};
const saveCuttingSettings = async ({ familyYields = {}, productOverrides = {} }) => {
const normalizedFamilyYields = normalizeFamilyYields(familyYields);
const normalizedProductOverrides = normalizeProductOverrides(productOverrides);
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query('DELETE FROM cutting_family_rules');
for (const [familyKey, unitsPerRoll] of Object.entries(normalizedFamilyYields)) {
await client.query(`
INSERT INTO cutting_family_rules (family_key, units_per_roll, updated_at)
VALUES ($1, $2, CURRENT_TIMESTAMP)
`, [familyKey, unitsPerRoll]);
}
await client.query('DELETE FROM cutting_product_overrides');
for (const [productId, override] of Object.entries(normalizedProductOverrides)) {
await client.query(`
INSERT INTO cutting_product_overrides (product_id, family_key, color, size, updated_at)
VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP)
`, [
productId,
override.familyKey || null,
override.color || null,
override.size || null
]);
}
await client.query('COMMIT');
return {
familyYields: normalizedFamilyYields,
productOverrides: normalizedProductOverrides
};
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}
};
module.exports = {
FAMILY_KEYS,
listCuttingSettings,
normalizeFamilyKey,
normalizeFamilyYields,
normalizeProductOverrides,
saveCuttingSettings
};