260 lines
8.2 KiB
PL/PgSQL
260 lines
8.2 KiB
PL/PgSQL
|
|
-- 1. Função para calcular a prioridade mais alta de uma peça
|
|
CREATE OR REPLACE FUNCTION calcular_prioridade_mais_alta_peca(p_peca_id uuid)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
prioridade_mais_alta text := 'P4'; -- Default
|
|
BEGIN
|
|
-- Buscar a prioridade mais alta desta peça em todas as prioridades de fabricação
|
|
SELECT
|
|
CASE
|
|
WHEN EXISTS (
|
|
SELECT 1 FROM itens_prioridade_fabricacao ipf
|
|
JOIN prioridades_fabricacao pf ON ipf.prioridade_fabricacao_id = pf.id
|
|
JOIN prioridades_config pc ON pf.prioridade_id = pc.id
|
|
WHERE ipf.peca_id = p_peca_id AND pc.codigo = 'P1'
|
|
) THEN 'P1'
|
|
WHEN EXISTS (
|
|
SELECT 1 FROM itens_prioridade_fabricacao ipf
|
|
JOIN prioridades_fabricacao pf ON ipf.prioridade_fabricacao_id = pf.id
|
|
JOIN prioridades_config pc ON pf.prioridade_id = pc.id
|
|
WHERE ipf.peca_id = p_peca_id AND pc.codigo = 'P2'
|
|
) THEN 'P2'
|
|
WHEN EXISTS (
|
|
SELECT 1 FROM itens_prioridade_fabricacao ipf
|
|
JOIN prioridades_fabricacao pf ON ipf.prioridade_fabricacao_id = pf.id
|
|
JOIN prioridades_config pc ON pf.prioridade_id = pc.id
|
|
WHERE ipf.peca_id = p_peca_id AND pc.codigo = 'P3'
|
|
) THEN 'P3'
|
|
ELSE 'P4'
|
|
END
|
|
INTO prioridade_mais_alta;
|
|
|
|
RETURN prioridade_mais_alta;
|
|
END;
|
|
$$;
|
|
|
|
-- 2. Função para sincronizar prioridade da peça
|
|
CREATE OR REPLACE FUNCTION sincronizar_prioridade_peca()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
peca_id_afetada uuid;
|
|
nova_prioridade text;
|
|
BEGIN
|
|
-- Determinar qual peça foi afetada
|
|
IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
|
|
peca_id_afetada := NEW.peca_id;
|
|
ELSIF TG_OP = 'DELETE' THEN
|
|
peca_id_afetada := OLD.peca_id;
|
|
END IF;
|
|
|
|
-- Calcular a nova prioridade mais alta para esta peça
|
|
nova_prioridade := calcular_prioridade_mais_alta_peca(peca_id_afetada);
|
|
|
|
-- Atualizar a coluna prioridade na tabela pecas
|
|
UPDATE pecas
|
|
SET prioridade = nova_prioridade,
|
|
updated_at = now()
|
|
WHERE id = peca_id_afetada;
|
|
|
|
-- Retornar o registro apropriado
|
|
IF TG_OP = 'DELETE' THEN
|
|
RETURN OLD;
|
|
ELSE
|
|
RETURN NEW;
|
|
END IF;
|
|
END;
|
|
$$;
|
|
|
|
-- 3. Criar trigger na tabela itens_prioridade_fabricacao
|
|
DROP TRIGGER IF EXISTS trigger_sincronizar_prioridade_peca ON itens_prioridade_fabricacao;
|
|
CREATE TRIGGER trigger_sincronizar_prioridade_peca
|
|
AFTER INSERT OR UPDATE OR DELETE ON itens_prioridade_fabricacao
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION sincronizar_prioridade_peca();
|
|
|
|
-- 4. Função para auto-criar prioridade P4 para peças novas
|
|
CREATE OR REPLACE FUNCTION auto_criar_prioridade_p4()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
prioridade_config_p4_id uuid;
|
|
prioridade_fabricacao_id uuid;
|
|
BEGIN
|
|
-- Garantir que a peça nova tenha prioridade P4
|
|
NEW.prioridade := 'P4';
|
|
|
|
-- Buscar ID da configuração de prioridade P4
|
|
SELECT id INTO prioridade_config_p4_id
|
|
FROM prioridades_config
|
|
WHERE codigo = 'P4';
|
|
|
|
IF prioridade_config_p4_id IS NULL THEN
|
|
RAISE EXCEPTION 'Configuração de prioridade P4 não encontrada';
|
|
END IF;
|
|
|
|
-- Buscar ou criar prioridade_fabricacao para P4 desta OF+fase
|
|
SELECT id INTO prioridade_fabricacao_id
|
|
FROM prioridades_fabricacao
|
|
WHERE of_number = NEW.of_number
|
|
AND etapa_fase = NEW.etapa_fase
|
|
AND prioridade_id = prioridade_config_p4_id;
|
|
|
|
-- Se não existe, criar a prioridade_fabricacao
|
|
IF prioridade_fabricacao_id IS NULL THEN
|
|
INSERT INTO prioridades_fabricacao (
|
|
of_number,
|
|
etapa_fase,
|
|
prioridade_id,
|
|
nome_prioridade,
|
|
ativo
|
|
) VALUES (
|
|
NEW.of_number,
|
|
NEW.etapa_fase,
|
|
prioridade_config_p4_id,
|
|
'P4 - Baixa',
|
|
true
|
|
) RETURNING id INTO prioridade_fabricacao_id;
|
|
END IF;
|
|
|
|
-- Criar item na prioridade P4 (será executado após o INSERT da peça)
|
|
-- Usar pg_notify para processar após o commit da transação
|
|
PERFORM pg_notify('nova_peca_p4', json_build_object(
|
|
'peca_id', NEW.id,
|
|
'prioridade_fabricacao_id', prioridade_fabricacao_id,
|
|
'peso_unitario', NEW.peso_unitario,
|
|
'quantidade', NEW.quantidade
|
|
)::text);
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
-- 5. Criar trigger na tabela pecas para auto-criar prioridade P4
|
|
DROP TRIGGER IF EXISTS trigger_auto_criar_prioridade_p4 ON pecas;
|
|
CREATE TRIGGER trigger_auto_criar_prioridade_p4
|
|
BEFORE INSERT ON pecas
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auto_criar_prioridade_p4();
|
|
|
|
-- 6. Função para processar peças novas após commit
|
|
CREATE OR REPLACE FUNCTION processar_peca_nova_p4()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
notification_data json;
|
|
peca_existe boolean;
|
|
BEGIN
|
|
-- Parse dos dados da notificação
|
|
notification_data := NEW.payload::json;
|
|
|
|
-- Verificar se a peça ainda não está na prioridade P4
|
|
SELECT EXISTS(
|
|
SELECT 1 FROM itens_prioridade_fabricacao
|
|
WHERE peca_id = (notification_data->>'peca_id')::uuid
|
|
AND prioridade_fabricacao_id = (notification_data->>'prioridade_fabricacao_id')::uuid
|
|
) INTO peca_existe;
|
|
|
|
-- Se não existe, criar o item
|
|
IF NOT peca_existe THEN
|
|
INSERT INTO itens_prioridade_fabricacao (
|
|
peca_id,
|
|
prioridade_fabricacao_id,
|
|
quantidade_priorizada,
|
|
peso_total,
|
|
ordem_fabricacao
|
|
) VALUES (
|
|
(notification_data->>'peca_id')::uuid,
|
|
(notification_data->>'prioridade_fabricacao_id')::uuid,
|
|
(notification_data->>'quantidade')::numeric,
|
|
(notification_data->>'quantidade')::numeric * (notification_data->>'peso_unitario')::numeric,
|
|
1
|
|
);
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
-- 7. Atualizar RLS na tabela pecas para impedir alteração manual da prioridade
|
|
DROP POLICY IF EXISTS "Users can update their own pecas" ON pecas;
|
|
CREATE POLICY "Users can update their own pecas" ON pecas
|
|
FOR UPDATE
|
|
USING (auth.uid() = user_id)
|
|
WITH CHECK (
|
|
auth.uid() = user_id AND
|
|
-- Impedir alteração da coluna prioridade manualmente
|
|
(OLD.prioridade = NEW.prioridade OR NEW.prioridade IS NULL)
|
|
);
|
|
|
|
-- 8. Migrar dados existentes - atualizar prioridades das peças com base no sistema atual
|
|
DO $$
|
|
DECLARE
|
|
peca_record record;
|
|
BEGIN
|
|
-- Para cada peça existente, calcular e atualizar sua prioridade
|
|
FOR peca_record IN
|
|
SELECT DISTINCT id FROM pecas
|
|
LOOP
|
|
UPDATE pecas
|
|
SET prioridade = calcular_prioridade_mais_alta_peca(peca_record.id)
|
|
WHERE id = peca_record.id;
|
|
END LOOP;
|
|
END $$;
|
|
|
|
-- 9. Criar peças em P4 para aquelas que não estão em nenhuma prioridade
|
|
INSERT INTO itens_prioridade_fabricacao (
|
|
peca_id,
|
|
prioridade_fabricacao_id,
|
|
quantidade_priorizada,
|
|
peso_total,
|
|
ordem_fabricacao
|
|
)
|
|
SELECT DISTINCT
|
|
p.id as peca_id,
|
|
pf.id as prioridade_fabricacao_id,
|
|
p.quantidade as quantidade_priorizada,
|
|
p.quantidade * p.peso_unitario as peso_total,
|
|
1 as ordem_fabricacao
|
|
FROM pecas p
|
|
JOIN prioridades_config pc ON pc.codigo = 'P4'
|
|
LEFT JOIN LATERAL (
|
|
SELECT pf.id
|
|
FROM prioridades_fabricacao pf
|
|
WHERE pf.of_number = p.of_number
|
|
AND pf.etapa_fase = p.etapa_fase
|
|
AND pf.prioridade_id = pc.id
|
|
LIMIT 1
|
|
) pf ON true
|
|
LEFT JOIN itens_prioridade_fabricacao ipf ON ipf.peca_id = p.id
|
|
WHERE ipf.id IS NULL -- Peças que não estão em nenhuma prioridade
|
|
AND pf.id IS NOT NULL; -- Apenas se existir a prioridade_fabricacao
|
|
|
|
-- 10. Criar prioridades_fabricacao P4 para OF+fase que não existem
|
|
INSERT INTO prioridades_fabricacao (
|
|
of_number,
|
|
etapa_fase,
|
|
prioridade_id,
|
|
nome_prioridade,
|
|
ativo
|
|
)
|
|
SELECT DISTINCT
|
|
p.of_number,
|
|
p.etapa_fase,
|
|
pc.id as prioridade_id,
|
|
'P4 - Baixa' as nome_prioridade,
|
|
true as ativo
|
|
FROM pecas p
|
|
JOIN prioridades_config pc ON pc.codigo = 'P4'
|
|
LEFT JOIN prioridades_fabricacao pf ON pf.of_number = p.of_number
|
|
AND pf.etapa_fase = p.etapa_fase
|
|
AND pf.prioridade_id = pc.id
|
|
WHERE pf.id IS NULL;
|