Files
tracksteel_app/supabase/migrations/20250731021728_1706e095-465b-45cd-be33-87364b8398f2.sql

214 lines
8.6 KiB
PL/PgSQL

-- 1. Primeiro, vamos corrigir os triggers existentes e garantir consistência
-- Remover triggers existentes que podem estar causando problemas
DROP TRIGGER IF EXISTS trigger_processar_movimentacao_estoque ON movimentacoes_estoque;
DROP TRIGGER IF EXISTS trigger_sincronizar_empenhos_movimentacoes ON movimentacoes_estoque;
-- Criar função consolidada para processar movimentações de estoque
CREATE OR REPLACE FUNCTION public.processar_movimentacao_estoque_consolidada()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
-- Para INSERT (nova movimentação)
IF TG_OP = 'INSERT' THEN
-- Atualizar quantidades no estoque baseado no tipo de movimentação
IF NEW.tipo_movimentacao = 'entrada' THEN
UPDATE estoque_materiais
SET quantidade_total = quantidade_total + NEW.quantidade,
quantidade_disponivel = quantidade_disponivel + NEW.quantidade
WHERE id = NEW.material_id;
ELSIF NEW.tipo_movimentacao = 'saida' THEN
UPDATE estoque_materiais
SET quantidade_total = quantidade_total - NEW.quantidade,
quantidade_disponivel = quantidade_disponivel - NEW.quantidade
WHERE id = NEW.material_id;
ELSIF NEW.tipo_movimentacao = 'empenho' THEN
-- Para empenho: diminuir disponível, aumentar empenhada
UPDATE estoque_materiais
SET quantidade_disponivel = quantidade_disponivel - NEW.quantidade,
quantidade_empenhada = quantidade_empenhada + NEW.quantidade
WHERE id = NEW.material_id;
-- Criar registro de empenho automaticamente
INSERT INTO empenhos_material (
material_id,
of_number,
quantidade_empenhada,
quantidade_utilizada,
lote,
observacoes,
status,
data_empenho,
created_by,
movimentacao_empenho_id
) VALUES (
NEW.material_id,
NEW.of_vinculada,
NEW.quantidade,
0,
NEW.lote,
NEW.observacoes,
'Empenhado',
NEW.data_movimentacao,
NEW.created_by,
NEW.id
);
ELSIF NEW.tipo_movimentacao = 'desempenho' THEN
-- Para desempenho: aumentar disponível, diminuir empenhada
UPDATE estoque_materiais
SET quantidade_disponivel = quantidade_disponivel + NEW.quantidade,
quantidade_empenhada = quantidade_empenhada - NEW.quantidade
WHERE id = NEW.material_id;
-- Atualizar quantidade utilizada nos empenhos existentes
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
),
atualizacao AS (
SELECT id,
CASE
WHEN NEW.quantidade <= disponivel_para_utilizar THEN NEW.quantidade
ELSE disponivel_para_utilizar
END as qtd_a_utilizar
FROM empenhos_ordenados
LIMIT 1
)
UPDATE empenhos_material
SET quantidade_utilizada = quantidade_utilizada + atualizacao.qtd_a_utilizar,
status = CASE
WHEN quantidade_utilizada + atualizacao.qtd_a_utilizar >= quantidade_empenhada
THEN 'Finalizado'
ELSE 'Empenhado'
END
FROM atualizacao
WHERE empenhos_material.id = atualizacao.id;
ELSIF NEW.tipo_movimentacao = 'ajuste' THEN
UPDATE estoque_materiais
SET quantidade_total = quantidade_total + NEW.quantidade,
quantidade_disponivel = quantidade_disponivel + NEW.quantidade
WHERE id = NEW.material_id;
ELSIF NEW.tipo_movimentacao = 'transferencia' THEN
UPDATE estoque_materiais
SET quantidade_disponivel = quantidade_disponivel - NEW.quantidade
WHERE id = NEW.material_id;
END IF;
RETURN NEW;
END IF;
-- Para DELETE (reversão da movimentação)
IF TG_OP = 'DELETE' THEN
-- Reverter as operações baseado no tipo de movimentação
IF OLD.tipo_movimentacao = 'entrada' THEN
UPDATE estoque_materiais
SET quantidade_total = quantidade_total - OLD.quantidade,
quantidade_disponivel = quantidade_disponivel - OLD.quantidade
WHERE id = OLD.material_id;
ELSIF OLD.tipo_movimentacao = 'saida' THEN
UPDATE estoque_materiais
SET quantidade_total = quantidade_total + OLD.quantidade,
quantidade_disponivel = quantidade_disponivel + OLD.quantidade
WHERE id = OLD.material_id;
ELSIF OLD.tipo_movimentacao = 'empenho' THEN
-- Reverter empenho: aumentar disponível, diminuir empenhada
UPDATE estoque_materiais
SET quantidade_disponivel = quantidade_disponivel + OLD.quantidade,
quantidade_empenhada = quantidade_empenhada - OLD.quantidade
WHERE id = OLD.material_id;
-- Excluir o empenho vinculado
DELETE FROM empenhos_material
WHERE movimentacao_empenho_id = OLD.id;
ELSIF OLD.tipo_movimentacao = 'desempenho' THEN
-- Reverter desempenho: diminuir disponível, aumentar empenhada
UPDATE estoque_materiais
SET quantidade_disponivel = quantidade_disponivel - OLD.quantidade,
quantidade_empenhada = quantidade_empenhada + OLD.quantidade
WHERE id = OLD.material_id;
-- Reverter quantidade utilizada nos empenhos
UPDATE empenhos_material
SET quantidade_utilizada = quantidade_utilizada - OLD.quantidade,
status = 'Empenhado'
WHERE material_id = OLD.material_id
AND of_number = OLD.of_vinculada
AND quantidade_utilizada >= OLD.quantidade;
ELSIF OLD.tipo_movimentacao = 'ajuste' THEN
UPDATE estoque_materiais
SET quantidade_total = quantidade_total - OLD.quantidade,
quantidade_disponivel = quantidade_disponivel - OLD.quantidade
WHERE id = OLD.material_id;
ELSIF OLD.tipo_movimentacao = 'transferencia' THEN
UPDATE estoque_materiais
SET quantidade_disponivel = quantidade_disponivel + OLD.quantidade
WHERE id = OLD.material_id;
END IF;
RETURN OLD;
END IF;
RETURN NULL;
END;
$function$;
-- Criar o trigger consolidado
CREATE TRIGGER trigger_processar_movimentacao_estoque_consolidada
BEFORE INSERT OR DELETE ON movimentacoes_estoque
FOR EACH ROW EXECUTE FUNCTION processar_movimentacao_estoque_consolidada();
-- Função para limpar dados inconsistentes
CREATE OR REPLACE FUNCTION public.limpar_dados_inconsistentes_estoque()
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
BEGIN
-- Recalcular quantidades empenhadas baseado na tabela de empenhos
UPDATE estoque_materiais
SET quantidade_empenhada = COALESCE(
(SELECT SUM(quantidade_empenhada - quantidade_utilizada)
FROM empenhos_material
WHERE material_id = estoque_materiais.id
AND status = 'Empenhado'),
0
);
-- Remover empenhos órfãos (sem movimentação vinculada)
DELETE FROM empenhos_material
WHERE movimentacao_empenho_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM movimentacoes_estoque
WHERE id = empenhos_material.movimentacao_empenho_id
);
-- Remover movimentações órfãs de empenho (sem material)
DELETE FROM movimentacoes_estoque
WHERE tipo_movimentacao = 'empenho'
AND NOT EXISTS (
SELECT 1 FROM estoque_materiais
WHERE id = movimentacoes_estoque.material_id
);
END;
$function$;
-- Executar limpeza de dados inconsistentes
SELECT limpar_dados_inconsistentes_estoque();