214 lines
8.6 KiB
PL/PgSQL
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();
|