fix: reconhecimento robusto de pecas advance steel sem quantidade inline e recuperacao de pecas compostas
This commit is contained in:
@@ -398,7 +398,7 @@
|
|||||||
let lastPage = null;
|
let lastPage = null;
|
||||||
|
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
if (lastPage === null || item.page !== lastPage || Math.abs(item.y - (lastY ?? item.y)) > 3.5) {
|
if (lastPage === null || item.page !== lastPage || Math.abs(item.y - (lastY ?? item.y)) > 4.5) {
|
||||||
if (currentLine.length > 0) {
|
if (currentLine.length > 0) {
|
||||||
lines.push(currentLine);
|
lines.push(currentLine);
|
||||||
}
|
}
|
||||||
@@ -461,21 +461,21 @@
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Linha Mestre de Peça Principal (ex: "B133-1-20 2 Pl 6x160x154" ou "B133-1-11 1 C 100x50x20x2.8")
|
// 1. Linha Mestre de Peça Principal (ex: "B133-1-20 2 Pl 6x160x154" ou "B133-1-20 Pl 6x160x154")
|
||||||
const masterMatch = lineText.match(/^([A-Za-z0-9]+(?:-\d+)+)\s+(\d+)\s+([A-Za-z].*)$/);
|
const masterMatch = lineText.match(/^([A-Za-z0-9]+(?:-\d+)+)(?:\s+(\d+))?\s+([A-Za-z].*)$/);
|
||||||
if (masterMatch) {
|
if (masterMatch) {
|
||||||
const fullMark = masterMatch[1];
|
const fullMark = masterMatch[1];
|
||||||
const quant = parseInt(masterMatch[2], 10);
|
const inlineQuant = masterMatch[2] ? parseInt(masterMatch[2], 10) : 0;
|
||||||
const descCandidate = masterMatch[3].trim();
|
const descCandidate = masterMatch[3].trim();
|
||||||
const parts = fullMark.split('-');
|
const parts = fullMark.split('-');
|
||||||
const pieceNumber = parts[parts.length - 1];
|
const pieceNumber = parts[parts.length - 1];
|
||||||
const pieceNumInt = parseInt(pieceNumber, 10);
|
const pieceNumInt = parseInt(pieceNumber, 10);
|
||||||
|
|
||||||
|
// Peça principal tem identificador < 1000 e não possui material na linha de cabeçalho da marca
|
||||||
if (pieceNumInt < 1000) {
|
if (pieceNumInt < 1000) {
|
||||||
const hasMaterial = KNOWN_MATERIALS.some(m => descCandidate.includes(m));
|
const hasMaterial = KNOWN_MATERIALS.some(m => descCandidate.includes(m));
|
||||||
const hasManyNumbers = (descCandidate.match(/[0-9.,]+/g) || []).length >= 3;
|
|
||||||
|
|
||||||
if (!hasMaterial && !hasManyNumbers) {
|
if (!hasMaterial) {
|
||||||
const ofCode = parts.length >= 2 ? parts[0] : defaultOf;
|
const ofCode = parts.length >= 2 ? parts[0] : defaultOf;
|
||||||
const phaseCode = parts.length >= 3 ? parts[1] : '0';
|
const phaseCode = parts.length >= 3 ? parts[1] : '0';
|
||||||
|
|
||||||
@@ -486,7 +486,7 @@
|
|||||||
marca: pieceNumber,
|
marca: pieceNumber,
|
||||||
numeroPeca: pieceNumber,
|
numeroPeca: pieceNumber,
|
||||||
descricao: descCandidate || 'ESTRUTURA',
|
descricao: descCandidate || 'ESTRUTURA',
|
||||||
quantidade: quant > 0 ? quant : 1,
|
quantidade: inlineQuant > 0 ? inlineQuant : 1,
|
||||||
material: '',
|
material: '',
|
||||||
comprimento: 0,
|
comprimento: 0,
|
||||||
pesoUnitario: 0,
|
pesoUnitario: 0,
|
||||||
@@ -623,6 +623,8 @@
|
|||||||
let maxComp = asm.comprimento || 0;
|
let maxComp = asm.comprimento || 0;
|
||||||
let totalPeso = asm.subtotalPeso > 0 ? asm.subtotalPeso : asm.pesoTotal;
|
let totalPeso = asm.subtotalPeso > 0 ? asm.subtotalPeso : asm.pesoTotal;
|
||||||
|
|
||||||
|
let finalQuant = asm.quantidade;
|
||||||
|
|
||||||
if (isComposed) {
|
if (isComposed) {
|
||||||
let sumComponentsWeight = 0;
|
let sumComponentsWeight = 0;
|
||||||
let bestComp = asm.components[0];
|
let bestComp = asm.components[0];
|
||||||
@@ -645,10 +647,24 @@
|
|||||||
if (!totalPeso || totalPeso === 0) {
|
if (!totalPeso || totalPeso === 0) {
|
||||||
totalPeso = sumComponentsWeight;
|
totalPeso = sumComponentsWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Se a quantidade veio 1 (ou não veio no cabeçalho), calcular relação peso total / soma peso unitário dos componentes
|
||||||
|
if (finalQuant <= 1 && asm.components.length > 0) {
|
||||||
|
const sumUnitWeights = asm.components.reduce((acc, c) => {
|
||||||
|
const unitW = c.quantidade > 0 ? (c.pesoTotal / c.quantidade) : c.pesoTotal;
|
||||||
|
return acc + unitW;
|
||||||
|
}, 0);
|
||||||
|
if (sumUnitWeights > 0 && totalPeso > sumUnitWeights * 1.3) {
|
||||||
|
const ratio = Math.round(totalPeso / sumUnitWeights);
|
||||||
|
if (ratio > 1) {
|
||||||
|
finalQuant = ratio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regra de Ouro: Peso Unitário = Peso Total dividido pela quantidade da peça principal
|
// Regra de Ouro: Peso Unitário = Peso Total dividido pela quantidade da peça principal
|
||||||
const pesoUnit = asm.quantidade > 0 ? (totalPeso / asm.quantidade) : totalPeso;
|
const pesoUnit = finalQuant > 0 ? (totalPeso / finalQuant) : totalPeso;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
of: asm.of,
|
of: asm.of,
|
||||||
@@ -656,7 +672,7 @@
|
|||||||
marca: asm.marca,
|
marca: asm.marca,
|
||||||
descricao: asm.descricao,
|
descricao: asm.descricao,
|
||||||
isComposed: isComposed ? "SIM" : "NÃO",
|
isComposed: isComposed ? "SIM" : "NÃO",
|
||||||
quantidade: asm.quantidade,
|
quantidade: finalQuant,
|
||||||
material: materialPrincipal,
|
material: materialPrincipal,
|
||||||
perfilPrincipal: perfilPrincipal,
|
perfilPrincipal: perfilPrincipal,
|
||||||
comprimentoMax: maxComp > 0 ? maxComp : "-",
|
comprimentoMax: maxComp > 0 ? maxComp : "-",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ interface ComponentItem {
|
|||||||
perfil: string;
|
perfil: string;
|
||||||
material: string;
|
material: string;
|
||||||
comprimento: number;
|
comprimento: number;
|
||||||
|
pesoUnitario?: number;
|
||||||
pesoTotal: number;
|
pesoTotal: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +190,7 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
let lastPage: number | null = null;
|
let lastPage: number | null = null;
|
||||||
|
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
if (lastPage === null || item.page !== lastPage || Math.abs(item.y - (lastY ?? item.y)) > 3.5) {
|
if (lastPage === null || item.page !== lastPage || Math.abs(item.y - (lastY ?? item.y)) > 4.5) {
|
||||||
if (currentLine.length > 0) {
|
if (currentLine.length > 0) {
|
||||||
lines.push(currentLine);
|
lines.push(currentLine);
|
||||||
}
|
}
|
||||||
@@ -253,13 +254,12 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Verificar se é Linha Mestre de Peça Principal (ex: "B133-1-20 2 Pl 6x160x154" ou "B133-1-11 1 C 100x50x20x2.8")
|
// 1. Linha Mestre de Peça Principal (ex: "B133-1-20 Pl 6x160x154" ou "B133-1-20 2 Pl 6x160x154")
|
||||||
const masterMatch = lineText.match(/^([A-Za-z0-9]+(?:-\d+)+)\s+(\d+)\s+([A-Za-z].*)$/);
|
const masterMatch = lineText.match(/^([A-Za-z0-9]+(?:-\d+)+)(?:\s+(\d+))?\s+([A-Za-z].*)$/);
|
||||||
let isMasterLine = false;
|
|
||||||
|
|
||||||
if (masterMatch) {
|
if (masterMatch) {
|
||||||
const fullMark = masterMatch[1];
|
const fullMark = masterMatch[1];
|
||||||
const quant = parseInt(masterMatch[2], 10);
|
const quant = masterMatch[2] ? parseInt(masterMatch[2], 10) : 1;
|
||||||
const descCandidate = masterMatch[3].trim();
|
const descCandidate = masterMatch[3].trim();
|
||||||
const parts = fullMark.split('-');
|
const parts = fullMark.split('-');
|
||||||
const pieceNumber = parts[parts.length - 1];
|
const pieceNumber = parts[parts.length - 1];
|
||||||
@@ -267,12 +267,9 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
|
|
||||||
// Se o número da peça for menor que 1000, é uma peça principal mestre
|
// Se o número da peça for menor que 1000, é uma peça principal mestre
|
||||||
if (pieceNumInt < 1000) {
|
if (pieceNumInt < 1000) {
|
||||||
// Checar se não é uma linha completa de detalhe com material e medidas
|
|
||||||
const hasMaterial = KNOWN_MATERIALS.some((m) => descCandidate.includes(m));
|
const hasMaterial = KNOWN_MATERIALS.some((m) => descCandidate.includes(m));
|
||||||
const hasManyNumbers = (descCandidate.match(/[0-9.,]+/g) || []).length >= 3;
|
|
||||||
|
|
||||||
if (!hasMaterial && !hasManyNumbers) {
|
if (!hasMaterial) {
|
||||||
isMasterLine = true;
|
|
||||||
const ofCode = parts.length >= 2 ? parts[0] : defaultOf;
|
const ofCode = parts.length >= 2 ? parts[0] : defaultOf;
|
||||||
const phaseCode = parts.length >= 3 ? parts[1] : '0';
|
const phaseCode = parts.length >= 3 ? parts[1] : '0';
|
||||||
|
|
||||||
@@ -312,10 +309,6 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. Linha de Detalhe de Monopeça ou Componente Subordinado
|
// 3. Linha de Detalhe de Monopeça ou Componente Subordinado
|
||||||
// Ex: "B133-1-11 1 C 100x50x20x2.8 A36 540 2,6 2,6 0,25 0,25"
|
|
||||||
// Ex: "B133-1-1000 1 Pl 6x120x91 A36 120 91 0,5 1,1 0,024 0,049"
|
|
||||||
// Ex: "B133-1-1002 1 W 150x18.0 A572-GR 50 4.000 72 72 2,76 2,76"
|
|
||||||
// Ex: "- 12 M13 NaW 32 ASTM A325 10.9 10.9 32 0,1 1,7"
|
|
||||||
let itemMark = '';
|
let itemMark = '';
|
||||||
let itemQuant = 1;
|
let itemQuant = 1;
|
||||||
let remaining = lineText;
|
let remaining = lineText;
|
||||||
@@ -370,6 +363,7 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
const nums = numTokens.map(parseNumeric);
|
const nums = numTokens.map(parseNumeric);
|
||||||
|
|
||||||
let itemComp = 0;
|
let itemComp = 0;
|
||||||
|
let itemPUn = 0;
|
||||||
let itemPesoTot = 0;
|
let itemPesoTot = 0;
|
||||||
|
|
||||||
if (nums.length >= 1) {
|
if (nums.length >= 1) {
|
||||||
@@ -377,12 +371,16 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nums.length === 3) {
|
if (nums.length === 3) {
|
||||||
|
itemPUn = nums[1];
|
||||||
itemPesoTot = nums[2];
|
itemPesoTot = nums[2];
|
||||||
} else if (nums.length === 4) {
|
} else if (nums.length === 4) {
|
||||||
|
itemPUn = nums[1];
|
||||||
itemPesoTot = nums[2];
|
itemPesoTot = nums[2];
|
||||||
} else if (nums.length === 5) {
|
} else if (nums.length === 5) {
|
||||||
|
itemPUn = nums[1];
|
||||||
itemPesoTot = nums[2];
|
itemPesoTot = nums[2];
|
||||||
} else if (nums.length >= 6) {
|
} else if (nums.length >= 6) {
|
||||||
|
itemPUn = nums[2];
|
||||||
itemPesoTot = nums[3];
|
itemPesoTot = nums[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,6 +398,7 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
perfil: itemDesc || currentAssembly.descricao,
|
perfil: itemDesc || currentAssembly.descricao,
|
||||||
material: detectedMaterial || 'A36',
|
material: detectedMaterial || 'A36',
|
||||||
comprimento: itemComp,
|
comprimento: itemComp,
|
||||||
|
pesoUnitario: itemPUn,
|
||||||
pesoTotal: itemPesoTot
|
pesoTotal: itemPesoTot
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -410,6 +409,9 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
if (itemComp > 0 && (!currentAssembly.comprimento || currentAssembly.comprimento === 0)) {
|
if (itemComp > 0 && (!currentAssembly.comprimento || currentAssembly.comprimento === 0)) {
|
||||||
currentAssembly.comprimento = itemComp;
|
currentAssembly.comprimento = itemComp;
|
||||||
}
|
}
|
||||||
|
if (itemPUn > 0 && (!currentAssembly.pesoUnitario || currentAssembly.pesoUnitario === 0)) {
|
||||||
|
currentAssembly.pesoUnitario = itemPUn;
|
||||||
|
}
|
||||||
if (itemPesoTot > 0 && (!currentAssembly.pesoTotal || currentAssembly.pesoTotal === 0)) {
|
if (itemPesoTot > 0 && (!currentAssembly.pesoTotal || currentAssembly.pesoTotal === 0)) {
|
||||||
currentAssembly.pesoTotal = itemPesoTot;
|
currentAssembly.pesoTotal = itemPesoTot;
|
||||||
}
|
}
|
||||||
@@ -428,6 +430,7 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
|
|
||||||
if (isComposed) {
|
if (isComposed) {
|
||||||
let sumComponentsWeight = 0;
|
let sumComponentsWeight = 0;
|
||||||
|
let sumUnitComponentsWeight = 0;
|
||||||
let bestComp = asm.components[0];
|
let bestComp = asm.components[0];
|
||||||
maxComp = 0;
|
maxComp = 0;
|
||||||
|
|
||||||
@@ -437,6 +440,9 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
bestComp = c;
|
bestComp = c;
|
||||||
}
|
}
|
||||||
sumComponentsWeight += c.pesoTotal;
|
sumComponentsWeight += c.pesoTotal;
|
||||||
|
if (c.pesoUnitario > 0) {
|
||||||
|
sumUnitComponentsWeight += c.pesoUnitario * c.quantidade;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (bestComp) {
|
if (bestComp) {
|
||||||
@@ -449,6 +455,14 @@ const AdvanceSteelConverterContent: React.FC = () => {
|
|||||||
if (!totalPeso || totalPeso === 0) {
|
if (!totalPeso || totalPeso === 0) {
|
||||||
totalPeso = sumComponentsWeight;
|
totalPeso = sumComponentsWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detecção de quantidade de conjunto caso tenha vindo 1:
|
||||||
|
if (asm.quantidade === 1 && sumUnitComponentsWeight > 0 && totalPeso > 0) {
|
||||||
|
const ratio = Math.round(totalPeso / sumUnitComponentsWeight);
|
||||||
|
if (ratio > 1) {
|
||||||
|
asm.quantidade = ratio;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regra de Ouro: Peso Unitário = Peso Total dividido pela Quantidade da peça principal
|
// Regra de Ouro: Peso Unitário = Peso Total dividido pela Quantidade da peça principal
|
||||||
|
|||||||
Reference in New Issue
Block a user