From 4ba12503672717b6ce3a2dd274f717bebdd17f73 Mon Sep 17 00:00:00 2001 From: Marcos Reifonas Date: Thu, 24 Sep 2026 20:55:59 +0000 Subject: [PATCH] fix: permitir diminuir e zerar/anular quantidade apontada no modo smart --- .../smart/components/SmartProducaoFlow.tsx | 151 ++++++++++++------ 1 file changed, 99 insertions(+), 52 deletions(-) diff --git a/src/pages/smart/components/SmartProducaoFlow.tsx b/src/pages/smart/components/SmartProducaoFlow.tsx index 9160661..b96349b 100644 --- a/src/pages/smart/components/SmartProducaoFlow.tsx +++ b/src/pages/smart/components/SmartProducaoFlow.tsx @@ -400,58 +400,93 @@ export const SmartProducaoFlow: React.FC = ({ const hoje = new Date().toISOString().split('T')[0]; const nomeUsuario = user.name || user.username || user.email?.split('@')[0] || 'Operador'; - let delta = qtdApontar; if (modoEdicao) { - delta = qtdApontar - info.jaProduzido; - } + if (qtdApontar === info.jaProduzido) { + smartAudio.playClick(); + toast.info('Nenhuma alteração na quantidade foi feita.'); + setEtapaAtual('pecas'); + setPecaSelecionada(null); + setModoEdicao(false); + setSalvando(false); + return; + } - if (delta === 0) { - smartAudio.playClick(); - toast.info('Nenhuma alteração na quantidade foi feita.'); - setEtapaAtual('pecas'); - setPecaSelecionada(null); - setModoEdicao(false); - setSalvando(false); - return; - } + // Em modo de edição/ajuste, removemos os apontamentos anteriores dessa peça/processo + // e, se a nova quantidade for > 0, inserimos o apontamento ajustado consolidado. + // Isso evita deltas negativos (que violam a check constraint quantidade_positiva) + // e permite zerar/anular o apontamento com perfeição. + const { error: deleteError } = await supabase + .from('apontamentos_producao') + .delete() + .eq('of_number', obra.of_number) + .eq('peca_id', pecaSelecionada.id) + .eq('processo_id', processoSelecionado.id); - const payload = { - of_number: obra.of_number, - peca_id: pecaSelecionada.id, - tipo_apontamento: 'peca' as const, - processo_id: processoSelecionado.id, - quantidade_produzida: delta, - data_apontamento: hoje, - created_by: user.id, - usuario_nome: nomeUsuario, - is_forcado: false, - status_confirmacao: 'confirmado', - observacoes: modoEdicao ? 'Ajuste de quantidade via Modo Smart' : 'Apontado via Modo Smart', - }; + if (deleteError) { + throw deleteError; + } - const { error } = await supabase.from('apontamentos_producao').insert(payload); + if (qtdApontar > 0) { + const payload = { + of_number: obra.of_number, + peca_id: pecaSelecionada.id, + tipo_apontamento: 'peca' as const, + processo_id: processoSelecionado.id, + quantidade_produzida: qtdApontar, + data_apontamento: hoje, + created_by: user.id, + usuario_nome: nomeUsuario, + is_forcado: false, + status_confirmacao: 'confirmado', + observacoes: `Ajuste de quantidade total para ${qtdApontar} un via Modo Smart`, + }; - if (error) { - throw error; - } + const { error: insertError } = await supabase.from('apontamentos_producao').insert(payload); + if (insertError) throw insertError; + } + + smartAudio.playSuccess(); + if (qtdApontar === 0) { + toast.success(`🗑️ Apontamento anulado/zerado: ${pecaSelecionada.marca} (${processoSelecionado.nome})`); + } else { + toast.success(`✏️ Ajuste realizado: ${pecaSelecionada.marca} (${processoSelecionado.nome}) para ${qtdApontar} un`); + } + + const delta = qtdApontar - info.jaProduzido; + const pesoTotalKg = delta * (pecaSelecionada.peso_unitario || 0); + onApontamentoRealizado(qtdApontar, pesoTotalKg); - // BIP sonoro de sucesso e vibração háptica! - smartAudio.playSuccess(); - if (modoEdicao) { - toast.success(`✏️ Ajuste realizado: ${pecaSelecionada.marca} (${processoSelecionado.nome}) para ${qtdApontar} un`); } else { + // Novo apontamento regular + const payload = { + of_number: obra.of_number, + peca_id: pecaSelecionada.id, + tipo_apontamento: 'peca' as const, + processo_id: processoSelecionado.id, + quantidade_produzida: qtdApontar, + data_apontamento: hoje, + created_by: user.id, + usuario_nome: nomeUsuario, + is_forcado: false, + status_confirmacao: 'confirmado', + observacoes: 'Apontado via Modo Smart', + }; + + const { error } = await supabase.from('apontamentos_producao').insert(payload); + if (error) { + throw error; + } + + smartAudio.playSuccess(); toast.success(`✅ Apontado: ${qtdApontar}x ${pecaSelecionada.marca} (${processoSelecionado.nome})`); + + const pesoTotalKg = qtdApontar * (pecaSelecionada.peso_unitario || 0); + onApontamentoRealizado(qtdApontar, pesoTotalKg); } - // Notificar estatísticas do operador - const pesoTotalKg = delta * (pecaSelecionada.peso_unitario || 0); - onApontamentoRealizado(qtdApontar, pesoTotalKg); - - // FAST LOOP / STICKY CONTEXT: - // Atualiza os dados imediatamente e volta para a lista de peças daquela Fase/Processo! + // Atualiza os dados imediatamente e volta para a lista de peças daquela Fase/Processo await carregarDadosOF(); - // Permanece na mesma fase para apontar a próxima peça sem voltar tudo! setEtapaAtual('pecas'); setPecaSelecionada(null); setModoEdicao(false); @@ -970,8 +1005,9 @@ export const SmartProducaoFlow: React.FC = ({ const somarQtd = (valor: number) => { smartAudio.playClick(); setQtdApontar((prev) => { - const nova = Math.max(1, prev + valor); - return saldoPendente > 0 ? Math.min(saldoPendente, nova) : nova; + const minQtd = modoEdicao ? 0 : 1; + const nova = Math.max(minQtd, prev + valor); + return maxPermitido > 0 ? Math.min(maxPermitido, nova) : nova; }); }; @@ -1069,7 +1105,7 @@ export const SmartProducaoFlow: React.FC = ({