diff --git a/check_b134.mjs b/check_b134.mjs deleted file mode 100644 index 2b719f3..0000000 --- a/check_b134.mjs +++ /dev/null @@ -1,2 +0,0 @@ -// Script temporário de auditoria da OF B134 -export {}; diff --git a/src/pages/Visualizador3D.tsx b/src/pages/Visualizador3D.tsx index 0bd08b1..5da40c8 100644 --- a/src/pages/Visualizador3D.tsx +++ b/src/pages/Visualizador3D.tsx @@ -110,11 +110,11 @@ export default function Visualizador3D() { .select('id, of_number, etapa_fase, marca, descricao, quantidade, peso_unitario, peso_total, perfil_principal, material') .eq('of_number', selectedOF); - // Fetch apontamentos com join de peca e processo + // Fetch apontamentos com join de peca e processo (apenas peças mestres) const { data: apontamentosData, error: errorApontamentos } = await supabase .from('apontamentos_producao' as any) .select(` - id, of_number, peca_id, quantidade_produzida, + id, of_number, peca_id, quantidade_produzida, tipo_apontamento, componente_id, peca:pecas!apontamentos_producao_peca_id_fkey(marca, etapa_fase), processo:processos_fabricacao!apontamentos_producao_processo_id_fkey(nome, cor, ordem) `) @@ -188,6 +188,10 @@ export default function Visualizador3D() { apontamentosData.sort((a: any, b: any) => (a.processo?.ordem || 0) - (b.processo?.ordem || 0)); apontamentosData.forEach((ap: any) => { + // Ignora apontamentos de componentes para não inflar as peças mestres + if (ap.tipo_apontamento && ap.tipo_apontamento !== 'peca') return; + if (ap.componente_id) return; + const marca = ap.peca?.marca ? String(ap.peca.marca).trim() : ''; const fase = ap.peca?.etapa_fase ? String(ap.peca.etapa_fase).trim() : ''; if (marca) { diff --git a/src/pages/smart/components/SmartConsultaRelatoriosFlow.tsx b/src/pages/smart/components/SmartConsultaRelatoriosFlow.tsx index 29a392e..861d9a6 100644 --- a/src/pages/smart/components/SmartConsultaRelatoriosFlow.tsx +++ b/src/pages/smart/components/SmartConsultaRelatoriosFlow.tsx @@ -90,10 +90,10 @@ export const SmartConsultaRelatoriosFlow: React.FC(); (resApontamentos.data || []).forEach((ap: any) => { + // Ignora apontamentos de componentes para não inflar as quantidades da peça mestre + if (ap.tipo_apontamento && ap.tipo_apontamento !== 'peca') return; + if (ap.componente_id) return; + const pecaId = ap.peca_id; const nomeProc = mapaNomeProcesso.get(ap.processo_id) || ''; const qtd = Number(ap.quantidade_produzida || 0); diff --git a/src/pages/smart/components/SmartProducaoFlow.tsx b/src/pages/smart/components/SmartProducaoFlow.tsx index a4f8250..d9f4633 100644 --- a/src/pages/smart/components/SmartProducaoFlow.tsx +++ b/src/pages/smart/components/SmartProducaoFlow.tsx @@ -94,7 +94,8 @@ export const calcularSaldoProcessoPeca = ( if (procAnteriorValido) { const keyAnt = `${peca.id}_${procAnteriorValido.id}`; const qtdApontadaAnterior = mapaProd.get(keyAnt) || 0; - qtdDisponivelParaEntrar = qtdApontadaAnterior; + // Trava de teto: o saldo para entrar jamais pode exceder o total da peça + qtdDisponivelParaEntrar = Math.min(Number(peca.quantidade) || 0, qtdApontadaAnterior); if (qtdApontadaAnterior === 0) { motivoBloqueio = `Aguardando ${procAnteriorValido.nome}`; @@ -127,7 +128,7 @@ export const calcularSaldoProcessoPeca = ( } } - const saldo = Math.max(0, qtdDisponivelParaEntrar - jaProduzidoAtual); + const saldo = Math.max(0, Math.min(Number(peca.quantidade) || 0, qtdDisponivelParaEntrar) - jaProduzidoAtual); return { saldo, @@ -149,6 +150,8 @@ interface ApontamentoItem { status_confirmacao?: string; forcado_por_user_nome?: string; usuario_nome?: string; + tipo_apontamento?: string; + componente_id?: string | null; } export const SmartProducaoFlow: React.FC = ({ @@ -190,7 +193,7 @@ export const SmartProducaoFlow: React.FC = ({ .eq('of_number', obra.of_number), supabase .from('apontamentos_producao') - .select('id, peca_id, processo_id, quantidade_produzida, is_forcado, status_confirmacao, forcado_por_user_nome, usuario_nome') + .select('id, peca_id, processo_id, quantidade_produzida, is_forcado, status_confirmacao, forcado_por_user_nome, usuario_nome, tipo_apontamento, componente_id') .eq('of_number', obra.of_number), ]); @@ -224,10 +227,14 @@ export const SmartProducaoFlow: React.FC = ({ return lista.length > 0 ? lista : ['Geral']; }, [pecas]); - // Mapa de produção acumulada por peca_id e processo_id + // Mapa de produção acumulada por peca_id e processo_id (apenas apontamentos de peças mestres) const mapaProducao = useMemo(() => { const mapa = new Map(); apontamentosExistentes.forEach((ap) => { + // Ignora apontamentos de componentes para não inflar a contagem da peça pai + if (ap.tipo_apontamento && ap.tipo_apontamento !== 'peca') return; + if (ap.componente_id) return; + const key = `${ap.peca_id}_${ap.processo_id}`; const atual = mapa.get(key) || 0; mapa.set(key, atual + Number(ap.quantidade_produzida || 0)); @@ -238,7 +245,11 @@ export const SmartProducaoFlow: React.FC = ({ // Apontamentos forçados que ainda estão pendentes de confirmação de baixa const apontamentosPendentes = useMemo(() => { return apontamentosExistentes.filter( - (ap) => ap.is_forcado && ap.status_confirmacao === 'pendente_confirmacao' + (ap) => + (!ap.tipo_apontamento || ap.tipo_apontamento === 'peca') && + !ap.componente_id && + ap.is_forcado && + ap.status_confirmacao === 'pendente_confirmacao' ); }, [apontamentosExistentes]); diff --git a/src/pages/smart/components/SmartViewer3DFlow.tsx b/src/pages/smart/components/SmartViewer3DFlow.tsx index e463462..eb09f29 100644 --- a/src/pages/smart/components/SmartViewer3DFlow.tsx +++ b/src/pages/smart/components/SmartViewer3DFlow.tsx @@ -69,7 +69,7 @@ export const SmartViewer3DFlow: React.FC = ({ supabase .from('apontamentos_producao' as any) .select(` - id, of_number, peca_id, quantidade_produzida, + id, of_number, peca_id, quantidade_produzida, tipo_apontamento, componente_id, peca:pecas!apontamentos_producao_peca_id_fkey(marca, etapa_fase), processo:processos_fabricacao!apontamentos_producao_processo_id_fkey(nome, cor, ordem) `) @@ -139,6 +139,10 @@ export const SmartViewer3DFlow: React.FC = ({ ); sortedApontamentos.forEach((ap: any) => { + // Ignora apontamentos de componentes para não inflar as peças mestres + if (ap.tipo_apontamento && ap.tipo_apontamento !== 'peca') return; + if (ap.componente_id) return; + const marca = ap.peca?.marca ? String(ap.peca.marca).trim() : ''; const fase = ap.peca?.etapa_fase ? String(ap.peca.etapa_fase).trim() : ''; if (marca) {