first commit
This commit is contained in:
@@ -0,0 +1,451 @@
|
||||
-- ============================================================
|
||||
-- SeConectAI Vendas — Schema PostgreSQL (multi-tenant CRM/Vendas)
|
||||
-- ============================================================
|
||||
-- Estratégia de multi-tenancy: banco único, isolado por tenant_id
|
||||
-- + Row Level Security (RLS). Mais simples de operar em Docker/
|
||||
-- Docker Compose do que "schema por tenant" e escala bem até
|
||||
-- centenas de tenants num único Postgres.
|
||||
-- ============================================================
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- gen_random_uuid()
|
||||
|
||||
-- ============================================================
|
||||
-- 1. NÍVEL MASTER (você — dono da plataforma)
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE master_admins (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
nome VARCHAR(150) NOT NULL,
|
||||
email VARCHAR(150) UNIQUE NOT NULL,
|
||||
senha_hash TEXT NOT NULL, -- argon2id ou bcrypt cost>=12
|
||||
ativo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
mfa_secret TEXT, -- TOTP opcional, recomendado p/ master
|
||||
ultimo_login TIMESTAMPTZ,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
atualizado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Conexão(ões) com a Evolution API 2.3, cadastrada pelo master.
|
||||
-- Pode haver mais de um servidor Evolution (ex: para balancear carga).
|
||||
CREATE TABLE evolution_api_config (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
nome VARCHAR(100) NOT NULL, -- "Servidor Principal"
|
||||
base_url VARCHAR(255) NOT NULL,
|
||||
api_key_cripto TEXT NOT NULL, -- criptografar em repouso (app-level, ex: AES-256-GCM)
|
||||
versao VARCHAR(20) NOT NULL DEFAULT '2.3',
|
||||
ativo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Config SMTP padrão da plataforma (fallback quando o tenant não
|
||||
-- tem SMTP próprio cadastrado)
|
||||
CREATE TABLE master_email_config (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
smtp_host VARCHAR(150) NOT NULL,
|
||||
smtp_porta INTEGER NOT NULL,
|
||||
smtp_usuario VARCHAR(150) NOT NULL,
|
||||
smtp_senha_cripto TEXT NOT NULL,
|
||||
email_remetente VARCHAR(150) NOT NULL,
|
||||
ativo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE planos (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
nome VARCHAR(100) NOT NULL,
|
||||
descricao TEXT,
|
||||
valor_mensal NUMERIC(10,2) NOT NULL,
|
||||
limite_customers INTEGER, -- NULL = ilimitado
|
||||
limite_usuarios INTEGER,
|
||||
limite_instancias_whatsapp INTEGER NOT NULL DEFAULT 1,
|
||||
ativo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. TENANTS — seus clientes que compram/usam a plataforma
|
||||
-- ============================================================
|
||||
|
||||
CREATE TYPE tenant_status AS ENUM ('trial', 'ativo', 'inadimplente', 'suspenso', 'cancelado');
|
||||
|
||||
CREATE TABLE tenants (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
razao_social VARCHAR(200) NOT NULL,
|
||||
nome_fantasia VARCHAR(200),
|
||||
documento VARCHAR(20), -- CNPJ/CPF
|
||||
email_contato VARCHAR(150) NOT NULL,
|
||||
telefone VARCHAR(20),
|
||||
logo_url TEXT, -- personalização visual (whitelabel)
|
||||
cor_primaria VARCHAR(7), -- "#1a73e8"
|
||||
plano_id UUID REFERENCES planos(id),
|
||||
status tenant_status NOT NULL DEFAULT 'trial',
|
||||
dia_vencimento_mensalidade SMALLINT NOT NULL DEFAULT 10
|
||||
CHECK (dia_vencimento_mensalidade BETWEEN 1 AND 28),
|
||||
trial_expira_em TIMESTAMPTZ,
|
||||
criado_por UUID REFERENCES master_admins(id),
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
atualizado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tenants_status ON tenants(status);
|
||||
|
||||
-- Faturas da mensalidade (você cobrando o tenant)
|
||||
CREATE TYPE cobranca_status AS ENUM ('pendente', 'pago', 'atrasado', 'cancelado');
|
||||
|
||||
CREATE TABLE tenant_faturas (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
referencia VARCHAR(7) NOT NULL, -- '2026-08'
|
||||
valor NUMERIC(10,2) NOT NULL,
|
||||
vencimento DATE NOT NULL,
|
||||
pago_em TIMESTAMPTZ,
|
||||
status cobranca_status NOT NULL DEFAULT 'pendente',
|
||||
alerta_enviado_em TIMESTAMPTZ,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE(tenant_id, referencia)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tenant_faturas_venc
|
||||
ON tenant_faturas(vencimento) WHERE status IN ('pendente', 'atrasado');
|
||||
|
||||
-- ============================================================
|
||||
-- 3. USUÁRIOS E AUTENTICAÇÃO
|
||||
-- ============================================================
|
||||
|
||||
CREATE TYPE user_role AS ENUM ('tenant_admin', 'vendedor', 'financeiro', 'visualizador');
|
||||
|
||||
CREATE TABLE tenant_users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
nome VARCHAR(150) NOT NULL,
|
||||
email VARCHAR(150) NOT NULL,
|
||||
senha_hash TEXT NOT NULL,
|
||||
role user_role NOT NULL DEFAULT 'vendedor',
|
||||
ativo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
mfa_secret TEXT,
|
||||
ultimo_login TIMESTAMPTZ,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE(tenant_id, email)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tenant_users_tenant ON tenant_users(tenant_id);
|
||||
|
||||
-- Refresh tokens (JWT access token curto + refresh token com rotação)
|
||||
CREATE TABLE auth_refresh_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
usuario_tipo VARCHAR(20) NOT NULL, -- 'master' | 'tenant_user'
|
||||
usuario_id UUID NOT NULL,
|
||||
token_hash TEXT NOT NULL, -- nunca guardar o token em texto puro
|
||||
expira_em TIMESTAMPTZ NOT NULL,
|
||||
revogado BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
ip_origem INET,
|
||||
user_agent TEXT,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_refresh_tokens_usuario ON auth_refresh_tokens(usuario_tipo, usuario_id);
|
||||
|
||||
CREATE TABLE password_reset_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
usuario_tipo VARCHAR(20) NOT NULL,
|
||||
usuario_id UUID NOT NULL,
|
||||
token_hash TEXT NOT NULL,
|
||||
expira_em TIMESTAMPTZ NOT NULL,
|
||||
usado BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Registro de tentativas de login (para rate-limit/bloqueio de força bruta)
|
||||
CREATE TABLE login_attempts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email VARCHAR(150) NOT NULL,
|
||||
usuario_tipo VARCHAR(20) NOT NULL,
|
||||
sucesso BOOLEAN NOT NULL,
|
||||
ip_origem INET,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_login_attempts_email_data ON login_attempts(email, criado_em);
|
||||
|
||||
-- ============================================================
|
||||
-- 4. INTEGRAÇÕES POR TENANT (WhatsApp / E-mail / Templates)
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE tenant_whatsapp_instances (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
evolution_config_id UUID REFERENCES evolution_api_config(id),
|
||||
instance_name VARCHAR(100) NOT NULL UNIQUE, -- nome único na Evolution API
|
||||
numero_conectado VARCHAR(20),
|
||||
status VARCHAR(30) NOT NULL DEFAULT 'desconectado',
|
||||
-- desconectado | conectando | conectado | erro
|
||||
qr_code_gerado_em TIMESTAMPTZ,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE tenant_email_config (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL UNIQUE REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
smtp_host VARCHAR(150),
|
||||
smtp_porta INTEGER,
|
||||
smtp_usuario VARCHAR(150),
|
||||
smtp_senha_cripto TEXT,
|
||||
email_remetente VARCHAR(150),
|
||||
usar_config_padrao BOOLEAN NOT NULL DEFAULT TRUE, -- usa master_email_config se true
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Templates de mensagens (nível master = padrão global; nível tenant = customizado)
|
||||
CREATE TABLE alert_templates (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE, -- NULL = template padrão da plataforma
|
||||
tipo VARCHAR(50) NOT NULL,
|
||||
-- 'mensalidade_tenant' | 'cobranca_cliente' | 'venda_confirmada' | 'lembrete_vencimento'
|
||||
canal VARCHAR(20) NOT NULL, -- 'whatsapp' | 'email'
|
||||
assunto VARCHAR(200), -- só para email
|
||||
corpo TEXT NOT NULL, -- placeholders: {{nome}}, {{valor}}, {{vencimento}}
|
||||
ativo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Log/auditoria de todo alerta disparado (master->tenant e tenant->customer)
|
||||
CREATE TABLE alert_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
destinatario_tipo VARCHAR(20) NOT NULL, -- 'tenant' | 'customer'
|
||||
destinatario_id UUID NOT NULL, -- id do tenant ou do customer
|
||||
canal VARCHAR(20) NOT NULL, -- whatsapp | email
|
||||
template_id UUID REFERENCES alert_templates(id),
|
||||
conteudo_enviado TEXT,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'enviado', -- enviado | falhou | entregue | lido
|
||||
erro TEXT,
|
||||
enviado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_alert_logs_tenant ON alert_logs(tenant_id, enviado_em);
|
||||
|
||||
-- ============================================================
|
||||
-- 5. CLIENTES DO TENANT ("customers" — empresas atendidas)
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE customers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
razao_social VARCHAR(200) NOT NULL,
|
||||
nome_fantasia VARCHAR(200),
|
||||
documento VARCHAR(20),
|
||||
email VARCHAR(150),
|
||||
telefone_whatsapp VARCHAR(20),
|
||||
endereco TEXT,
|
||||
cidade VARCHAR(100),
|
||||
uf CHAR(2),
|
||||
observacoes TEXT,
|
||||
ativo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
atualizado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_customers_tenant ON customers(tenant_id);
|
||||
|
||||
CREATE TABLE customer_contacts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
customer_id UUID NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
|
||||
nome VARCHAR(150) NOT NULL,
|
||||
cargo VARCHAR(100),
|
||||
email VARCHAR(150),
|
||||
telefone_whatsapp VARCHAR(20),
|
||||
principal BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- 6. PRODUTOS E SERVIÇOS DO TENANT
|
||||
-- ============================================================
|
||||
|
||||
CREATE TYPE item_tipo AS ENUM ('produto', 'servico');
|
||||
|
||||
CREATE TABLE products_services (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
tipo item_tipo NOT NULL,
|
||||
nome VARCHAR(200) NOT NULL,
|
||||
descricao TEXT,
|
||||
sku VARCHAR(50),
|
||||
valor_venda NUMERIC(12,2) NOT NULL,
|
||||
valor_custo NUMERIC(12,2),
|
||||
unidade VARCHAR(20) NOT NULL DEFAULT 'un', -- un, hora, mês...
|
||||
recorrente BOOLEAN NOT NULL DEFAULT FALSE, -- ex: serviço de mensalidade
|
||||
ativo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
atualizado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE(tenant_id, sku)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_products_tenant ON products_services(tenant_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 7. VENDAS
|
||||
-- ============================================================
|
||||
|
||||
CREATE TYPE venda_status AS ENUM ('orcamento', 'confirmada', 'cancelada', 'concluida');
|
||||
|
||||
CREATE TABLE sales (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
customer_id UUID NOT NULL REFERENCES customers(id),
|
||||
vendedor_id UUID REFERENCES tenant_users(id),
|
||||
numero_venda SERIAL,
|
||||
status venda_status NOT NULL DEFAULT 'confirmada',
|
||||
valor_total NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
desconto NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
observacoes TEXT,
|
||||
data_venda DATE NOT NULL DEFAULT CURRENT_DATE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
atualizado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sales_tenant_data ON sales(tenant_id, data_venda);
|
||||
CREATE INDEX idx_sales_customer ON sales(customer_id);
|
||||
|
||||
CREATE TABLE sale_items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
sale_id UUID NOT NULL REFERENCES sales(id) ON DELETE CASCADE,
|
||||
product_service_id UUID NOT NULL REFERENCES products_services(id),
|
||||
quantidade NUMERIC(10,2) NOT NULL DEFAULT 1,
|
||||
valor_unitario NUMERIC(12,2) NOT NULL,
|
||||
valor_total NUMERIC(12,2) NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sale_items_sale ON sale_items(sale_id);
|
||||
|
||||
-- Parcelas/recebimentos: contas a receber do tenant junto ao customer
|
||||
CREATE TYPE parcela_status AS ENUM ('pendente', 'pago', 'atrasado', 'cancelado');
|
||||
|
||||
CREATE TABLE sale_payments (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
sale_id UUID NOT NULL REFERENCES sales(id) ON DELETE CASCADE,
|
||||
numero_parcela SMALLINT NOT NULL DEFAULT 1,
|
||||
valor NUMERIC(12,2) NOT NULL,
|
||||
vencimento DATE NOT NULL,
|
||||
pago_em TIMESTAMPTZ,
|
||||
forma_pagamento VARCHAR(30), -- pix, boleto, cartao, dinheiro
|
||||
status parcela_status NOT NULL DEFAULT 'pendente',
|
||||
alerta_enviado_em TIMESTAMPTZ,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sale_payments_venc
|
||||
ON sale_payments(vencimento) WHERE status IN ('pendente', 'atrasado');
|
||||
|
||||
-- ============================================================
|
||||
-- 8. AUDITORIA GERAL
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE audit_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID REFERENCES tenants(id) ON DELETE SET NULL,
|
||||
usuario_tipo VARCHAR(20) NOT NULL, -- master | tenant_user
|
||||
usuario_id UUID,
|
||||
acao VARCHAR(100) NOT NULL, -- login, criar_venda, excluir_cliente...
|
||||
entidade VARCHAR(50),
|
||||
entidade_id UUID,
|
||||
detalhes JSONB,
|
||||
ip_origem INET,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_audit_tenant_data ON audit_logs(tenant_id, criado_em);
|
||||
|
||||
-- ============================================================
|
||||
-- 9. VIEWS DE DASHBOARD (usadas no painel do tenant)
|
||||
-- ============================================================
|
||||
|
||||
CREATE VIEW vw_resumo_vendas_semanal AS
|
||||
SELECT
|
||||
s.tenant_id,
|
||||
date_trunc('week', s.data_venda)::date AS semana,
|
||||
COUNT(*) AS qtd_vendas,
|
||||
SUM(s.valor_total) AS total_vendido
|
||||
FROM sales s
|
||||
WHERE s.status IN ('confirmada', 'concluida')
|
||||
GROUP BY s.tenant_id, date_trunc('week', s.data_venda);
|
||||
|
||||
CREATE VIEW vw_resumo_vendas_mensal AS
|
||||
SELECT
|
||||
s.tenant_id,
|
||||
date_trunc('month', s.data_venda)::date AS mes,
|
||||
COUNT(*) AS qtd_vendas,
|
||||
SUM(s.valor_total) AS total_vendido
|
||||
FROM sales s
|
||||
WHERE s.status IN ('confirmada', 'concluida')
|
||||
GROUP BY s.tenant_id, date_trunc('month', s.data_venda);
|
||||
|
||||
CREATE VIEW vw_recebimentos AS
|
||||
SELECT
|
||||
sp.id,
|
||||
s.tenant_id,
|
||||
s.customer_id,
|
||||
sp.valor,
|
||||
sp.vencimento,
|
||||
sp.status,
|
||||
sp.pago_em
|
||||
FROM sale_payments sp
|
||||
JOIN sales s ON s.id = sp.sale_id;
|
||||
|
||||
-- ============================================================
|
||||
-- 10. ROW LEVEL SECURITY — isolamento entre tenants
|
||||
-- ============================================================
|
||||
-- A aplicação deve definir, por conexão/transação:
|
||||
-- SET app.current_tenant_id = '<uuid-do-tenant-logado>';
|
||||
-- Usuários master (que enxergam todos os tenants) usam uma role
|
||||
-- de banco separada (ex: app_master) que faz BYPASS RLS, ou uma
|
||||
-- policy adicional que libera quando app.is_master = 'true'.
|
||||
|
||||
ALTER TABLE customers ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE customer_contacts ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE products_services ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE sales ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE sale_items ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE sale_payments ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE tenant_users ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE tenant_whatsapp_instances ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE tenant_email_config ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
CREATE POLICY tenant_isolation_customers ON customers
|
||||
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
||||
|
||||
CREATE POLICY tenant_isolation_products ON products_services
|
||||
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
||||
|
||||
CREATE POLICY tenant_isolation_sales ON sales
|
||||
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
||||
|
||||
CREATE POLICY tenant_isolation_tenant_users ON tenant_users
|
||||
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
||||
|
||||
CREATE POLICY tenant_isolation_whatsapp ON tenant_whatsapp_instances
|
||||
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
||||
|
||||
CREATE POLICY tenant_isolation_email_config ON tenant_email_config
|
||||
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
||||
|
||||
-- sale_items e customer_contacts não têm tenant_id direto: isolar via join
|
||||
CREATE POLICY tenant_isolation_sale_items ON sale_items
|
||||
USING (sale_id IN (
|
||||
SELECT id FROM sales
|
||||
WHERE tenant_id = current_setting('app.current_tenant_id', true)::uuid
|
||||
));
|
||||
|
||||
CREATE POLICY tenant_isolation_sale_payments ON sale_payments
|
||||
USING (sale_id IN (
|
||||
SELECT id FROM sales
|
||||
WHERE tenant_id = current_setting('app.current_tenant_id', true)::uuid
|
||||
));
|
||||
|
||||
CREATE POLICY tenant_isolation_customer_contacts ON customer_contacts
|
||||
USING (customer_id IN (
|
||||
SELECT id FROM customers
|
||||
WHERE tenant_id = current_setting('app.current_tenant_id', true)::uuid
|
||||
));
|
||||
|
||||
-- Fim do schema
|
||||
Reference in New Issue
Block a user