Agenda, Agendador, Configurações
This commit is contained in:
2
DBS/2026-03-11/supabase-snippets/Untitled query 116.sql
Normal file
2
DBS/2026-03-11/supabase-snippets/Untitled query 116.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE public.agenda_configuracoes DROP COLUMN IF EXISTS
|
||||
session_start_offset_min;
|
||||
1
DBS/2026-03-11/supabase-snippets/Untitled query 130.sql
Normal file
1
DBS/2026-03-11/supabase-snippets/Untitled query 130.sql
Normal file
@@ -0,0 +1 @@
|
||||
select pg_get_functiondef('public.NOME_DA_FUNCAO(args_aqui)'::regprocedure);
|
||||
45
DBS/2026-03-11/supabase-snippets/Untitled query 132.sql
Normal file
45
DBS/2026-03-11/supabase-snippets/Untitled query 132.sql
Normal file
@@ -0,0 +1,45 @@
|
||||
-- 1) Tabela profiles
|
||||
create table if not exists public.profiles (
|
||||
id uuid primary key references auth.users(id) on delete cascade,
|
||||
role text not null default 'patient' check (role in ('admin','therapist','patient')),
|
||||
full_name text,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
-- 2) updated_at automático
|
||||
create or replace function public.set_updated_at()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
new.updated_at = now();
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists trg_profiles_updated_at on public.profiles;
|
||||
create trigger trg_profiles_updated_at
|
||||
before update on public.profiles
|
||||
for each row execute function public.set_updated_at();
|
||||
|
||||
-- 3) Trigger: cria profile automaticamente quando usuário nasce no auth
|
||||
create or replace function public.handle_new_user()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
begin
|
||||
insert into public.profiles (id, role)
|
||||
values (new.id, 'patient')
|
||||
on conflict (id) do nothing;
|
||||
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists on_auth_user_created on auth.users;
|
||||
create trigger on_auth_user_created
|
||||
after insert on auth.users
|
||||
for each row execute function public.handle_new_user();
|
||||
20
DBS/2026-03-11/supabase-snippets/Untitled query 157.sql
Normal file
20
DBS/2026-03-11/supabase-snippets/Untitled query 157.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
do $$
|
||||
begin
|
||||
if exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'patient_patient_tag'
|
||||
and column_name = 'patient_tag_id'
|
||||
)
|
||||
and not exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'patient_patient_tag'
|
||||
and column_name = 'tag_id'
|
||||
) then
|
||||
alter table public.patient_patient_tag
|
||||
rename column patient_tag_id to tag_id;
|
||||
end if;
|
||||
end $$;
|
||||
5
DBS/2026-03-11/supabase-snippets/Untitled query 159.sql
Normal file
5
DBS/2026-03-11/supabase-snippets/Untitled query 159.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
insert into public.profiles (id, role)
|
||||
select u.id, 'patient'
|
||||
from auth.users u
|
||||
left join public.profiles p on p.id = u.id
|
||||
where p.id is null;
|
||||
12
DBS/2026-03-11/supabase-snippets/Untitled query 174.sql
Normal file
12
DBS/2026-03-11/supabase-snippets/Untitled query 174.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
select
|
||||
id, name, email, phone,
|
||||
birth_date, cpf, rg, gender,
|
||||
marital_status, profession,
|
||||
place_of_birth, education_level,
|
||||
cep, address_street, address_number,
|
||||
address_neighborhood, address_city, address_state,
|
||||
phone_alt,
|
||||
notes, consent, created_at
|
||||
from public.patient_intake_requests
|
||||
order by created_at desc
|
||||
limit 1;
|
||||
23
DBS/2026-03-11/supabase-snippets/Untitled query 209.sql
Normal file
23
DBS/2026-03-11/supabase-snippets/Untitled query 209.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
create or replace function public.agenda_cfg_sync()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
if new.agenda_view_mode = 'custom' then
|
||||
new.usar_horario_admin_custom := true;
|
||||
new.admin_inicio_visualizacao := new.agenda_custom_start;
|
||||
new.admin_fim_visualizacao := new.agenda_custom_end;
|
||||
else
|
||||
new.usar_horario_admin_custom := false;
|
||||
end if;
|
||||
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists trg_agenda_cfg_sync on public.agenda_configuracoes;
|
||||
|
||||
create trigger trg_agenda_cfg_sync
|
||||
before insert or update on public.agenda_configuracoes
|
||||
for each row
|
||||
execute function public.agenda_cfg_sync();
|
||||
2
DBS/2026-03-11/supabase-snippets/Untitled query 216.sql
Normal file
2
DBS/2026-03-11/supabase-snippets/Untitled query 216.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
drop index if exists public.uq_subscriptions_tenant;
|
||||
drop index if exists public.uq_subscriptions_personal_user;
|
||||
6
DBS/2026-03-11/supabase-snippets/Untitled query 219.sql
Normal file
6
DBS/2026-03-11/supabase-snippets/Untitled query 219.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
-- Limpa TUDO da agenda (eventos, regras, exceções)
|
||||
-- Execute no Supabase Studio — não tem volta!
|
||||
|
||||
DELETE FROM recurrence_exceptions;
|
||||
DELETE FROM recurrence_rules;
|
||||
DELETE FROM agenda_eventos;
|
||||
12
DBS/2026-03-11/supabase-snippets/Untitled query 221.sql
Normal file
12
DBS/2026-03-11/supabase-snippets/Untitled query 221.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
select
|
||||
t.tgname as trigger_name,
|
||||
pg_get_triggerdef(t.oid) as trigger_def,
|
||||
p.proname as function_name,
|
||||
n.nspname as function_schema
|
||||
from pg_trigger t
|
||||
join pg_proc p on p.oid = t.tgfoid
|
||||
join pg_namespace n on n.oid = p.pronamespace
|
||||
join pg_class c on c.oid = t.tgrelid
|
||||
where not t.tgisinternal
|
||||
and c.relname = 'patient_intake_requests'
|
||||
order by t.tgname;
|
||||
46
DBS/2026-03-11/supabase-snippets/Untitled query 235.sql
Normal file
46
DBS/2026-03-11/supabase-snippets/Untitled query 235.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- ============================================================
|
||||
-- LIMPEZA DE DADOS DE TESTE — filtra por tenant/owner
|
||||
-- Execute no Supabase Studio com cuidado -- ============================================================
|
||||
DO $$ DECLARE
|
||||
v_tenant_id uuid := 'bbbbbbbb-0002-0002-0002-000000000002';
|
||||
v_owner_id uuid := 'aaaaaaaa-0002-0002-0002-000000000002';
|
||||
n_exc int;
|
||||
n_ev int;
|
||||
n_rule int;
|
||||
n_sol int;
|
||||
BEGIN
|
||||
|
||||
-- 1. Exceções (filha de recurrence_rules — apagar primeiro)
|
||||
DELETE FROM public.recurrence_exceptions
|
||||
WHERE recurrence_id IN (
|
||||
SELECT id FROM public.recurrence_rules
|
||||
WHERE (v_tenant_id IS NULL OR tenant_id = v_tenant_id)
|
||||
AND (v_owner_id IS NULL OR owner_id = v_owner_id)
|
||||
);
|
||||
GET DIAGNOSTICS n_exc = ROW_COUNT;
|
||||
|
||||
-- 2. Regras de recorrência
|
||||
DELETE FROM public.recurrence_rules
|
||||
WHERE (v_tenant_id IS NULL OR tenant_id = v_tenant_id)
|
||||
AND (v_owner_id IS NULL OR owner_id = v_owner_id);
|
||||
GET DIAGNOSTICS n_rule = ROW_COUNT;
|
||||
|
||||
-- 3. Eventos da agenda
|
||||
DELETE FROM public.agenda_eventos
|
||||
WHERE (v_tenant_id IS NULL OR tenant_id = v_tenant_id)
|
||||
AND (v_owner_id IS NULL OR owner_id = v_owner_id);
|
||||
GET DIAGNOSTICS n_ev = ROW_COUNT;
|
||||
|
||||
-- 4. Solicitações públicas (agendador online)
|
||||
DELETE FROM public.agendador_solicitacoes
|
||||
WHERE (v_tenant_id IS NULL OR tenant_id = v_tenant_id)
|
||||
AND (v_owner_id IS NULL OR owner_id = v_owner_id);
|
||||
GET DIAGNOSTICS n_sol = ROW_COUNT;
|
||||
|
||||
RAISE NOTICE '✅ Limpeza concluída:';
|
||||
RAISE NOTICE ' recurrence_exceptions : %', n_exc;
|
||||
RAISE NOTICE ' recurrence_rules : %', n_rule;
|
||||
RAISE NOTICE ' agenda_eventos : %', n_ev;
|
||||
RAISE NOTICE ' agendador_solicitacoes : %', n_sol;
|
||||
END;
|
||||
$$;
|
||||
10
DBS/2026-03-11/supabase-snippets/Untitled query 271.sql
Normal file
10
DBS/2026-03-11/supabase-snippets/Untitled query 271.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
select
|
||||
id as tenant_member_id,
|
||||
tenant_id,
|
||||
user_id,
|
||||
role,
|
||||
status,
|
||||
created_at
|
||||
from public.tenant_members
|
||||
where user_id = '824f125c-55bb-40f5-a8c4-7a33618b91c7'
|
||||
order by created_at desc;
|
||||
4
DBS/2026-03-11/supabase-snippets/Untitled query 277.sql
Normal file
4
DBS/2026-03-11/supabase-snippets/Untitled query 277.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
select *
|
||||
from agenda_eventos
|
||||
order by created_at desc nulls last
|
||||
limit 10;
|
||||
6
DBS/2026-03-11/supabase-snippets/Untitled query 319.sql
Normal file
6
DBS/2026-03-11/supabase-snippets/Untitled query 319.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
select
|
||||
routine_name,
|
||||
routine_type
|
||||
from information_schema.routines
|
||||
where routine_schema = 'public'
|
||||
and routine_name ilike '%intake%';
|
||||
4
DBS/2026-03-11/supabase-snippets/Untitled query 323.sql
Normal file
4
DBS/2026-03-11/supabase-snippets/Untitled query 323.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
select id as owner_id, email, created_at
|
||||
from auth.users
|
||||
where email = 'admin@agendapsi.com.br'
|
||||
limit 1;
|
||||
8
DBS/2026-03-11/supabase-snippets/Untitled query 324.sql
Normal file
8
DBS/2026-03-11/supabase-snippets/Untitled query 324.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
select
|
||||
id,
|
||||
owner_id,
|
||||
status,
|
||||
created_at,
|
||||
converted_patient_id
|
||||
from public.patient_intake_requests
|
||||
where id = '54daa09a-b2cb-4a0b-91aa-e4cea1915efe';
|
||||
6
DBS/2026-03-11/supabase-snippets/Untitled query 330.sql
Normal file
6
DBS/2026-03-11/supabase-snippets/Untitled query 330.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
select f.key as feature_key
|
||||
from public.plan_features pf
|
||||
join public.features f on f.id = pf.feature_id
|
||||
where pf.plan_id = 'fdc2813d-dfaa-4e2c-b71d-ef7b84dfd9e9'
|
||||
and pf.enabled = true
|
||||
order by f.key;
|
||||
3
DBS/2026-03-11/supabase-snippets/Untitled query 361.sql
Normal file
3
DBS/2026-03-11/supabase-snippets/Untitled query 361.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
select id, key, name
|
||||
from public.plans
|
||||
order by key;
|
||||
1
DBS/2026-03-11/supabase-snippets/Untitled query 376.sql
Normal file
1
DBS/2026-03-11/supabase-snippets/Untitled query 376.sql
Normal file
@@ -0,0 +1 @@
|
||||
SELECT * FROM public.agendador_solicitacoes LIMIT 5;
|
||||
5
DBS/2026-03-11/supabase-snippets/Untitled query 431.sql
Normal file
5
DBS/2026-03-11/supabase-snippets/Untitled query 431.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
select table_schema, table_name, column_name
|
||||
from information_schema.columns
|
||||
where column_name in ('owner_id', 'tenant_id')
|
||||
and table_schema = 'public'
|
||||
order by table_name;
|
||||
12
DBS/2026-03-11/supabase-snippets/Untitled query 437.sql
Normal file
12
DBS/2026-03-11/supabase-snippets/Untitled query 437.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
alter table public.patient_groups enable row level security;
|
||||
|
||||
drop policy if exists patient_groups_select on public.patient_groups;
|
||||
|
||||
create policy patient_groups_select
|
||||
on public.patient_groups
|
||||
for select
|
||||
to authenticated
|
||||
using (
|
||||
owner_id = auth.uid()
|
||||
or owner_id is null
|
||||
);
|
||||
9
DBS/2026-03-11/supabase-snippets/Untitled query 439.sql
Normal file
9
DBS/2026-03-11/supabase-snippets/Untitled query 439.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
select *
|
||||
from public.owner_feature_entitlements
|
||||
where owner_id = '816b24fe-a0c3-4409-b79b-c6c0a6935d03'::uuid
|
||||
order by feature_key;
|
||||
|
||||
select public.has_feature('816b24fe-a0c3-4409-b79b-c6c0a6935d03'::uuid, 'online_scheduling.manage') as can_manage;
|
||||
|
||||
5
DBS/2026-03-11/supabase-snippets/Untitled query 449.sql
Normal file
5
DBS/2026-03-11/supabase-snippets/Untitled query 449.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
create index if not exists idx_patient_group_patient_group_id
|
||||
on public.patient_group_patient (patient_group_id);
|
||||
|
||||
create index if not exists idx_patient_groups_owner_system_nome
|
||||
on public.patient_groups (owner_id, is_system, nome);
|
||||
9
DBS/2026-03-11/supabase-snippets/Untitled query 457.sql
Normal file
9
DBS/2026-03-11/supabase-snippets/Untitled query 457.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
-- 1) Marcar como SaaS master
|
||||
insert into public.saas_admins (user_id)
|
||||
values ('40a4b683-a0c9-4890-a201-20faf41fca06')
|
||||
on conflict (user_id) do nothing;
|
||||
|
||||
-- 2) Garantir profile (seu session.js busca role em profiles)
|
||||
insert into public.profiles (id, role)
|
||||
values ('40a4b683-a0c9-4890-a201-20faf41fca06', 'saas_admin')
|
||||
on conflict (id) do update set role = excluded.role;
|
||||
5
DBS/2026-03-11/supabase-snippets/Untitled query 468.sql
Normal file
5
DBS/2026-03-11/supabase-snippets/Untitled query 468.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
select *
|
||||
from public.owner_feature_entitlements
|
||||
where owner_id = '816b24fe-a0c3-4409-b79b-c6c0a6935d03'::uuid
|
||||
order by feature_key;
|
||||
|
||||
5
DBS/2026-03-11/supabase-snippets/Untitled query 476.sql
Normal file
5
DBS/2026-03-11/supabase-snippets/Untitled query 476.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
select column_name, data_type
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'patient_patient_tag'
|
||||
order by ordinal_position;
|
||||
18
DBS/2026-03-11/supabase-snippets/Untitled query 508.sql
Normal file
18
DBS/2026-03-11/supabase-snippets/Untitled query 508.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
create or replace function public.prevent_promoting_to_system()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
if new.is_system = true and old.is_system is distinct from true then
|
||||
raise exception 'Não é permitido transformar um grupo comum em grupo do sistema.';
|
||||
end if;
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists trg_prevent_promoting_to_system on public.patient_groups;
|
||||
|
||||
create trigger trg_prevent_promoting_to_system
|
||||
before update on public.patient_groups
|
||||
for each row
|
||||
execute function public.prevent_promoting_to_system();
|
||||
4
DBS/2026-03-11/supabase-snippets/Untitled query 521.sql
Normal file
4
DBS/2026-03-11/supabase-snippets/Untitled query 521.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
select id, tenant_id, user_id, role, status, created_at
|
||||
from tenant_members
|
||||
where user_id = '1715ec83-9a30-4dce-b73a-2deb66dcfb13'
|
||||
order by created_at desc;
|
||||
2
DBS/2026-03-11/supabase-snippets/Untitled query 566.sql
Normal file
2
DBS/2026-03-11/supabase-snippets/Untitled query 566.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
const { data, error } = await supabase.rpc('my_tenants')
|
||||
console.log({ data, error })
|
||||
6
DBS/2026-03-11/supabase-snippets/Untitled query 633.sql
Normal file
6
DBS/2026-03-11/supabase-snippets/Untitled query 633.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
select id, tenant_id, user_id, role, status, created_at
|
||||
from tenant_members
|
||||
where tenant_id = '816b24fe-a0c3-4409-b79b-c6c0a6935d03'::uuid
|
||||
order by
|
||||
(case when role = 'clinic_admin' then 0 else 1 end),
|
||||
created_at;
|
||||
15
DBS/2026-03-11/supabase-snippets/Untitled query 641.sql
Normal file
15
DBS/2026-03-11/supabase-snippets/Untitled query 641.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- Para o tenant A:
|
||||
select id as responsible_member_id
|
||||
from public.tenant_members
|
||||
where tenant_id = '816b24fe-a0c3-4409-b79b-c6c0a6935d03'
|
||||
and user_id = '824f125c-55bb-40f5-a8c4-7a33618b91c7'
|
||||
and status = 'active'
|
||||
limit 1;
|
||||
|
||||
-- Para o tenant B:
|
||||
select id as responsible_member_id
|
||||
from public.tenant_members
|
||||
where tenant_id = 'e8b10543-fb36-4e75-9d37-6fece9745637'
|
||||
and user_id = '824f125c-55bb-40f5-a8c4-7a33618b91c7'
|
||||
and status = 'active'
|
||||
limit 1;
|
||||
4
DBS/2026-03-11/supabase-snippets/Untitled query 649.sql
Normal file
4
DBS/2026-03-11/supabase-snippets/Untitled query 649.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
select id, name, kind, created_at
|
||||
from public.tenants
|
||||
order by created_at desc
|
||||
limit 10;
|
||||
5
DBS/2026-03-11/supabase-snippets/Untitled query 677.sql
Normal file
5
DBS/2026-03-11/supabase-snippets/Untitled query 677.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
select id as member_id
|
||||
from tenant_members
|
||||
where tenant_id = '816b24fe-a0c3-4409-b79b-c6c0a6935d03'
|
||||
and user_id = '824f125c-55bb-40f5-a8c4-7a33618b91c7'
|
||||
limit 1;
|
||||
2
DBS/2026-03-11/supabase-snippets/Untitled query 744.sql
Normal file
2
DBS/2026-03-11/supabase-snippets/Untitled query 744.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
insert into public.users (id, created_at)
|
||||
values ('e8b10543-fb36-4e75-9d37-6fece9745637', now());
|
||||
4
DBS/2026-03-11/supabase-snippets/Untitled query 781.sql
Normal file
4
DBS/2026-03-11/supabase-snippets/Untitled query 781.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
select *
|
||||
from public.tenant_members
|
||||
where tenant_id = 'UUID_AQUI'
|
||||
order by created_at desc;
|
||||
17
DBS/2026-03-11/supabase-snippets/Untitled query 790.sql
Normal file
17
DBS/2026-03-11/supabase-snippets/Untitled query 790.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
create table if not exists public.subscriptions (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
user_id uuid not null references auth.users(id) on delete cascade,
|
||||
plan_key text not null,
|
||||
interval text not null check (interval in ('month','year')),
|
||||
status text not null check (status in ('active','canceled','past_due','trial')) default 'active',
|
||||
started_at timestamptz not null default now(),
|
||||
current_period_start timestamptz not null default now(),
|
||||
current_period_end timestamptz null,
|
||||
canceled_at timestamptz null,
|
||||
source text not null default 'manual',
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create index if not exists subscriptions_user_id_idx on public.subscriptions(user_id);
|
||||
create index if not exists subscriptions_status_idx on public.subscriptions(status);
|
||||
13
DBS/2026-03-11/supabase-snippets/Untitled query 830.sql
Normal file
13
DBS/2026-03-11/supabase-snippets/Untitled query 830.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
-- Ver todas as regras no banco
|
||||
SELECT
|
||||
id,
|
||||
owner_id,
|
||||
status,
|
||||
type,
|
||||
weekdays,
|
||||
start_date,
|
||||
end_date,
|
||||
start_time,
|
||||
created_at
|
||||
FROM recurrence_rules
|
||||
ORDER BY created_at DESC;
|
||||
3
DBS/2026-03-11/supabase-snippets/Untitled query 843.sql
Normal file
3
DBS/2026-03-11/supabase-snippets/Untitled query 843.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
select id, name, created_at
|
||||
from public.tenants
|
||||
order by created_at desc;
|
||||
8
DBS/2026-03-11/supabase-snippets/Untitled query 856.sql
Normal file
8
DBS/2026-03-11/supabase-snippets/Untitled query 856.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
alter table public.profiles enable row level security;
|
||||
|
||||
drop policy if exists "profiles_select_own" on public.profiles;
|
||||
create policy "profiles_select_own"
|
||||
on public.profiles
|
||||
for select
|
||||
to authenticated
|
||||
using (id = auth.uid());
|
||||
7
DBS/2026-03-11/supabase-snippets/Untitled query 869.sql
Normal file
7
DBS/2026-03-11/supabase-snippets/Untitled query 869.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- 2) Tenho membership ativa no tenant atual?
|
||||
select *
|
||||
from tenant_members
|
||||
where tenant_id = 'e8b10543-fb36-4e75-9d37-6fece9745637'
|
||||
and user_id = auth.uid()
|
||||
order by created_at desc;
|
||||
|
||||
8
DBS/2026-03-11/supabase-snippets/Untitled query 880.sql
Normal file
8
DBS/2026-03-11/supabase-snippets/Untitled query 880.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
select
|
||||
n.nspname as schema,
|
||||
p.proname as function_name,
|
||||
pg_get_functiondef(p.oid) as definition
|
||||
from pg_proc p
|
||||
join pg_namespace n on n.oid = p.pronamespace
|
||||
where n.nspname = 'public'
|
||||
and pg_get_functiondef(p.oid) ilike '%entitlements_invalidation%';
|
||||
266
DBS/2026-03-11/supabase-snippets/Untitled query 886.sql
Normal file
266
DBS/2026-03-11/supabase-snippets/Untitled query 886.sql
Normal file
@@ -0,0 +1,266 @@
|
||||
-- =========================================================
|
||||
-- PATCH — Completar cadastro para bater com PatientsCadastroPage.vue
|
||||
-- (rode DEPOIS do seu supabase_cadastro_pacientes.sql)
|
||||
-- =========================================================
|
||||
|
||||
create extension if not exists pgcrypto;
|
||||
|
||||
-- ---------------------------------------------------------
|
||||
-- 1) Completar colunas que o front usa e hoje faltam em patients
|
||||
-- ---------------------------------------------------------
|
||||
do $$
|
||||
begin
|
||||
if not exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema='public' and table_name='patients' and column_name='email_alt'
|
||||
) then
|
||||
alter table public.patients add column email_alt text;
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema='public' and table_name='patients' and column_name='phones'
|
||||
) then
|
||||
-- array de textos (Postgres). No JS você manda ["...","..."] normalmente.
|
||||
alter table public.patients add column phones text[];
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema='public' and table_name='patients' and column_name='gender'
|
||||
) then
|
||||
alter table public.patients add column gender text;
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema='public' and table_name='patients' and column_name='marital_status'
|
||||
) then
|
||||
alter table public.patients add column marital_status text;
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
-- (opcional) índices úteis pra busca/filtro por nome/email
|
||||
create index if not exists idx_patients_owner_name on public.patients(owner_id, name);
|
||||
create index if not exists idx_patients_owner_email on public.patients(owner_id, email);
|
||||
|
||||
-- ---------------------------------------------------------
|
||||
-- 2) patient_groups
|
||||
-- ---------------------------------------------------------
|
||||
create table if not exists public.patient_groups (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
owner_id uuid not null references auth.users(id) on delete cascade,
|
||||
name text not null,
|
||||
color text,
|
||||
is_system boolean not null default false,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
-- nome único por owner
|
||||
do $$
|
||||
begin
|
||||
if not exists (
|
||||
select 1 from pg_constraint
|
||||
where conname = 'patient_groups_owner_name_uniq'
|
||||
and conrelid = 'public.patient_groups'::regclass
|
||||
) then
|
||||
alter table public.patient_groups
|
||||
add constraint patient_groups_owner_name_uniq unique(owner_id, name);
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
drop trigger if exists trg_patient_groups_set_updated_at on public.patient_groups;
|
||||
create trigger trg_patient_groups_set_updated_at
|
||||
before update on public.patient_groups
|
||||
for each row execute function public.set_updated_at();
|
||||
|
||||
create index if not exists idx_patient_groups_owner on public.patient_groups(owner_id);
|
||||
|
||||
alter table public.patient_groups enable row level security;
|
||||
|
||||
drop policy if exists "patient_groups_select_own" on public.patient_groups;
|
||||
create policy "patient_groups_select_own"
|
||||
on public.patient_groups for select
|
||||
to authenticated
|
||||
using (owner_id = auth.uid());
|
||||
|
||||
drop policy if exists "patient_groups_insert_own" on public.patient_groups;
|
||||
create policy "patient_groups_insert_own"
|
||||
on public.patient_groups for insert
|
||||
to authenticated
|
||||
with check (owner_id = auth.uid());
|
||||
|
||||
drop policy if exists "patient_groups_update_own" on public.patient_groups;
|
||||
create policy "patient_groups_update_own"
|
||||
on public.patient_groups for update
|
||||
to authenticated
|
||||
using (owner_id = auth.uid())
|
||||
with check (owner_id = auth.uid());
|
||||
|
||||
drop policy if exists "patient_groups_delete_own" on public.patient_groups;
|
||||
create policy "patient_groups_delete_own"
|
||||
on public.patient_groups for delete
|
||||
to authenticated
|
||||
using (owner_id = auth.uid());
|
||||
|
||||
grant select, insert, update, delete on public.patient_groups to authenticated;
|
||||
|
||||
-- ---------------------------------------------------------
|
||||
-- 3) patient_tags
|
||||
-- ---------------------------------------------------------
|
||||
create table if not exists public.patient_tags (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
owner_id uuid not null references auth.users(id) on delete cascade,
|
||||
name text not null,
|
||||
color text,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
do $$
|
||||
begin
|
||||
if not exists (
|
||||
select 1 from pg_constraint
|
||||
where conname = 'patient_tags_owner_name_uniq'
|
||||
and conrelid = 'public.patient_tags'::regclass
|
||||
) then
|
||||
alter table public.patient_tags
|
||||
add constraint patient_tags_owner_name_uniq unique(owner_id, name);
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
drop trigger if exists trg_patient_tags_set_updated_at on public.patient_tags;
|
||||
create trigger trg_patient_tags_set_updated_at
|
||||
before update on public.patient_tags
|
||||
for each row execute function public.set_updated_at();
|
||||
|
||||
create index if not exists idx_patient_tags_owner on public.patient_tags(owner_id);
|
||||
|
||||
alter table public.patient_tags enable row level security;
|
||||
|
||||
drop policy if exists "patient_tags_select_own" on public.patient_tags;
|
||||
create policy "patient_tags_select_own"
|
||||
on public.patient_tags for select
|
||||
to authenticated
|
||||
using (owner_id = auth.uid());
|
||||
|
||||
drop policy if exists "patient_tags_insert_own" on public.patient_tags;
|
||||
create policy "patient_tags_insert_own"
|
||||
on public.patient_tags for insert
|
||||
to authenticated
|
||||
with check (owner_id = auth.uid());
|
||||
|
||||
drop policy if exists "patient_tags_update_own" on public.patient_tags;
|
||||
create policy "patient_tags_update_own"
|
||||
on public.patient_tags for update
|
||||
to authenticated
|
||||
using (owner_id = auth.uid())
|
||||
with check (owner_id = auth.uid());
|
||||
|
||||
drop policy if exists "patient_tags_delete_own" on public.patient_tags;
|
||||
create policy "patient_tags_delete_own"
|
||||
on public.patient_tags for delete
|
||||
to authenticated
|
||||
using (owner_id = auth.uid());
|
||||
|
||||
grant select, insert, update, delete on public.patient_tags to authenticated;
|
||||
|
||||
-- ---------------------------------------------------------
|
||||
-- 4) pivôs (patient_group_patient / patient_patient_tag)
|
||||
-- ---------------------------------------------------------
|
||||
create table if not exists public.patient_group_patient (
|
||||
patient_id uuid not null references public.patients(id) on delete cascade,
|
||||
patient_group_id uuid not null references public.patient_groups(id) on delete cascade,
|
||||
created_at timestamptz not null default now(),
|
||||
primary key (patient_id, patient_group_id)
|
||||
);
|
||||
|
||||
create index if not exists idx_pgp_patient on public.patient_group_patient(patient_id);
|
||||
create index if not exists idx_pgp_group on public.patient_group_patient(patient_group_id);
|
||||
|
||||
alter table public.patient_group_patient enable row level security;
|
||||
|
||||
-- a pivot “herda” tenant via join; policy usando exists pra validar owner do patient
|
||||
drop policy if exists "pgp_select_own" on public.patient_group_patient;
|
||||
create policy "pgp_select_own"
|
||||
on public.patient_group_patient for select
|
||||
to authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1 from public.patients p
|
||||
where p.id = patient_group_patient.patient_id
|
||||
and p.owner_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
drop policy if exists "pgp_write_own" on public.patient_group_patient;
|
||||
create policy "pgp_write_own"
|
||||
on public.patient_group_patient for all
|
||||
to authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1 from public.patients p
|
||||
where p.id = patient_group_patient.patient_id
|
||||
and p.owner_id = auth.uid()
|
||||
)
|
||||
)
|
||||
with check (
|
||||
exists (
|
||||
select 1 from public.patients p
|
||||
where p.id = patient_group_patient.patient_id
|
||||
and p.owner_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
grant select, insert, update, delete on public.patient_group_patient to authenticated;
|
||||
|
||||
-- tags pivot (ATENÇÃO: coluna é tag_id, como teu Vue usa!)
|
||||
create table if not exists public.patient_patient_tag (
|
||||
patient_id uuid not null references public.patients(id) on delete cascade,
|
||||
tag_id uuid not null references public.patient_tags(id) on delete cascade,
|
||||
created_at timestamptz not null default now(),
|
||||
primary key (patient_id, tag_id)
|
||||
);
|
||||
|
||||
create index if not exists idx_ppt_patient on public.patient_patient_tag(patient_id);
|
||||
create index if not exists idx_ppt_tag on public.patient_patient_tag(tag_id);
|
||||
|
||||
alter table public.patient_patient_tag enable row level security;
|
||||
|
||||
drop policy if exists "ppt_select_own" on public.patient_patient_tag;
|
||||
create policy "ppt_select_own"
|
||||
on public.patient_patient_tag for select
|
||||
to authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1 from public.patients p
|
||||
where p.id = patient_patient_tag.patient_id
|
||||
and p.owner_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
drop policy if exists "ppt_write_own" on public.patient_patient_tag;
|
||||
create policy "ppt_write_own"
|
||||
on public.patient_patient_tag for all
|
||||
to authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1 from public.patients p
|
||||
where p.id = patient_patient_tag.patient_id
|
||||
and p.owner_id = auth.uid()
|
||||
)
|
||||
)
|
||||
with check (
|
||||
exists (
|
||||
select 1 from public.patients p
|
||||
where p.id = patient_patient_tag.patient_id
|
||||
and p.owner_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
grant select, insert, update, delete on public.patient_patient_tag to authenticated;
|
||||
|
||||
-- =========================================================
|
||||
-- FIM PATCH
|
||||
-- =========================================================
|
||||
42
DBS/2026-03-11/supabase-snippets/Untitled query 899.sql
Normal file
42
DBS/2026-03-11/supabase-snippets/Untitled query 899.sql
Normal file
@@ -0,0 +1,42 @@
|
||||
-- BUCKET avatars: RLS por pasta do usuário "<uid>/..."
|
||||
-- Requer que seu path seja: `${auth.uid()}/...` (no seu código já é)
|
||||
|
||||
drop policy if exists "avatars_select_own" on storage.objects;
|
||||
create policy "avatars_select_own"
|
||||
on storage.objects for select
|
||||
to authenticated
|
||||
using (
|
||||
bucket_id = 'avatars'
|
||||
and name like auth.uid()::text || '/%'
|
||||
);
|
||||
|
||||
drop policy if exists "avatars_insert_own" on storage.objects;
|
||||
create policy "avatars_insert_own"
|
||||
on storage.objects for insert
|
||||
to authenticated
|
||||
with check (
|
||||
bucket_id = 'avatars'
|
||||
and name like auth.uid()::text || '/%'
|
||||
);
|
||||
|
||||
drop policy if exists "avatars_update_own" on storage.objects;
|
||||
create policy "avatars_update_own"
|
||||
on storage.objects for update
|
||||
to authenticated
|
||||
using (
|
||||
bucket_id = 'avatars'
|
||||
and name like auth.uid()::text || '/%'
|
||||
)
|
||||
with check (
|
||||
bucket_id = 'avatars'
|
||||
and name like auth.uid()::text || '/%'
|
||||
);
|
||||
|
||||
drop policy if exists "avatars_delete_own" on storage.objects;
|
||||
create policy "avatars_delete_own"
|
||||
on storage.objects for delete
|
||||
to authenticated
|
||||
using (
|
||||
bucket_id = 'avatars'
|
||||
and name like auth.uid()::text || '/%'
|
||||
);
|
||||
3
DBS/2026-03-11/supabase-snippets/Untitled query 934.sql
Normal file
3
DBS/2026-03-11/supabase-snippets/Untitled query 934.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
select *
|
||||
from tenant_members
|
||||
where user_id = 'SEU_USER_ID';
|
||||
14
DBS/2026-03-11/supabase-snippets/Untitled query 938.sql
Normal file
14
DBS/2026-03-11/supabase-snippets/Untitled query 938.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
select
|
||||
tm.id as responsible_member_id,
|
||||
tm.tenant_id,
|
||||
tm.user_id,
|
||||
tm.role,
|
||||
tm.status,
|
||||
tm.created_at
|
||||
from public.tenant_members tm
|
||||
where tm.tenant_id = (
|
||||
select owner_id from public.patient_intake_requests
|
||||
where id = '54daa09a-b2cb-4a0b-91aa-e4cea1915efe'
|
||||
)
|
||||
and tm.user_id = '824f125c-55bb-40f5-a8c4-7a33618b91c7'
|
||||
limit 10;
|
||||
17
DBS/2026-03-11/supabase-snippets/Untitled query 975.sql
Normal file
17
DBS/2026-03-11/supabase-snippets/Untitled query 975.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- 1) Qual é meu uid?
|
||||
select auth.uid() as my_uid;
|
||||
|
||||
-- 2) Tenho membership ativa no tenant atual?
|
||||
select *
|
||||
from tenant_members
|
||||
where tenant_id = 'e8b10543-fb36-4e75-9d37-6fece9745637'
|
||||
and user_id = auth.uid()
|
||||
order by created_at desc;
|
||||
|
||||
-- 3) Se você usa status:
|
||||
select *
|
||||
from tenant_members
|
||||
where tenant_id = 'e8b10543-fb36-4e75-9d37-6fece9745637'
|
||||
and user_id = auth.uid()
|
||||
and status = 'active'
|
||||
order by created_at desc;
|
||||
123
DBS/2026-03-11/supabase-snippets/saas_docs.sql
Normal file
123
DBS/2026-03-11/supabase-snippets/saas_docs.sql
Normal file
@@ -0,0 +1,123 @@
|
||||
-- ============================================================
|
||||
-- saas_docs — Documentação dinâmica do sistema
|
||||
-- Exibida nas páginas do frontend via botão "Ajuda"
|
||||
-- ============================================================
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1. TABELA
|
||||
-- ------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS public.saas_docs (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
titulo text NOT NULL,
|
||||
conteudo text NOT NULL DEFAULT '',
|
||||
medias jsonb NOT NULL DEFAULT '[]'::jsonb,
|
||||
-- formato: [{ "tipo": "imagem"|"video", "url": "..." }, ...]
|
||||
|
||||
tipo_acesso text NOT NULL DEFAULT 'usuario'
|
||||
CHECK (tipo_acesso IN ('usuario', 'admin')),
|
||||
-- 'usuario' → todos os autenticados
|
||||
-- 'admin' → clinic_admin, tenant_admin, saas_admin
|
||||
|
||||
pagina_path text NOT NULL,
|
||||
-- path da rota do frontend, ex: '/therapist/agenda'
|
||||
|
||||
pagina_label text,
|
||||
-- label amigável (informativo, não usado no match)
|
||||
|
||||
docs_relacionados uuid[] NOT NULL DEFAULT '{}',
|
||||
-- IDs de outros saas_docs exibidos como "Veja também"
|
||||
|
||||
ativo boolean NOT NULL DEFAULT true,
|
||||
ordem int NOT NULL DEFAULT 0,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2. ÍNDICE
|
||||
-- ------------------------------------------------------------
|
||||
-- Query principal do frontend: filtra por path + ativo
|
||||
CREATE INDEX IF NOT EXISTS saas_docs_path_ativo_idx
|
||||
ON public.saas_docs (pagina_path, ativo);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3. RLS
|
||||
-- ------------------------------------------------------------
|
||||
ALTER TABLE public.saas_docs ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- SaaS admin: acesso total (SELECT, INSERT, UPDATE, DELETE)
|
||||
-- Verificado via tabela saas_admins
|
||||
CREATE POLICY "saas_admin_full_access" ON public.saas_docs
|
||||
FOR ALL
|
||||
TO authenticated
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.saas_admins
|
||||
WHERE saas_admins.user_id = auth.uid()
|
||||
)
|
||||
)
|
||||
WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.saas_admins
|
||||
WHERE saas_admins.user_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
-- Admins de clínica: leem todos os docs ativos (usuario + admin)
|
||||
CREATE POLICY "clinic_admin_read_all_docs" ON public.saas_docs
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
ativo = true
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM public.profiles
|
||||
WHERE profiles.id = auth.uid()
|
||||
AND profiles.role IN ('clinic_admin', 'tenant_admin')
|
||||
)
|
||||
);
|
||||
|
||||
-- Demais usuários autenticados: leem apenas docs do tipo 'usuario'
|
||||
CREATE POLICY "users_read_usuario_docs" ON public.saas_docs
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
ativo = true
|
||||
AND tipo_acesso = 'usuario'
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4. STORAGE — bucket saas-docs (imagens dos documentos)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO storage.buckets (id, name, public)
|
||||
VALUES ('saas-docs', 'saas-docs', true)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- SaaS admin: pode fazer upload
|
||||
CREATE POLICY "saas_admin_storage_upload" ON storage.objects
|
||||
FOR INSERT
|
||||
TO authenticated
|
||||
WITH CHECK (
|
||||
bucket_id = 'saas-docs'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM public.saas_admins
|
||||
WHERE saas_admins.user_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
-- SaaS admin: pode deletar
|
||||
CREATE POLICY "saas_admin_storage_delete" ON storage.objects
|
||||
FOR DELETE
|
||||
TO authenticated
|
||||
USING (
|
||||
bucket_id = 'saas-docs'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM public.saas_admins
|
||||
WHERE saas_admins.user_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
-- Leitura pública (bucket é público, mas policy explícita para clareza)
|
||||
CREATE POLICY "saas_docs_public_read" ON storage.objects
|
||||
FOR SELECT
|
||||
TO public
|
||||
USING (bucket_id = 'saas-docs');
|
||||
Reference in New Issue
Block a user