feat: schema multi-tenant (tenants, app_config, tenant_id backfill, RLS)

- Novas tabelas reserva_hotel.tenants e reserva_hotel.app_config
- Coluna tenant_id adicionada em todas as tabelas de catalogo/reservas
- Tenant default 'grupo-1001' criado + backfill das rows existentes
- RLS + grants pro anon ler tenants e app_config
- Types TS regenerados

Aplicado via MCP. Arquivos de migration sao source of truth historica.
This commit is contained in:
Rodribm10 2026-04-14 20:59:37 -03:00
parent 45ffd9110c
commit e912563196
4 changed files with 306 additions and 3 deletions

View File

@ -14,6 +14,77 @@ export type Database = {
}
reserva_hotel: {
Tables: {
app_config: {
Row: {
cor_fundo: string
cor_primaria: string
cor_secundaria: string
cor_superficie: string
cor_texto: string
created_at: string
favicon_url: string | null
fonte_corpo: string
fonte_display: string
footer_text: string | null
id: number
logo_url: string | null
nome_rede: string
subtitulo_hero: string | null
tagline: string | null
tenant_id: number
titulo_hero: string
updated_at: string
}
Insert: {
cor_fundo?: string
cor_primaria?: string
cor_secundaria?: string
cor_superficie?: string
cor_texto?: string
created_at?: string
favicon_url?: string | null
fonte_corpo?: string
fonte_display?: string
footer_text?: string | null
id?: number
logo_url?: string | null
nome_rede: string
subtitulo_hero?: string | null
tagline?: string | null
tenant_id: number
titulo_hero: string
updated_at?: string
}
Update: {
cor_fundo?: string
cor_primaria?: string
cor_secundaria?: string
cor_superficie?: string
cor_texto?: string
created_at?: string
favicon_url?: string | null
fonte_corpo?: string
fonte_display?: string
footer_text?: string | null
id?: number
logo_url?: string | null
nome_rede?: string
subtitulo_hero?: string | null
tagline?: string | null
tenant_id?: number
titulo_hero?: string
updated_at?: string
}
Relationships: [
{
foreignKeyName: "app_config_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: true
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
contas_pagamento: {
Row: {
ativa: boolean | null
@ -26,6 +97,7 @@ export type Database = {
nome_identificacao: string
path_crt: string | null
path_key: string | null
tenant_id: number
updated_at: string | null
}
Insert: {
@ -39,6 +111,7 @@ export type Database = {
nome_identificacao: string
path_crt?: string | null
path_key?: string | null
tenant_id: number
updated_at?: string | null
}
Update: {
@ -52,9 +125,18 @@ export type Database = {
nome_identificacao?: string
path_crt?: string | null
path_key?: string | null
tenant_id?: number
updated_at?: string | null
}
Relationships: []
Relationships: [
{
foreignKeyName: "contas_pagamento_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: false
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
extras: {
Row: {
@ -66,6 +148,7 @@ export type Database = {
imagem_url: string | null
ordem: number
preco: number
tenant_id: number
titulo: string
updated_at: string
}
@ -78,6 +161,7 @@ export type Database = {
imagem_url?: string | null
ordem?: number
preco: number
tenant_id: number
titulo: string
updated_at?: string
}
@ -90,6 +174,7 @@ export type Database = {
imagem_url?: string | null
ordem?: number
preco?: number
tenant_id?: number
titulo?: string
updated_at?: string
}
@ -101,6 +186,13 @@ export type Database = {
referencedRelation: "marcas"
referencedColumns: ["id"]
},
{
foreignKeyName: "extras_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: false
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
fotos_categoria: {
@ -112,6 +204,7 @@ export type Database = {
id: string
id_unidade: string
ordem: number
tenant_id: number
updated_at: string
url_foto: string
}
@ -123,6 +216,7 @@ export type Database = {
id?: string
id_unidade: string
ordem?: number
tenant_id: number
updated_at?: string
url_foto: string
}
@ -134,6 +228,7 @@ export type Database = {
id?: string
id_unidade?: string
ordem?: number
tenant_id?: number
updated_at?: string
url_foto?: string
}
@ -145,6 +240,13 @@ export type Database = {
referencedRelation: "unidades"
referencedColumns: ["id"]
},
{
foreignKeyName: "fotos_categoria_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: false
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
marcas: {
@ -156,6 +258,7 @@ export type Database = {
id: string
nome: string
permanencias: string[]
tenant_id: number
updated_at: string | null
}
Insert: {
@ -166,6 +269,7 @@ export type Database = {
id?: string
nome: string
permanencias?: string[]
tenant_id: number
updated_at?: string | null
}
Update: {
@ -176,9 +280,18 @@ export type Database = {
id?: string
nome?: string
permanencias?: string[]
tenant_id?: number
updated_at?: string | null
}
Relationships: []
Relationships: [
{
foreignKeyName: "marcas_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: false
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
precos: {
Row: {
@ -190,6 +303,7 @@ export type Database = {
id_marca: string
periodo_semana: string
permanencia: string
tenant_id: number
updated_at: string | null
valor: number
}
@ -202,6 +316,7 @@ export type Database = {
id_marca: string
periodo_semana?: string
permanencia: string
tenant_id: number
updated_at?: string | null
valor: number
}
@ -214,6 +329,7 @@ export type Database = {
id_marca?: string
periodo_semana?: string
permanencia?: string
tenant_id?: number
updated_at?: string | null
valor?: number
}
@ -225,6 +341,13 @@ export type Database = {
referencedRelation: "marcas"
referencedColumns: ["id"]
},
{
foreignKeyName: "precos_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: false
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
reserva_extras: {
@ -292,6 +415,7 @@ export type Database = {
qr_code_pix: string | null
status: string
telefone_cliente: string | null
tenant_id: number
tipo_permanencia: string
txid_pix: string | null
updated_at: string | null
@ -319,6 +443,7 @@ export type Database = {
qr_code_pix?: string | null
status?: string
telefone_cliente?: string | null
tenant_id: number
tipo_permanencia: string
txid_pix?: string | null
updated_at?: string | null
@ -346,6 +471,7 @@ export type Database = {
qr_code_pix?: string | null
status?: string
telefone_cliente?: string | null
tenant_id?: number
tipo_permanencia?: string
txid_pix?: string | null
updated_at?: string | null
@ -367,6 +493,13 @@ export type Database = {
referencedRelation: "unidades"
referencedColumns: ["id"]
},
{
foreignKeyName: "reservas_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: false
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
suites: {
@ -380,6 +513,7 @@ export type Database = {
id_api: string | null
nome: string
numero: string | null
tenant_id: number
updated_at: string | null
}
Insert: {
@ -392,6 +526,7 @@ export type Database = {
id_api?: string | null
nome: string
numero?: string | null
tenant_id: number
updated_at?: string | null
}
Update: {
@ -404,9 +539,18 @@ export type Database = {
id_api?: string | null
nome?: string
numero?: string | null
tenant_id?: number
updated_at?: string | null
}
Relationships: []
Relationships: [
{
foreignKeyName: "suites_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: false
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
suites_unidades: {
Row: {
@ -444,6 +588,33 @@ export type Database = {
},
]
}
tenants: {
Row: {
ativo: boolean
created_at: string
id: number
nome: string
slug: string
updated_at: string
}
Insert: {
ativo?: boolean
created_at?: string
id?: number
nome: string
slug: string
updated_at?: string
}
Update: {
ativo?: boolean
created_at?: string
id?: number
nome?: string
slug?: string
updated_at?: string
}
Relationships: []
}
unidades: {
Row: {
ativa: boolean | null
@ -457,6 +628,7 @@ export type Database = {
id_marca: string
nome: string
telefone: string | null
tenant_id: number
updated_at: string | null
}
Insert: {
@ -471,6 +643,7 @@ export type Database = {
id_marca: string
nome: string
telefone?: string | null
tenant_id: number
updated_at?: string | null
}
Update: {
@ -485,6 +658,7 @@ export type Database = {
id_marca?: string
nome?: string
telefone?: string | null
tenant_id?: number
updated_at?: string | null
}
Relationships: [
@ -502,6 +676,13 @@ export type Database = {
referencedRelation: "marcas"
referencedColumns: ["id"]
},
{
foreignKeyName: "unidades_tenant_id_fkey"
columns: ["tenant_id"]
isOneToOne: false
referencedRelation: "tenants"
referencedColumns: ["id"]
},
]
}
}
@ -720,3 +901,5 @@ export const Constants = {
Enums: {},
},
} as const
A new version of Supabase CLI is available: v2.90.0 (currently installed v2.48.3)
We recommend updating regularly for new features and bug fixes: https://supabase.com/docs/guides/cli/getting-started#updating-the-supabase-cli

View File

@ -0,0 +1,34 @@
-- Multi-tenancy foundation: tenants + app_config
-- Já aplicada via MCP.
create table if not exists reserva_hotel.tenants (
id bigserial primary key,
slug text not null unique,
nome text not null,
ativo boolean not null default true,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
create index if not exists idx_tenants_slug on reserva_hotel.tenants(slug);
create table if not exists reserva_hotel.app_config (
id bigserial primary key,
tenant_id bigint not null unique references reserva_hotel.tenants(id) on delete cascade,
nome_rede text not null, -- "Rede 1001"
titulo_hero text not null, -- "Reserva Rede 1001"
subtitulo_hero text, -- "Experiência exclusiva"
tagline text, -- "Escolha, confirme e receba seu PIX na hora."
footer_text text, -- "© 2026 Rede 1001 · Experiência Exclusiva"
logo_url text,
favicon_url text,
cor_primaria text not null default '#C9A961',
cor_secundaria text not null default '#E8B4A0',
cor_fundo text not null default '#0B0D12',
cor_superficie text not null default '#0F1A2E',
cor_texto text not null default '#F5F1E8',
fonte_display text not null default 'Fraunces',
fonte_corpo text not null default 'Inter',
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);

View File

@ -0,0 +1,70 @@
-- Adiciona tenant_id em todas as tabelas existentes + cria tenant default
-- + backfill de tudo pro tenant 1 ("Grupo Nova / Rede 1001")
-- Já aplicada via MCP.
-- 1. Tenant default
insert into reserva_hotel.tenants (slug, nome, ativo)
values ('grupo-1001', 'Grupo Nova — Rede 1001', true)
on conflict (slug) do nothing;
-- 2. app_config default
insert into reserva_hotel.app_config
(tenant_id, nome_rede, titulo_hero, subtitulo_hero, tagline, footer_text,
cor_primaria, cor_secundaria, cor_fundo, cor_superficie, cor_texto,
fonte_display, fonte_corpo)
select
t.id,
'Rede 1001',
'Reserva Rede 1001',
'Experiência exclusiva',
'Escolha, confirme e receba seu PIX na hora.',
'© 2026 Rede 1001 · Experiência Exclusiva',
'#C9A961', '#E8B4A0', '#0B0D12', '#0F1A2E', '#F5F1E8',
'Fraunces', 'Inter'
from reserva_hotel.tenants t
where t.slug = 'grupo-1001'
on conflict (tenant_id) do nothing;
-- 3. Adiciona tenant_id (nullable pra backfill)
alter table reserva_hotel.marcas add column if not exists tenant_id bigint references reserva_hotel.tenants(id);
alter table reserva_hotel.unidades add column if not exists tenant_id bigint references reserva_hotel.tenants(id);
alter table reserva_hotel.suites add column if not exists tenant_id bigint references reserva_hotel.tenants(id);
alter table reserva_hotel.precos add column if not exists tenant_id bigint references reserva_hotel.tenants(id);
alter table reserva_hotel.contas_pagamento add column if not exists tenant_id bigint references reserva_hotel.tenants(id);
alter table reserva_hotel.reservas add column if not exists tenant_id bigint references reserva_hotel.tenants(id);
alter table reserva_hotel.fotos_categoria add column if not exists tenant_id bigint references reserva_hotel.tenants(id);
alter table reserva_hotel.extras add column if not exists tenant_id bigint references reserva_hotel.tenants(id);
-- 4. Backfill
do $$
declare v_tenant_id bigint;
begin
select id into v_tenant_id from reserva_hotel.tenants where slug = 'grupo-1001';
update reserva_hotel.marcas set tenant_id = v_tenant_id where tenant_id is null;
update reserva_hotel.unidades set tenant_id = v_tenant_id where tenant_id is null;
update reserva_hotel.suites set tenant_id = v_tenant_id where tenant_id is null;
update reserva_hotel.precos set tenant_id = v_tenant_id where tenant_id is null;
update reserva_hotel.contas_pagamento set tenant_id = v_tenant_id where tenant_id is null;
update reserva_hotel.reservas set tenant_id = v_tenant_id where tenant_id is null;
update reserva_hotel.fotos_categoria set tenant_id = v_tenant_id where tenant_id is null;
update reserva_hotel.extras set tenant_id = v_tenant_id where tenant_id is null;
end $$;
-- 5. NOT NULL
alter table reserva_hotel.marcas alter column tenant_id set not null;
alter table reserva_hotel.unidades alter column tenant_id set not null;
alter table reserva_hotel.suites alter column tenant_id set not null;
alter table reserva_hotel.precos alter column tenant_id set not null;
alter table reserva_hotel.contas_pagamento alter column tenant_id set not null;
alter table reserva_hotel.reservas alter column tenant_id set not null;
alter table reserva_hotel.fotos_categoria alter column tenant_id set not null;
alter table reserva_hotel.extras alter column tenant_id set not null;
-- 6. Indexes
create index if not exists idx_marcas_tenant on reserva_hotel.marcas(tenant_id);
create index if not exists idx_unidades_tenant on reserva_hotel.unidades(tenant_id);
create index if not exists idx_precos_tenant on reserva_hotel.precos(tenant_id);
create index if not exists idx_reservas_tenant on reserva_hotel.reservas(tenant_id);
create index if not exists idx_fotos_categoria_tenant on reserva_hotel.fotos_categoria(tenant_id);
create index if not exists idx_extras_tenant on reserva_hotel.extras(tenant_id);

View File

@ -0,0 +1,16 @@
-- RLS + grants pras tabelas publicas de tenant
-- Já aplicada via MCP.
alter table reserva_hotel.tenants enable row level security;
alter table reserva_hotel.app_config enable row level security;
drop policy if exists "public_read_tenants" on reserva_hotel.tenants;
create policy "public_read_tenants" on reserva_hotel.tenants
for select using (ativo = true);
drop policy if exists "public_read_app_config" on reserva_hotel.app_config;
create policy "public_read_app_config" on reserva_hotel.app_config
for select using (true);
grant select on reserva_hotel.tenants to anon, authenticated;
grant select on reserva_hotel.app_config to anon, authenticated;