Files
RDO/setup_rdo_schema_final.sql

246 lines
9.4 KiB
PL/PgSQL

-- ============================================================================
-- SCRIPT DE MIGRAÇÃO: CONFIGURAÇÃO DO ESQUEMA 'rdo'
-- ============================================================================
-- Este script cria o esquema 'rdo', tabelas e permissões necessárias
-- para alinhar o banco de dados com a configuração do app.
-- ============================================================================
-- 1. CRIAR ESQUEMA
-- ============================================================================
CREATE SCHEMA IF NOT EXISTS rdo;
-- 2. GARANTIR EXTENSÕES
-- ============================================================================
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- 3. CRIAR TABELAS NO ESQUEMA 'rdo'
-- ============================================================================
-- Tabela: Organizacoes
CREATE TABLE IF NOT EXISTS rdo.organizacoes (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
nome TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
razao_social TEXT,
cnpj TEXT,
status TEXT DEFAULT 'ativa' CHECK (status IN ('ativa', 'inativa', 'suspensa')),
plano TEXT DEFAULT 'trial' CHECK (plano IN ('trial', 'basico', 'profissional', 'enterprise')),
max_usuarios INTEGER DEFAULT 5,
max_obras INTEGER DEFAULT 10,
max_rdos_mes INTEGER DEFAULT 100,
max_storage_mb INTEGER DEFAULT 1024,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela: Usuarios
CREATE TABLE IF NOT EXISTS rdo.usuarios (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
organizacao_id UUID REFERENCES rdo.organizacoes(id) ON DELETE SET NULL,
email TEXT NOT NULL,
nome TEXT NOT NULL,
telefone TEXT,
cargo TEXT,
role TEXT DEFAULT 'usuario' CHECK (role IN ('dev', 'admin', 'engenheiro', 'mestre_obra', 'usuario')),
ativo BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela: Obras
CREATE TABLE IF NOT EXISTS rdo.obras (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
organizacao_id UUID NOT NULL REFERENCES rdo.organizacoes(id) ON DELETE CASCADE,
nome TEXT NOT NULL,
descricao TEXT,
endereco TEXT,
cep TEXT,
cidade TEXT,
estado TEXT,
responsavel_id UUID REFERENCES rdo.usuarios(id) ON DELETE SET NULL,
data_inicio DATE,
data_prevista_fim DATE,
data_conclusao DATE,
progresso_geral NUMERIC(5,2) DEFAULT 0,
status TEXT DEFAULT 'ativa' CHECK (status IN ('ativa', 'pausada', 'concluida', 'cancelada')),
configuracoes JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela: RDOs
CREATE TABLE IF NOT EXISTS rdo.rdos (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
organizacao_id UUID REFERENCES rdo.organizacoes(id) ON DELETE CASCADE,
obra_id UUID NOT NULL REFERENCES rdo.obras(id) ON DELETE CASCADE,
criado_por UUID NOT NULL REFERENCES rdo.usuarios(id),
data_relatorio DATE NOT NULL,
condicoes_climaticas TEXT NOT NULL,
observacoes_gerais TEXT,
status TEXT DEFAULT 'rascunho' CHECK (status IN ('rascunho', 'enviado', 'aprovado', 'rejeitado')),
aprovado_por UUID REFERENCES rdo.usuarios(id),
aprovado_em TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela: RDO Atividades
CREATE TABLE IF NOT EXISTS rdo.rdo_atividades (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
tipo_atividade TEXT NOT NULL,
descricao TEXT NOT NULL,
localizacao TEXT,
percentual_concluido NUMERIC(5,2) DEFAULT 0,
ordem INTEGER DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela: RDO Mão de Obra
CREATE TABLE IF NOT EXISTS rdo.rdo_mao_obra (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
funcao TEXT NOT NULL,
quantidade INTEGER DEFAULT 0,
horas_trabalhadas NUMERIC(5,2) DEFAULT 0,
observacoes TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela: RDO Equipamentos
CREATE TABLE IF NOT EXISTS rdo.rdo_equipamentos (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
nome_equipamento TEXT NOT NULL,
tipo TEXT,
horas_utilizadas NUMERIC(5,2) DEFAULT 0,
combustivel_gasto NUMERIC(10,2) DEFAULT 0,
observacoes TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela: RDO Ocorrencias
CREATE TABLE IF NOT EXISTS rdo.rdo_ocorrencias (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
tipo_ocorrencia TEXT NOT NULL,
descricao TEXT NOT NULL,
gravidade TEXT CHECK (gravidade IN ('baixa', 'media', 'alta', 'critica')),
acao_tomada TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela: RDO Anexos
CREATE TABLE IF NOT EXISTS rdo.rdo_anexos (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
nome_arquivo TEXT NOT NULL,
tipo_arquivo TEXT,
url_storage TEXT NOT NULL,
tamanho_bytes BIGINT,
descricao TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 4. HABILITAR RLS NO NOVO ESQUEMA
-- ============================================================================
ALTER TABLE rdo.organizacoes ENABLE ROW LEVEL SECURITY;
ALTER TABLE rdo.usuarios ENABLE ROW LEVEL SECURITY;
ALTER TABLE rdo.obras ENABLE ROW LEVEL SECURITY;
ALTER TABLE rdo.rdos ENABLE ROW LEVEL SECURITY;
ALTER TABLE rdo.rdo_atividades ENABLE ROW LEVEL SECURITY;
ALTER TABLE rdo.rdo_mao_obra ENABLE ROW LEVEL SECURITY;
ALTER TABLE rdo.rdo_equipamentos ENABLE ROW LEVEL SECURITY;
ALTER TABLE rdo.rdo_ocorrencias ENABLE ROW LEVEL SECURITY;
ALTER TABLE rdo.rdo_anexos ENABLE ROW LEVEL SECURITY;
-- 5. CRIAR POLÍTICAS PERMISSIVAS (INICIAL) PARA AUTHENTICATED
-- ============================================================================
CREATE POLICY "auth_all_rdo_usuarios" ON rdo.usuarios FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "auth_all_rdo_orgs" ON rdo.organizacoes FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "auth_all_rdo_obras" ON rdo.obras FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "auth_all_rdo_rdos" ON rdo.rdos FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "auth_all_rdo_ativ" ON rdo.rdo_atividades FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "auth_all_rdo_mao" ON rdo.rdo_mao_obra FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "auth_all_rdo_equip" ON rdo.rdo_equipamentos FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "auth_all_rdo_ocor" ON rdo.rdo_ocorrencias FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "auth_all_rdo_anex" ON rdo.rdo_anexos FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
-- 6. PERMISSÕES DE SCHEMA
-- ============================================================================
GRANT USAGE ON SCHEMA rdo TO authenticated, anon;
GRANT ALL ON ALL TABLES IN SCHEMA rdo TO authenticated;
GRANT ALL ON ALL SEQUENCES IN SCHEMA rdo TO authenticated;
GRANT ALL ON ALL FUNCTIONS IN SCHEMA rdo TO authenticated;
-- 7. CORRIGIR TRIGGER PARA O NOVO ESQUEMA
-- ============================================================================
CREATE OR REPLACE FUNCTION rdo.handle_new_user()
RETURNS TRIGGER
SECURITY DEFINER
SET search_path = rdo, public
AS $$
DECLARE
user_name TEXT;
BEGIN
-- Extrair nome
user_name := COALESCE(
NEW.raw_user_meta_data->>'nome',
NEW.raw_user_meta_data->>'name',
NEW.raw_user_meta_data->>'full_name',
split_part(NEW.email, '@', 1)
);
-- Inserir em rdo.usuarios
INSERT INTO rdo.usuarios (
id,
email,
nome,
role,
ativo
) VALUES (
NEW.id,
NEW.email,
user_name,
'usuario',
true
)
ON CONFLICT (id) DO UPDATE SET
email = EXCLUDED.email,
nome = COALESCE(EXCLUDED.nome, rdo.usuarios.nome),
updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Remover trigger antigo se existir em auth.users
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
-- Criar novo trigger apontando para a função no esquema rdo
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW
EXECUTE FUNCTION rdo.handle_new_user();
-- 8. DADOS INICIAIS (SEED)
-- ============================================================================
-- Criar organização padrão se não houver nenhuma
INSERT INTO rdo.organizacoes (nome, slug, status, plano)
VALUES ('Baldon Engemetal', 'baldon-engemetal', 'ativa', 'profissional')
ON CONFLICT (slug) DO NOTHING;
-- Garantir que o admin atual seja um usuário no esquema rdo (se ele já existir no Auth)
INSERT INTO rdo.usuarios (id, email, nome, role, ativo)
SELECT id, email, 'Admin TrackSteel', 'dev', true
FROM auth.users
WHERE email = 'admtracksteel@gmail.com'
ON CONFLICT (id) DO UPDATE SET role = 'dev', ativo = true;
-- Associar admin à organização Baldon
UPDATE rdo.usuarios
SET organizacao_id = (SELECT id FROM rdo.organizacoes WHERE slug = 'baldon-engemetal' LIMIT 1)
WHERE email = 'admtracksteel@gmail.com';