503 lines
18 KiB
SQL
503 lines
18 KiB
SQL
-- ========================================
|
|
-- MIGRATION: Multi-Tenant SaaS Schema (FIXED)
|
|
-- Data: 2024-12-02
|
|
-- Descrição: Estrutura completa para SaaS multi-tenant
|
|
-- ========================================
|
|
|
|
-- Habilitar extensões necessárias
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
|
|
-- ========================================
|
|
-- 1. TABELA DE ORGANIZAÇÕES (TENANTS)
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.organizacoes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
-- Identificação
|
|
slug VARCHAR(100) UNIQUE NOT NULL,
|
|
nome VARCHAR(255) NOT NULL,
|
|
razao_social VARCHAR(255),
|
|
cnpj VARCHAR(18) UNIQUE,
|
|
|
|
-- Contato
|
|
email_contato VARCHAR(255),
|
|
telefone VARCHAR(20),
|
|
endereco TEXT,
|
|
cidade VARCHAR(100),
|
|
estado VARCHAR(2),
|
|
cep VARCHAR(10),
|
|
|
|
-- Plano e limites
|
|
plano VARCHAR(50) DEFAULT 'trial' CHECK (plano IN ('trial', 'basic', 'professional', 'enterprise')),
|
|
max_usuarios INTEGER DEFAULT 5,
|
|
max_obras INTEGER DEFAULT 3,
|
|
max_rdos_mes INTEGER DEFAULT 100,
|
|
max_storage_mb INTEGER DEFAULT 500,
|
|
|
|
-- Personalização
|
|
logo_url TEXT,
|
|
cor_primaria VARCHAR(7) DEFAULT '#3B82F6',
|
|
cor_secundaria VARCHAR(7) DEFAULT '#1E40AF',
|
|
configuracoes JSONB DEFAULT '{}'::jsonb,
|
|
|
|
-- Status e controle
|
|
status VARCHAR(50) DEFAULT 'ativa' CHECK (status IN ('ativa', 'suspensa', 'cancelada', 'trial')),
|
|
data_trial_inicio TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
data_trial_fim TIMESTAMP WITH TIME ZONE DEFAULT (NOW() + INTERVAL '14 days'),
|
|
data_proxima_cobranca TIMESTAMP WITH TIME ZONE,
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
-- Constraints
|
|
CONSTRAINT slug_format CHECK (slug ~ '^[a-z0-9-]+$'),
|
|
CONSTRAINT slug_length CHECK (length(slug) >= 3 AND length(slug) <= 100)
|
|
);
|
|
|
|
-- Índices para organizações
|
|
CREATE INDEX IF NOT EXISTS idx_organizacoes_slug ON public.organizacoes(slug);
|
|
CREATE INDEX IF NOT EXISTS idx_organizacoes_status ON public.organizacoes(status);
|
|
CREATE INDEX IF NOT EXISTS idx_organizacoes_plano ON public.organizacoes(plano);
|
|
|
|
-- ========================================
|
|
-- 2. TABELA DE USUÁRIOS
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.usuarios (
|
|
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
organizacao_id UUID REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
|
|
-- Informações pessoais
|
|
nome VARCHAR(255) NOT NULL,
|
|
email VARCHAR(255) NOT NULL,
|
|
telefone VARCHAR(20),
|
|
cpf VARCHAR(14),
|
|
cargo VARCHAR(100),
|
|
|
|
-- Avatar
|
|
avatar_url TEXT,
|
|
|
|
-- Status
|
|
ativo BOOLEAN DEFAULT true,
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
-- Constraints
|
|
UNIQUE(organizacao_id, email)
|
|
);
|
|
|
|
-- Índices para usuários
|
|
CREATE INDEX IF NOT EXISTS idx_usuarios_org ON public.usuarios(organizacao_id, id);
|
|
CREATE INDEX IF NOT EXISTS idx_usuarios_email ON public.usuarios(email);
|
|
CREATE INDEX IF NOT EXISTS idx_usuarios_ativo ON public.usuarios(ativo);
|
|
|
|
-- ========================================
|
|
-- 3. TABELA DE ROLES E PERMISSÕES
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.organizacao_usuarios (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
usuario_id UUID NOT NULL REFERENCES public.usuarios(id) ON DELETE CASCADE,
|
|
|
|
-- Role na organização
|
|
role VARCHAR(50) NOT NULL CHECK (role IN ('owner', 'admin', 'engenheiro', 'mestre_obra', 'usuario')),
|
|
|
|
-- Permissões customizadas (opcional)
|
|
permissoes_customizadas JSONB DEFAULT '{}'::jsonb,
|
|
|
|
-- Status
|
|
ativo BOOLEAN DEFAULT true,
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
-- Constraints
|
|
UNIQUE(organizacao_id, usuario_id)
|
|
);
|
|
|
|
-- Índices
|
|
CREATE INDEX IF NOT EXISTS idx_org_usuarios_org ON public.organizacao_usuarios(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_org_usuarios_user ON public.organizacao_usuarios(usuario_id);
|
|
CREATE INDEX IF NOT EXISTS idx_org_usuarios_role ON public.organizacao_usuarios(role);
|
|
|
|
-- ========================================
|
|
-- 4. TABELA DE CONVITES
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.convites (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
|
|
-- Dados do convite
|
|
email VARCHAR(255) NOT NULL,
|
|
role VARCHAR(50) NOT NULL CHECK (role IN ('admin', 'engenheiro', 'mestre_obra', 'usuario')),
|
|
token VARCHAR(255) UNIQUE NOT NULL DEFAULT encode(random()::text::bytea, 'hex'),
|
|
|
|
-- Quem convidou
|
|
convidado_por UUID REFERENCES public.usuarios(id),
|
|
|
|
-- Status
|
|
status VARCHAR(50) DEFAULT 'pendente' CHECK (status IN ('pendente', 'aceito', 'expirado', 'cancelado')),
|
|
|
|
-- Datas
|
|
expira_em TIMESTAMP WITH TIME ZONE DEFAULT (NOW() + INTERVAL '7 days'),
|
|
aceito_em TIMESTAMP WITH TIME ZONE,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
-- Constraints
|
|
UNIQUE(organizacao_id, email, status)
|
|
);
|
|
|
|
-- Índices
|
|
CREATE INDEX IF NOT EXISTS idx_convites_org ON public.convites(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_convites_token ON public.convites(token);
|
|
CREATE INDEX IF NOT EXISTS idx_convites_status ON public.convites(status);
|
|
|
|
-- ========================================
|
|
-- 5. TABELA DE OBRAS
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.obras (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
|
|
-- Informações básicas
|
|
nome VARCHAR(255) NOT NULL,
|
|
descricao TEXT,
|
|
codigo VARCHAR(50),
|
|
|
|
-- Localização
|
|
endereco TEXT,
|
|
cidade VARCHAR(100),
|
|
estado VARCHAR(2),
|
|
cep VARCHAR(10),
|
|
coordenadas JSONB,
|
|
|
|
-- Cliente e contrato
|
|
cliente VARCHAR(255),
|
|
contrato VARCHAR(100),
|
|
valor_contrato DECIMAL(15,2),
|
|
|
|
-- Responsável
|
|
responsavel_id UUID REFERENCES public.usuarios(id),
|
|
|
|
-- Datas
|
|
data_inicio DATE,
|
|
data_prevista_fim DATE,
|
|
data_conclusao DATE,
|
|
|
|
-- Progresso
|
|
progresso_geral DECIMAL(5,2) DEFAULT 0 CHECK (progresso_geral >= 0 AND progresso_geral <= 100),
|
|
|
|
-- Status
|
|
status VARCHAR(50) DEFAULT 'planejamento' CHECK (status IN ('planejamento', 'ativa', 'pausada', 'concluida', 'cancelada')),
|
|
|
|
-- Configurações específicas da obra
|
|
configuracoes JSONB DEFAULT '{}'::jsonb,
|
|
|
|
-- Observações
|
|
observacoes TEXT,
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Índices
|
|
CREATE INDEX IF NOT EXISTS idx_obras_org ON public.obras(organizacao_id, id);
|
|
CREATE INDEX IF NOT EXISTS idx_obras_status ON public.obras(status);
|
|
CREATE INDEX IF NOT EXISTS idx_obras_responsavel ON public.obras(responsavel_id);
|
|
CREATE INDEX IF NOT EXISTS idx_obras_data_inicio ON public.obras(data_inicio);
|
|
|
|
-- ========================================
|
|
-- 6. TABELA DE RDOs
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.rdos (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
obra_id UUID NOT NULL REFERENCES public.obras(id) ON DELETE CASCADE,
|
|
|
|
-- Número sequencial por obra
|
|
numero INTEGER NOT NULL,
|
|
|
|
-- Criador
|
|
criado_por UUID NOT NULL REFERENCES public.usuarios(id),
|
|
|
|
-- Data do relatório
|
|
data_relatorio DATE NOT NULL DEFAULT CURRENT_DATE,
|
|
|
|
-- Condições climáticas
|
|
condicoes_climaticas VARCHAR(50),
|
|
temperatura_min DECIMAL(5,2),
|
|
temperatura_max DECIMAL(5,2),
|
|
observacoes_clima TEXT,
|
|
|
|
-- Observações gerais
|
|
observacoes_gerais TEXT,
|
|
|
|
-- Status e aprovação
|
|
status VARCHAR(50) DEFAULT 'rascunho' CHECK (status IN ('rascunho', 'enviado', 'aprovado', 'rejeitado')),
|
|
aprovado_por UUID REFERENCES public.usuarios(id),
|
|
aprovado_em TIMESTAMP WITH TIME ZONE,
|
|
motivo_rejeicao TEXT,
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
-- Constraints
|
|
UNIQUE(obra_id, numero),
|
|
UNIQUE(obra_id, data_relatorio)
|
|
);
|
|
|
|
-- Índices
|
|
CREATE INDEX IF NOT EXISTS idx_rdos_org ON public.rdos(organizacao_id, id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdos_obra ON public.rdos(obra_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdos_criador ON public.rdos(criado_por);
|
|
CREATE INDEX IF NOT EXISTS idx_rdos_data ON public.rdos(data_relatorio);
|
|
CREATE INDEX IF NOT EXISTS idx_rdos_status ON public.rdos(status);
|
|
|
|
-- ========================================
|
|
-- 7. TABELAS RELACIONADAS AO RDO
|
|
-- ========================================
|
|
|
|
-- 7.1 Atividades do RDO
|
|
CREATE TABLE IF NOT EXISTS public.rdo_atividades (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
rdo_id UUID NOT NULL REFERENCES public.rdos(id) ON DELETE CASCADE,
|
|
|
|
tipo_atividade VARCHAR(100) NOT NULL,
|
|
descricao TEXT NOT NULL,
|
|
localizacao VARCHAR(255),
|
|
percentual_concluido DECIMAL(5,2) DEFAULT 0 CHECK (percentual_concluido >= 0 AND percentual_concluido <= 100),
|
|
ordem INTEGER DEFAULT 0,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_atividades_org ON public.rdo_atividades(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_atividades_rdo ON public.rdo_atividades(rdo_id);
|
|
|
|
-- 7.2 Mão de Obra
|
|
CREATE TABLE IF NOT EXISTS public.rdo_mao_obra (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
rdo_id UUID NOT NULL REFERENCES public.rdos(id) ON DELETE CASCADE,
|
|
|
|
nome VARCHAR(255) NOT NULL,
|
|
funcao VARCHAR(100) NOT NULL,
|
|
quantidade INTEGER DEFAULT 1,
|
|
horas_trabalhadas DECIMAL(5,2) DEFAULT 8,
|
|
observacoes TEXT,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_mao_obra_org ON public.rdo_mao_obra(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_mao_obra_rdo ON public.rdo_mao_obra(rdo_id);
|
|
|
|
-- 7.3 Equipamentos
|
|
CREATE TABLE IF NOT EXISTS public.rdo_equipamentos (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
rdo_id UUID NOT NULL REFERENCES public.rdos(id) ON DELETE CASCADE,
|
|
|
|
nome_equipamento VARCHAR(255) NOT NULL,
|
|
tipo VARCHAR(100),
|
|
horas_utilizadas DECIMAL(5,2) DEFAULT 0,
|
|
combustivel_gasto DECIMAL(10,2) DEFAULT 0,
|
|
observacoes TEXT,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_equipamentos_org ON public.rdo_equipamentos(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_equipamentos_rdo ON public.rdo_equipamentos(rdo_id);
|
|
|
|
-- 7.4 Ocorrências
|
|
CREATE TABLE IF NOT EXISTS public.rdo_ocorrencias (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
rdo_id UUID NOT NULL REFERENCES public.rdos(id) ON DELETE CASCADE,
|
|
|
|
tipo_ocorrencia VARCHAR(100) NOT NULL,
|
|
descricao TEXT NOT NULL,
|
|
gravidade VARCHAR(50) DEFAULT 'media' CHECK (gravidade IN ('baixa', 'media', 'alta', 'critica')),
|
|
acao_tomada TEXT,
|
|
resolvida BOOLEAN DEFAULT false,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_ocorrencias_org ON public.rdo_ocorrencias(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_ocorrencias_rdo ON public.rdo_ocorrencias(rdo_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_ocorrencias_gravidade ON public.rdo_ocorrencias(gravidade);
|
|
|
|
-- 7.5 Anexos (Fotos e Documentos)
|
|
CREATE TABLE IF NOT EXISTS public.rdo_anexos (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
rdo_id UUID NOT NULL REFERENCES public.rdos(id) ON DELETE CASCADE,
|
|
|
|
nome_arquivo VARCHAR(255) NOT NULL,
|
|
tipo_arquivo VARCHAR(100),
|
|
url_storage TEXT NOT NULL,
|
|
tamanho_bytes BIGINT,
|
|
descricao TEXT,
|
|
ordem INTEGER DEFAULT 0,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_anexos_org ON public.rdo_anexos(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_anexos_rdo ON public.rdo_anexos(rdo_id);
|
|
|
|
-- 7.6 Inspeções de Solda (específico para estruturas metálicas)
|
|
CREATE TABLE IF NOT EXISTS public.rdo_inspecoes_solda (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
rdo_id UUID NOT NULL REFERENCES public.rdos(id) ON DELETE CASCADE,
|
|
|
|
identificacao_junta VARCHAR(100) NOT NULL,
|
|
status_inspecao VARCHAR(50) DEFAULT 'pendente' CHECK (status_inspecao IN ('aprovado', 'reprovado', 'pendente')),
|
|
metodo_inspecao VARCHAR(100),
|
|
observacoes TEXT,
|
|
inspecionado_por VARCHAR(255),
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_inspecoes_org ON public.rdo_inspecoes_solda(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_inspecoes_rdo ON public.rdo_inspecoes_solda(rdo_id);
|
|
|
|
-- 7.7 Verificações de Torque (específico para estruturas metálicas)
|
|
CREATE TABLE IF NOT EXISTS public.rdo_verificacoes_torque (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
rdo_id UUID NOT NULL REFERENCES public.rdos(id) ON DELETE CASCADE,
|
|
|
|
identificacao_parafuso VARCHAR(100) NOT NULL,
|
|
torque_especificado DECIMAL(10,2) DEFAULT 0,
|
|
torque_aplicado DECIMAL(10,2) NOT NULL,
|
|
status_verificacao VARCHAR(50) DEFAULT 'conforme' CHECK (status_verificacao IN ('conforme', 'nao_conforme')),
|
|
observacoes TEXT,
|
|
verificado_por VARCHAR(255),
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_verificacoes_org ON public.rdo_verificacoes_torque(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rdo_verificacoes_rdo ON public.rdo_verificacoes_torque(rdo_id);
|
|
|
|
-- ========================================
|
|
-- 8. TABELA DE TAREFAS
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.tarefas (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
obra_id UUID NOT NULL REFERENCES public.obras(id) ON DELETE CASCADE,
|
|
|
|
titulo VARCHAR(255) NOT NULL,
|
|
descricao TEXT,
|
|
|
|
status VARCHAR(50) DEFAULT 'pendente' CHECK (status IN ('pendente', 'em_andamento', 'concluida', 'cancelada')),
|
|
prioridade VARCHAR(50) DEFAULT 'media' CHECK (prioridade IN ('baixa', 'media', 'alta', 'urgente')),
|
|
|
|
responsavel_id UUID REFERENCES public.usuarios(id),
|
|
|
|
data_inicio DATE,
|
|
data_fim DATE,
|
|
progresso DECIMAL(5,2) DEFAULT 0 CHECK (progresso >= 0 AND progresso <= 100),
|
|
|
|
metadados JSONB DEFAULT '{}'::jsonb,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_tarefas_org ON public.tarefas(organizacao_id, id);
|
|
CREATE INDEX IF NOT EXISTS idx_tarefas_obra ON public.tarefas(obra_id);
|
|
CREATE INDEX IF NOT EXISTS idx_tarefas_responsavel ON public.tarefas(responsavel_id);
|
|
CREATE INDEX IF NOT EXISTS idx_tarefas_status ON public.tarefas(status);
|
|
|
|
-- ========================================
|
|
-- 9. TABELA DE LOGS DE TAREFAS
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.task_logs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
task_id UUID NOT NULL REFERENCES public.tarefas(id) ON DELETE CASCADE,
|
|
usuario_id UUID NOT NULL REFERENCES public.usuarios(id),
|
|
|
|
tipo_evento VARCHAR(50) NOT NULL CHECK (tipo_evento IN ('inicio', 'pausa', 'retomada', 'conclusao', 'revisao', 'edicao', 'cancelamento')),
|
|
descricao TEXT,
|
|
detalhes JSONB DEFAULT '{}'::jsonb,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_task_logs_org ON public.task_logs(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_task_logs_task ON public.task_logs(task_id);
|
|
CREATE INDEX IF NOT EXISTS idx_task_logs_usuario ON public.task_logs(usuario_id);
|
|
|
|
-- ========================================
|
|
-- 10. TABELA DE MÉTRICAS E USO
|
|
-- ========================================
|
|
|
|
CREATE TABLE IF NOT EXISTS public.organizacao_metricas (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organizacao_id UUID NOT NULL REFERENCES public.organizacoes(id) ON DELETE CASCADE,
|
|
mes_referencia DATE NOT NULL,
|
|
|
|
-- Contadores
|
|
total_usuarios INTEGER DEFAULT 0,
|
|
total_obras INTEGER DEFAULT 0,
|
|
total_rdos INTEGER DEFAULT 0,
|
|
storage_usado_mb DECIMAL(10,2) DEFAULT 0,
|
|
|
|
-- Limites do plano
|
|
limite_usuarios INTEGER,
|
|
limite_obras INTEGER,
|
|
limite_rdos_mes INTEGER,
|
|
limite_storage_mb INTEGER,
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
UNIQUE(organizacao_id, mes_referencia)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_org_metricas_org ON public.organizacao_metricas(organizacao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_org_metricas_mes ON public.organizacao_metricas(mes_referencia);
|
|
|
|
-- ========================================
|
|
-- COMENTÁRIOS PARA DOCUMENTAÇÃO
|
|
-- ========================================
|
|
|
|
COMMENT ON TABLE public.organizacoes IS 'Organizações/empresas (tenants) do sistema SaaS';
|
|
COMMENT ON TABLE public.usuarios IS 'Usuários do sistema vinculados a organizações';
|
|
COMMENT ON TABLE public.organizacao_usuarios IS 'Relacionamento entre usuários e organizações com roles';
|
|
COMMENT ON TABLE public.convites IS 'Convites pendentes para novos usuários';
|
|
COMMENT ON TABLE public.obras IS 'Obras/projetos de construção';
|
|
COMMENT ON TABLE public.rdos IS 'Relatórios Diários de Obra';
|
|
COMMENT ON TABLE public.rdo_atividades IS 'Atividades executadas registradas no RDO';
|
|
COMMENT ON TABLE public.rdo_mao_obra IS 'Mão de obra presente no dia do RDO';
|
|
COMMENT ON TABLE public.rdo_equipamentos IS 'Equipamentos utilizados no dia do RDO';
|
|
COMMENT ON TABLE public.rdo_ocorrencias IS 'Ocorrências e problemas reportados no RDO';
|
|
COMMENT ON TABLE public.rdo_anexos IS 'Fotos e documentos anexados ao RDO';
|
|
COMMENT ON TABLE public.rdo_inspecoes_solda IS 'Inspeções de solda para estruturas metálicas';
|
|
COMMENT ON TABLE public.rdo_verificacoes_torque IS 'Verificações de torque de parafusos';
|
|
COMMENT ON TABLE public.tarefas IS 'Tarefas planejadas para as obras';
|
|
COMMENT ON TABLE public.task_logs IS 'Histórico de eventos das tarefas';
|
|
COMMENT ON TABLE public.organizacao_metricas IS 'Métricas de uso por organização';
|