Files
tracksteel_app/supabase/migrations/20250731024308_4cf3d60f-e54a-453e-aa62-e7e26c8fb3b4.sql

107 lines
3.9 KiB
PL/PgSQL

-- Primeiro, vamos verificar e corrigir a foreign key constraint
-- Vamos dropar a constraint problemática e recriar corretamente
-- Dropar a constraint existente se ela existir
ALTER TABLE empenhos_material DROP CONSTRAINT IF EXISTS empenhos_material_movimentacao_empenho_id_fkey;
-- Recriar a constraint como DEFERRABLE para permitir que seja verificada ao final da transação
ALTER TABLE empenhos_material
ADD CONSTRAINT empenhos_material_movimentacao_empenho_id_fkey
FOREIGN KEY (movimentacao_empenho_id)
REFERENCES movimentacoes_estoque(id)
ON DELETE SET NULL
DEFERRABLE INITIALLY DEFERRED;
-- Também vamos ajustar a função para ser mais robusta
CREATE OR REPLACE FUNCTION public.sincronizar_empenhos_movimentacoes()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
-- Para INSERT de movimentação tipo empenho
IF TG_OP = 'INSERT' AND NEW.tipo_movimentacao = 'empenho' THEN
-- Aguardar um momento para garantir que o registro está commitado
PERFORM pg_sleep(0.001);
-- Verificar se o registro da movimentação realmente existe
IF EXISTS (SELECT 1 FROM movimentacoes_estoque WHERE id = NEW.id) THEN
-- Inserir registro na tabela empenhos_material
INSERT INTO empenhos_material (
material_id,
of_number,
quantidade_empenhada,
quantidade_utilizada,
lote,
observacoes,
movimentacao_empenho_id,
created_by,
status,
data_empenho
) VALUES (
NEW.material_id,
NEW.of_vinculada,
NEW.quantidade,
0,
NEW.lote,
NEW.observacoes,
NEW.id,
NEW.created_by,
'Empenhado',
NEW.data_movimentacao
);
END IF;
RETURN NEW;
END IF;
-- Para INSERT de movimentação tipo desempenho
IF TG_OP = 'INSERT' AND NEW.tipo_movimentacao = 'desempenho' THEN
-- Atualizar quantidade utilizada no empenho correspondente
WITH empenhos_ordenados AS (
SELECT id, quantidade_empenhada, quantidade_utilizada,
(quantidade_empenhada - quantidade_utilizada) as disponivel_para_utilizar
FROM empenhos_material
WHERE material_id = NEW.material_id
AND of_number = NEW.of_vinculada
AND status = 'Empenhado'
AND quantidade_utilizada < quantidade_empenhada
ORDER BY data_empenho ASC
LIMIT 1
)
UPDATE empenhos_material
SET quantidade_utilizada = quantidade_utilizada + LEAST(NEW.quantidade, empenhos_ordenados.disponivel_para_utilizar),
status = CASE
WHEN quantidade_utilizada + LEAST(NEW.quantidade, empenhos_ordenados.disponivel_para_utilizar) >= quantidade_empenhada
THEN 'Finalizado'
ELSE 'Empenhado'
END
FROM empenhos_ordenados
WHERE empenhos_material.id = empenhos_ordenados.id;
RETURN NEW;
END IF;
-- Para DELETE de movimentação tipo empenho
IF TG_OP = 'DELETE' AND OLD.tipo_movimentacao = 'empenho' THEN
-- Remover registro da tabela empenhos_material
DELETE FROM empenhos_material
WHERE movimentacao_empenho_id = OLD.id;
RETURN OLD;
END IF;
-- Para DELETE de movimentação tipo desempenho
IF TG_OP = 'DELETE' AND OLD.tipo_movimentacao = 'desempenho' THEN
-- Reverter quantidade utilizada no empenho
UPDATE empenhos_material
SET quantidade_utilizada = GREATEST(0, quantidade_utilizada - OLD.quantidade),
status = 'Empenhado'
WHERE material_id = OLD.material_id
AND of_number = OLD.of_vinculada
AND quantidade_utilizada > 0;
RETURN OLD;
END IF;
RETURN COALESCE(NEW, OLD);
END;
$function$;