fix: persistencia e extracao de comprimento de pecas e subcomponentes na importacao

This commit is contained in:
2026-10-16 15:43:15 -03:00
parent ec980cba05
commit ebcfe3c9d2
7 changed files with 141 additions and 17 deletions
+98 -7
View File
@@ -27,6 +27,90 @@ const CAMPOS_MONITORADOS: CampoConfig[] = [
{ key: 'tem_componentes', label: 'Tem Componentes', isCritico: true },
];
/**
* Função utilitária resiliente para extrair o comprimento numérico de uma peça principal.
* Suporta múltiplos aliases de importação (Bocad, Advance Steel, Excel, CSV) e formatações de string.
*/
export function extrairComprimentoSeguro(item: any): number | null {
if (!item) return null;
const raw =
item.comprimento ??
item.comprimento_ref ??
item.comprimentoRef ??
item.comprimentoMax ??
item.comprimento_max ??
item.comprimento_peca ??
item['Comprimento'] ??
item['Comprimento (mm)'] ??
item['Comprimento Ref. (mm)'] ??
item['Comprimento Max. (mm)'] ??
item['Comp. (mm)'] ??
item['Comp (mm)'] ??
item.compr ??
item.comp;
if (raw === undefined || raw === null || raw === '' || raw === '-') return null;
if (typeof raw === 'number') {
return isNaN(raw) || raw <= 0 ? null : Math.round(raw);
}
// String cleanup: trata formatos como "3.241", "3,241", "6000 mm", "5850.5"
let str = String(raw).trim().replace(/mm/gi, '').trim();
if (str.includes('.') && str.includes(',')) {
if (str.indexOf('.') < str.indexOf(',')) {
str = str.replace(/\./g, '').replace(',', '.');
} else {
str = str.replace(/,/g, '');
}
} else if (str.includes(',')) {
str = str.replace(',', '.');
}
const num = parseFloat(str);
return isNaN(num) || num <= 0 ? null : Math.round(num);
}
/**
* Função utilitária resiliente para extrair o comprimento numérico de subcomponentes.
*/
export function extrairComprimentoComponenteSeguro(item: any): number | null {
if (!item) return null;
const raw =
item.comprimento_componente ??
item.comprimentoComponente ??
item.comprimento ??
item.comprimento_ref ??
item.compr ??
item.comp ??
item['Comprimento Componente'] ??
item['Comprimento (mm)'] ??
item['Comprimento'] ??
item['Comp. (mm)'];
if (raw === undefined || raw === null || raw === '' || raw === '-') return null;
if (typeof raw === 'number') {
return isNaN(raw) || raw <= 0 ? null : Math.round(raw);
}
let str = String(raw).trim().replace(/mm/gi, '').trim();
if (str.includes('.') && str.includes(',')) {
if (str.indexOf('.') < str.indexOf(',')) {
str = str.replace(/\./g, '').replace(',', '.');
} else {
str = str.replace(/,/g, '');
}
} else if (str.includes(',')) {
str = str.replace(',', '.');
}
const num = parseFloat(str);
return isNaN(num) || num <= 0 ? null : Math.round(num);
}
/**
* Normaliza e agrupa linhas de peças e subcomponentes
*/
@@ -45,6 +129,7 @@ export function consolidarPecasEComponentes(rawItems: any[]): {
if (!marca) return;
const pecaKey = `${ofNumber}-${etapaFase}-${marca}`;
const comprimentoFinal = extrairComprimentoSeguro(item);
const pecaData = {
of_number: ofNumber,
@@ -54,12 +139,7 @@ export function consolidarPecasEComponentes(rawItems: any[]): {
quantidade: Number(item.quantidade) || 0,
peso_unitario: Number(item.peso_unitario) || 0,
peso_total: Number(item.peso_total) || 0,
comprimento:
item.comprimento !== undefined && item.comprimento !== null
? Number(item.comprimento)
: item.comprimento_ref
? Number(item.comprimento_ref)
: null,
comprimento: comprimentoFinal,
tratamento_superficial: item.tratamento_superficial || 'pintura',
material: item.material || 'Aço A36',
perfil_principal: item.perfil_principal || item.descricao || '',
@@ -68,6 +148,9 @@ export function consolidarPecasEComponentes(rawItems: any[]): {
if (!pecasMap.has(pecaKey)) {
pecasMap.set(pecaKey, pecaData);
} else if (comprimentoFinal && !pecasMap.get(pecaKey).comprimento) {
// Se a peça já estava no mapa mas sem comprimento e esta linha tem, atualiza
pecasMap.get(pecaKey).comprimento = comprimentoFinal;
}
// Se o item contém um subcomponente
@@ -92,12 +175,14 @@ export function consolidarPecasEComponentes(rawItems: any[]): {
}
cleanMarca = String(numVal);
const compComprimento = extrairComprimentoComponenteSeguro(item);
const compData = {
marca_componente: cleanMarca,
descricao: item.descricao_componente || item.descricao || '',
perfil: item.perfil_componente || item.perfil_principal || '',
peso_unitario: Number(item.peso_unitario_componente) || 0,
comprimento: item.comprimento_componente ? Number(item.comprimento_componente) : null,
comprimento: compComprimento,
quantidade_por_peca: Math.max(1, Math.round(Number(item.quantidade_por_peca) || 1)),
};
@@ -110,6 +195,12 @@ export function consolidarPecasEComponentes(rawItems: any[]): {
const exists = comps.some((c) => c.marca_componente === cleanMarca);
if (!exists) {
comps.push(compData);
} else if (compComprimento) {
// Se já existia mas sem comprimento, atualiza
const cExistente = comps.find((c) => c.marca_componente === cleanMarca);
if (cExistente && !cExistente.comprimento) {
cExistente.comprimento = compComprimento;
}
}
}
});
+6 -2
View File
@@ -1,5 +1,6 @@
import { supabase } from '@/integrations/supabase/client';
import { ItemAnaliseImportacao } from '@/types/importDiff';
import { extrairComprimentoSeguro } from '@/utils/importDiffService';
export interface ExecucaoImportacaoParams {
itens: ItemAnaliseImportacao[];
@@ -75,12 +76,14 @@ export async function executarImportacaoConciliada(
const pesoUnitFinal = Number(importado.peso_unitario || existente.peso_unitario || 0);
const pesoTotalCalculado = Number((qtdFinal * pesoUnitFinal).toFixed(3)) || Number(importado.peso_total || 0);
const comprFinal = extrairComprimentoSeguro(importado) ?? extrairComprimentoSeguro(existente);
const payloadUpdate: any = {
descricao: importado.descricao || existente.descricao || '',
quantidade: qtdFinal,
peso_unitario: pesoUnitFinal,
peso_total: pesoTotalCalculado,
comprimento: importado.comprimento !== undefined ? importado.comprimento : existente.comprimento,
comprimento: comprFinal,
tratamento_superficial: importado.tratamento_superficial || existente.tratamento_superficial || 'pintura',
material: importado.material || existente.material || 'Aço A36',
perfil_principal: importado.perfil_principal || existente.perfil_principal || '',
@@ -170,6 +173,7 @@ export async function executarImportacaoConciliada(
const qtd = Number(imp.quantidade) || 0;
const pesoU = Number(imp.peso_unitario) || 0;
const pesoT = Number(imp.peso_total) || Number((qtd * pesoU).toFixed(3));
const comprFinal = extrairComprimentoSeguro(imp);
return {
of_number: imp.of_number,
@@ -179,7 +183,7 @@ export async function executarImportacaoConciliada(
quantidade: qtd,
peso_unitario: pesoU,
peso_total: pesoT,
comprimento: imp.comprimento || null,
comprimento: comprFinal,
tratamento_superficial: imp.tratamento_superficial || 'pintura',
material: imp.material || 'Aço A36',
perfil_principal: imp.perfil_principal || '',