fix(apontamentos): previne erro 409 por trigger de concorrência e melhora tratamento de erro

This commit is contained in:
2026-08-31 21:00:13 +00:00
parent 8107e46eb1
commit f27610df97
2 changed files with 57 additions and 2 deletions
+5 -2
View File
@@ -381,9 +381,12 @@ interface InsertApontamentoData {
toast.success('Apontamento registrado com sucesso!'); toast.success('Apontamento registrado com sucesso!');
return { success: true }; return { success: true };
} catch (error) { } catch (error: any) {
console.error('❌ Erro ao criar apontamento:', error); console.error('❌ Erro ao criar apontamento:', error);
const errorMessage = error instanceof Error ? error.message : String(error); const isConflict = error?.status === 409 || error?.code === '23505' || String(error?.message || '').includes('409');
const errorMessage = isConflict
? 'Este item ou processo já teve o apontamento registrado por outro usuário ou os dados em cache estão desatualizados. Por favor, clique em "Limpar" no cache e atualize a página.'
: (error instanceof Error ? error.message : String(error));
toast.error('Erro ao registrar apontamento: ' + errorMessage); toast.error('Erro ao registrar apontamento: ' + errorMessage);
return { success: false, error }; return { success: false, error };
} }
@@ -0,0 +1,52 @@
-- Migration para corrigir a trigger atualizar_datas_reais_processo e prevenir erros 409 (Conflict) em inserções concorrentes de apontamentos
CREATE OR REPLACE FUNCTION public.atualizar_datas_reais_processo()
RETURNS TRIGGER AS $$
DECLARE
total_produzido NUMERIC;
total_planejado NUMERIC;
BEGIN
-- Se peca_id for nulo (ex: apontamento de componente sem peca_id vinculada), ignorar processamento de datas por peça
IF NEW.peca_id IS NULL THEN
RETURN NEW;
END IF;
-- Buscar quantidade total planejada da peça
SELECT COALESCE(quantidade, 0) INTO total_planejado
FROM public.pecas
WHERE id = NEW.peca_id;
-- Inserir novo registro ou atualizar existente usando ON CONFLICT para evitar erro 409 (Constraint UNIQUE peca_id + processo_id)
INSERT INTO public.processos_pecas_datas (
peca_id,
processo_id,
data_inicio_real,
quantidade_total_planejada,
quantidade_total_produzida
) VALUES (
NEW.peca_id,
NEW.processo_id,
NEW.data_apontamento,
total_planejado,
NEW.quantidade_produzida
)
ON CONFLICT (peca_id, processo_id) DO UPDATE
SET
quantidade_total_produzida = (
SELECT COALESCE(SUM(quantidade_produzida), 0)
FROM public.apontamentos_producao
WHERE peca_id = NEW.peca_id AND processo_id = NEW.processo_id
),
data_conclusao_real = CASE
WHEN (
SELECT COALESCE(SUM(quantidade_produzida), 0)
FROM public.apontamentos_producao
WHERE peca_id = NEW.peca_id AND processo_id = NEW.processo_id
) >= processos_pecas_datas.quantidade_total_planejada THEN NEW.data_apontamento
ELSE processos_pecas_datas.data_conclusao_real
END,
updated_at = now();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;