feat: suporte a pecas e OFs sem componentes cadastrados no corte e solda
This commit is contained in:
@@ -136,21 +136,26 @@ export const ApontamentoForm = () => {
|
||||
|
||||
let qtdDisponivelParaEntrar = Number(peca.quantidade) || 0;
|
||||
|
||||
// Identificar se a peça de fato possui subcomponentes cadastrados nesta OF
|
||||
const compsDaPeca = componentesAgrupados?.filter(c => c.peca_ids?.includes(peca.id)) || [];
|
||||
const temComponentesCadastrados = peca.tem_componentes !== false && compsDaPeca.length > 0;
|
||||
const ehSemMontagem = peca.tem_componentes === false;
|
||||
|
||||
// Se for CORTE:
|
||||
// Peças compostas são produzidas através do corte de seus subcomponentes.
|
||||
// Ao atingir 100% dos componentes cortados, o kit é concluído e a peça mestre é liberada para Solda.
|
||||
if (isCorte && peca.tem_componentes) {
|
||||
// Se tiver componentes cadastrados, são apontados os subcomponentes.
|
||||
// Se NÃO tiver componentes cadastrados (opção do usuário não controlar componentes), aponta a peça mestre normalmente!
|
||||
if (isCorte && temComponentesCadastrados) {
|
||||
qtdDisponivelParaEntrar = 0;
|
||||
} else if (!peca.tem_componentes && procNomeLower.includes('solda')) {
|
||||
// Regra: peças sem componentes não passam por solda
|
||||
} else if (ehSemMontagem && procNomeLower.includes('solda')) {
|
||||
// Regra: peças sem montagem (S/M) não passam por solda
|
||||
qtdDisponivelParaEntrar = 0;
|
||||
} else if (indexAtual > 0) {
|
||||
// Encontrar processo anterior válido
|
||||
let processoAnteriorValido = null;
|
||||
for (let i = indexAtual - 1; i >= 0; i--) {
|
||||
const p = processosOrdenados[i];
|
||||
if (!peca.tem_componentes && p.nome.toLowerCase().includes('solda')) {
|
||||
continue; // Pula a solda na busca do processo anterior para peças simples
|
||||
if (ehSemMontagem && p.nome.toLowerCase().includes('solda')) {
|
||||
continue; // Pula a solda na busca do processo anterior para peças simples (S/M)
|
||||
}
|
||||
processoAnteriorValido = p;
|
||||
break;
|
||||
@@ -162,8 +167,7 @@ export const ApontamentoForm = () => {
|
||||
.reduce((sum, a) => sum + (Number(a.quantidade_produzida) || 0), 0);
|
||||
|
||||
// Fallback de retrocompatibilidade para peças com componentes cortados antes da automação
|
||||
if (peca.tem_componentes && qtdApontadaAnterior === 0 && processoAnteriorValido.nome.toLowerCase().includes('corte')) {
|
||||
const compsDaPeca = componentesAgrupados?.filter(c => c.peca_ids?.includes(peca.id)) || [];
|
||||
if (temComponentesCadastrados && qtdApontadaAnterior === 0 && processoAnteriorValido.nome.toLowerCase().includes('corte')) {
|
||||
if (compsDaPeca.length > 0) {
|
||||
const todosCortados = compsDaPeca.every(c => {
|
||||
const aptsComp = apontamentos
|
||||
|
||||
@@ -17,7 +17,8 @@ import {
|
||||
PackageCheck,
|
||||
ShieldCheck,
|
||||
Wrench,
|
||||
Scissors
|
||||
Scissors,
|
||||
Info
|
||||
} from 'lucide-react';
|
||||
import { useKitsProducao, PecaKitInfo } from '@/hooks/useKitsProducao';
|
||||
import { useOFsAtivas, OFAtiva } from '@/hooks/useOFsAtivas';
|
||||
@@ -445,6 +446,15 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
|
||||
</div>
|
||||
|
||||
{/* ──────────────── Lista de Peças com Mapa Térmico ──────────────── */}
|
||||
{!loading && listaKits.length > 0 && !listaKits.some((k) => k.componentes && k.componentes.length > 0) && (
|
||||
<div className="p-3.5 rounded-2xl bg-amber-500/10 border border-amber-500/30 text-amber-900 dark:text-amber-200 flex items-center gap-3 shadow-xs">
|
||||
<Info className="w-5 h-5 shrink-0 text-amber-600 dark:text-amber-400" />
|
||||
<div className="text-xs leading-relaxed">
|
||||
<strong className="font-bold">Modo Peça Direta:</strong> Esta OF não possui subcomponentes cadastrados no sistema. O avanço no <strong>Corte</strong> e a liberação das peças para a <strong>Solda</strong> são gerenciados diretamente pelo apontamento das peças principais.
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{loading ? (
|
||||
<div className="py-16 flex flex-col items-center justify-center text-slate-400 gap-3">
|
||||
<div className="h-10 w-10 animate-spin rounded-full border-4 border-orange-500 border-t-transparent" />
|
||||
|
||||
@@ -78,21 +78,21 @@ export const calcularSaldoProcessoPeca = (
|
||||
let qtdDisponivelParaEntrar = Number(peca.quantidade) || 0;
|
||||
let motivoBloqueio: string | null = null;
|
||||
|
||||
const kitInfo = mapaKits?.get(peca.id);
|
||||
const temControleComponentes = Boolean(kitInfo && kitInfo.tem_componentes && (kitInfo.componentes?.length || 0) > 0);
|
||||
|
||||
// REGRA 1: Peças sem montagem (S/M) não passam por Solda
|
||||
if (ehSemMontagem && ehSolda) {
|
||||
qtdDisponivelParaEntrar = 0;
|
||||
motivoBloqueio = 'Peça S/M (Pula Solda - vai direto para Pintura)';
|
||||
} else if (ehSolda && !ehSemMontagem && mapaKits?.has(peca.id)) {
|
||||
} else if (ehSolda && !ehSemMontagem && temControleComponentes && kitInfo) {
|
||||
// REGRA 1.1: REGRA DO KIT COMPLETO DE CORTE PARA A SOLDA!
|
||||
// Apenas peças com componentes 100% cortados (em lotes de kits inteiros) são liberadas para Solda!
|
||||
const kitInfo = mapaKits.get(peca.id)!;
|
||||
if (kitInfo.tem_componentes) {
|
||||
qtdDisponivelParaEntrar = kitInfo.kits_completos_cortados;
|
||||
if (kitInfo.kits_completos_cortados === 0) {
|
||||
motivoBloqueio = kitInfo.motivo_bloqueio_solda || 'Aguardando corte completo dos kits';
|
||||
} else if (kitInfo.kits_completos_cortados <= jaProduzidoAtual) {
|
||||
motivoBloqueio = `Todos os ${kitInfo.kits_completos_cortados} kits cortados já foram soldados (${jaProduzidoAtual}/${peca.quantidade})`;
|
||||
}
|
||||
qtdDisponivelParaEntrar = kitInfo.kits_completos_cortados;
|
||||
if (kitInfo.kits_completos_cortados === 0) {
|
||||
motivoBloqueio = kitInfo.motivo_bloqueio_solda || 'Aguardando corte completo dos kits';
|
||||
} else if (kitInfo.kits_completos_cortados <= jaProduzidoAtual) {
|
||||
motivoBloqueio = `Todos os ${kitInfo.kits_completos_cortados} kits cortados já foram soldados (${jaProduzidoAtual}/${peca.quantidade})`;
|
||||
}
|
||||
} else if (indexAtual > 0) {
|
||||
// REGRA 2: Encontrar processo anterior válido
|
||||
@@ -1217,7 +1217,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
|
||||
fase={faseSelecionada}
|
||||
onSelectPecaParaApontar={(pecaKit) => {
|
||||
const ehProcCorte = processoSelecionado?.id === procCorteId;
|
||||
if (ehProcCorte && pecaKit.tem_componentes) {
|
||||
if (ehProcCorte && pecaKit.tem_componentes && pecaKit.componentes.length > 0) {
|
||||
setPecaParaCorteModal(pecaKit);
|
||||
} else {
|
||||
const pItem = pecasComSaldo.find((p) => p.id === pecaKit.peca_id);
|
||||
|
||||
Reference in New Issue
Block a user