Agenda, Agendador, Configurações
This commit is contained in:
174
DBS/2026-03-11/src-sql-arquivos/supabase_patient_groups.sql
Normal file
174
DBS/2026-03-11/src-sql-arquivos/supabase_patient_groups.sql
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
patient_groups_setup.sql
|
||||
Setup completo para:
|
||||
- public.patient_groups
|
||||
- public.patient_group_patient (tabela ponte)
|
||||
- view public.v_patient_groups_with_counts
|
||||
- índice único por owner + nome (case-insensitive)
|
||||
- 3 grupos padrão do sistema (Crianças, Adolescentes, Idosos) NÃO editáveis / NÃO removíveis
|
||||
- triggers de proteção
|
||||
|
||||
Observação (importante):
|
||||
- Os grupos padrão são criados com owner_id = '00000000-0000-0000-0000-000000000000' (SYSTEM_OWNER),
|
||||
para ficarem "globais" e não dependerem de auth.uid() em migrations.
|
||||
- Se você quiser que os grupos padrão pertençam a um owner específico (tenant),
|
||||
basta trocar o SYSTEM_OWNER abaixo por esse UUID.
|
||||
*/
|
||||
|
||||
begin;
|
||||
|
||||
-- ===========================
|
||||
-- 0) Constante de "dono do sistema"
|
||||
-- ===========================
|
||||
-- Troque aqui se você quiser que os grupos padrão pertençam a um owner específico.
|
||||
-- Ex.: '816b24fe-a0c3-4409-b79b-c6c0a6935d03'
|
||||
do $$
|
||||
begin
|
||||
-- só para documentar; não cria nada
|
||||
end $$;
|
||||
|
||||
-- ===========================
|
||||
-- 1) Tabela principal: patient_groups
|
||||
-- ===========================
|
||||
create table if not exists public.patient_groups (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
name text not null,
|
||||
description text,
|
||||
color text,
|
||||
is_active boolean not null default true,
|
||||
is_system boolean not null default false,
|
||||
owner_id uuid not null,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
-- (Opcional, mas recomendado) Garante que name não seja só espaços
|
||||
-- e evita nomes vazios.
|
||||
alter table public.patient_groups
|
||||
drop constraint if exists patient_groups_name_not_blank_check;
|
||||
|
||||
alter table public.patient_groups
|
||||
add constraint patient_groups_name_not_blank_check
|
||||
check (length(btrim(name)) > 0);
|
||||
|
||||
-- ===========================
|
||||
-- 2) Tabela ponte: patient_group_patient
|
||||
-- ===========================
|
||||
-- Se você já tiver essa tabela com FKs, ajuste aqui conforme seu schema.
|
||||
create table if not exists public.patient_group_patient (
|
||||
patient_group_id uuid not null references public.patient_groups(id) on delete cascade,
|
||||
patient_id uuid not null references public.patients(id) on delete cascade,
|
||||
created_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
-- Evita duplicar vínculo paciente<->grupo
|
||||
create unique index if not exists patient_group_patient_unique
|
||||
on public.patient_group_patient (patient_group_id, patient_id);
|
||||
|
||||
-- ===========================
|
||||
-- 3) View com contagem
|
||||
-- ===========================
|
||||
create or replace view public.v_patient_groups_with_counts as
|
||||
select
|
||||
g.*,
|
||||
coalesce(count(distinct pgp.patient_id), 0)::int as patients_count
|
||||
from public.patient_groups g
|
||||
left join public.patient_group_patient pgp
|
||||
on pgp.patient_group_id = g.id
|
||||
group by g.id;
|
||||
|
||||
-- ===========================
|
||||
-- 4) Índice único: não permitir mesmo nome por owner (case-insensitive)
|
||||
-- ===========================
|
||||
-- Atenção: se já existirem duplicados, este índice pode falhar ao criar.
|
||||
create unique index if not exists patient_groups_owner_name_unique
|
||||
on public.patient_groups (owner_id, (lower(name)));
|
||||
|
||||
-- ===========================
|
||||
-- 5) Triggers de proteção: system não edita / não remove
|
||||
-- ===========================
|
||||
create or replace function public.prevent_system_group_changes()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
if old.is_system = true then
|
||||
raise exception 'Grupos padrão do sistema não podem ser alterados ou excluídos.';
|
||||
end if;
|
||||
|
||||
if tg_op = 'DELETE' then
|
||||
return old;
|
||||
end if;
|
||||
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists trg_prevent_system_group_changes on public.patient_groups;
|
||||
|
||||
create trigger trg_prevent_system_group_changes
|
||||
before update or delete on public.patient_groups
|
||||
for each row
|
||||
execute function public.prevent_system_group_changes();
|
||||
|
||||
-- Impede "promover" um grupo comum para system
|
||||
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();
|
||||
|
||||
-- ===========================
|
||||
-- 6) Inserir 3 grupos padrão (imutáveis)
|
||||
-- ===========================
|
||||
-- Dono "global" do sistema (mude se quiser):
|
||||
-- 00000000-0000-0000-0000-000000000000
|
||||
with sys_owner as (
|
||||
select '00000000-0000-0000-0000-000000000000'::uuid as owner_id
|
||||
)
|
||||
insert into public.patient_groups (name, description, color, is_active, is_system, owner_id)
|
||||
select v.name, v.description, v.color, v.is_active, v.is_system, s.owner_id
|
||||
from sys_owner s
|
||||
join (values
|
||||
('Crianças', 'Grupo padrão do sistema', null, true, true),
|
||||
('Adolescentes', 'Grupo padrão do sistema', null, true, true),
|
||||
('Idosos', 'Grupo padrão do sistema', null, true, true)
|
||||
) as v(name, description, color, is_active, is_system)
|
||||
on true
|
||||
where not exists (
|
||||
select 1
|
||||
from public.patient_groups g
|
||||
where g.owner_id = s.owner_id
|
||||
and lower(g.name) = lower(v.name)
|
||||
);
|
||||
|
||||
commit;
|
||||
|
||||
/*
|
||||
Testes rápidos:
|
||||
1) Ver tudo:
|
||||
select * from public.v_patient_groups_with_counts order by is_system desc, name;
|
||||
|
||||
2) Tentar editar um system (deve falhar):
|
||||
update public.patient_groups set name='X' where name='Crianças';
|
||||
|
||||
3) Tentar deletar um system (deve falhar):
|
||||
delete from public.patient_groups where name='Crianças';
|
||||
|
||||
4) Tentar duplicar nome no mesmo owner (deve falhar por índice único):
|
||||
insert into public.patient_groups (name, is_active, is_system, owner_id)
|
||||
values ('teste22', true, false, '816b24fe-a0c3-4409-b79b-c6c0a6935d03');
|
||||
*/
|
||||
Reference in New Issue
Block a user