Files
tracksteel_app/supabase/migrations/20250726163232-b51b1ee8-d4a3-4af7-989b-24b2872af128.sql

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;