Files
tracksteel_app/supabase/migrations/20250731024730_d5b29825-4cce-4ddb-9430-e9744fe35dd5.sql

126 lines
4.7 KiB
PL/PgSQL

-- Remover a constraint única que está causando o problema
ALTER TABLE empenhos_material DROP CONSTRAINT IF EXISTS empenhos_material_of_number_material_id_key;
-- Criar nova função que consolida empenhos ao invés de criar duplicados
CREATE OR REPLACE FUNCTION public.sincronizar_empenhos_movimentacoes()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
empenho_existente_id UUID;
quantidade_atual NUMERIC;
BEGIN
-- Para INSERT de movimentação tipo empenho
IF TG_OP = 'INSERT' AND NEW.tipo_movimentacao = 'empenho' THEN
-- Verificar se já existe empenho para este material+OF
SELECT id, quantidade_empenhada INTO empenho_existente_id, quantidade_atual
FROM empenhos_material
WHERE material_id = NEW.material_id
AND of_number = NEW.of_vinculada
AND status = 'Empenhado'
LIMIT 1;
IF empenho_existente_id IS NOT NULL THEN
-- Atualizar empenho existente
UPDATE empenhos_material
SET quantidade_empenhada = quantidade_empenhada + NEW.quantidade,
movimentacao_empenho_id = NEW.id,
observacoes = COALESCE(observacoes, '') ||
CASE WHEN observacoes IS NOT NULL AND observacoes != ''
THEN '; ' || COALESCE(NEW.observacoes, '')
ELSE COALESCE(NEW.observacoes, '') END
WHERE id = empenho_existente_id;
ELSE
-- Criar novo empenho
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
-- Diminuir quantidade empenhada ou remover se for a única
WITH empenho_atual AS (
SELECT id, quantidade_empenhada
FROM empenhos_material
WHERE movimentacao_empenho_id = OLD.id
)
UPDATE empenhos_material
SET quantidade_empenhada = quantidade_empenhada - OLD.quantidade
FROM empenho_atual
WHERE empenhos_material.id = empenho_atual.id;
-- Remover empenho se quantidade chegou a zero
DELETE FROM empenhos_material
WHERE quantidade_empenhada <= 0 AND 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$;