246 lines
9.4 KiB
PL/PgSQL
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';
|