


SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;


CREATE EXTENSION IF NOT EXISTS "pg_net" WITH SCHEMA "extensions";






COMMENT ON SCHEMA "public" IS 'standard public schema';



CREATE EXTENSION IF NOT EXISTS "btree_gist" WITH SCHEMA "public";






CREATE EXTENSION IF NOT EXISTS "citext" WITH SCHEMA "public";






CREATE EXTENSION IF NOT EXISTS "pg_graphql" WITH SCHEMA "graphql";






CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "extensions";






CREATE EXTENSION IF NOT EXISTS "pg_trgm" WITH SCHEMA "public";






CREATE EXTENSION IF NOT EXISTS "pgcrypto" WITH SCHEMA "extensions";






CREATE EXTENSION IF NOT EXISTS "supabase_vault" WITH SCHEMA "vault";






CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA "extensions";






CREATE TYPE "public"."commitment_log_source" AS ENUM (
    'manual',
    'auto'
);


ALTER TYPE "public"."commitment_log_source" OWNER TO "supabase_admin";


CREATE TYPE "public"."determined_field_type" AS ENUM (
    'text',
    'textarea',
    'number',
    'date',
    'select',
    'boolean'
);


ALTER TYPE "public"."determined_field_type" OWNER TO "supabase_admin";


CREATE TYPE "public"."recurrence_exception_type" AS ENUM (
    'cancel_session',
    'reschedule_session',
    'patient_missed',
    'therapist_canceled',
    'holiday_block'
);


ALTER TYPE "public"."recurrence_exception_type" OWNER TO "supabase_admin";


CREATE TYPE "public"."recurrence_type" AS ENUM (
    'weekly',
    'biweekly',
    'monthly',
    'yearly',
    'custom_weekdays'
);


ALTER TYPE "public"."recurrence_type" OWNER TO "supabase_admin";


CREATE TYPE "public"."status_agenda_serie" AS ENUM (
    'ativo',
    'pausado',
    'cancelado'
);


ALTER TYPE "public"."status_agenda_serie" OWNER TO "supabase_admin";


CREATE TYPE "public"."status_evento_agenda" AS ENUM (
    'agendado',
    'realizado',
    'faltou',
    'cancelado',
    'remarcar'
);


ALTER TYPE "public"."status_evento_agenda" OWNER TO "supabase_admin";


CREATE TYPE "public"."status_excecao_agenda" AS ENUM (
    'pendente',
    'ativo',
    'arquivado'
);


ALTER TYPE "public"."status_excecao_agenda" OWNER TO "supabase_admin";


CREATE TYPE "public"."tipo_evento_agenda" AS ENUM (
    'sessao',
    'bloqueio'
);


ALTER TYPE "public"."tipo_evento_agenda" OWNER TO "supabase_admin";


CREATE TYPE "public"."tipo_excecao_agenda" AS ENUM (
    'bloqueio',
    'horario_extra'
);


ALTER TYPE "public"."tipo_excecao_agenda" OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."__rls_ping"() RETURNS "text"
    LANGUAGE "sql" STABLE
    AS $$
  select 'ok'::text;
$$;


ALTER FUNCTION "public"."__rls_ping"() OWNER TO "supabase_admin";

SET default_tablespace = '';

SET default_table_access_method = "heap";


CREATE TABLE IF NOT EXISTS "public"."subscriptions" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "user_id" "uuid",
    "plan_id" "uuid" NOT NULL,
    "status" "text" DEFAULT 'active'::"text" NOT NULL,
    "current_period_start" timestamp with time zone,
    "current_period_end" timestamp with time zone,
    "cancel_at_period_end" boolean DEFAULT false NOT NULL,
    "provider" "text" DEFAULT 'manual'::"text" NOT NULL,
    "provider_customer_id" "text",
    "provider_subscription_id" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "tenant_id" "uuid",
    "plan_key" "text",
    "interval" "text",
    "source" "text" DEFAULT 'manual'::"text" NOT NULL,
    "started_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "canceled_at" timestamp with time zone,
    "activated_at" timestamp with time zone,
    "past_due_since" timestamp with time zone,
    "suspended_at" timestamp with time zone,
    "suspended_reason" "text",
    "cancelled_at" timestamp with time zone,
    "cancel_reason" "text",
    "expired_at" timestamp with time zone,
    CONSTRAINT "subscriptions_interval_check" CHECK (("interval" = ANY (ARRAY['month'::"text", 'year'::"text"]))),
    CONSTRAINT "subscriptions_owner_xor" CHECK (((("tenant_id" IS NOT NULL) AND ("user_id" IS NULL)) OR (("tenant_id" IS NULL) AND ("user_id" IS NOT NULL)))),
    CONSTRAINT "subscriptions_status_check" CHECK (("status" = ANY (ARRAY['pending'::"text", 'active'::"text", 'past_due'::"text", 'suspended'::"text", 'cancelled'::"text", 'expired'::"text"])))
);


ALTER TABLE "public"."subscriptions" OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."activate_subscription_from_intent"("p_intent_id" "uuid") RETURNS "public"."subscriptions"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_intent record;
  v_sub public.subscriptions;
  v_days int;
  v_user_id uuid;
  v_plan_id uuid;
  v_target text;
begin
  -- lê pela VIEW unificada
  select * into v_intent
  from public.subscription_intents
  where id = p_intent_id;

  if not found then
    raise exception 'Intent não encontrado: %', p_intent_id;
  end if;

  if v_intent.status <> 'paid' then
    raise exception 'Intent precisa estar paid para ativar assinatura';
  end if;

  -- resolve target e plan_id via plans.key
  select p.id, p.target
    into v_plan_id, v_target
  from public.plans p
  where p.key = v_intent.plan_key
  limit 1;

  if v_plan_id is null then
    raise exception 'Plano não encontrado em plans.key = %', v_intent.plan_key;
  end if;

  v_target := lower(coalesce(v_target, ''));

  -- ✅ supervisor adicionado
  if v_target not in ('clinic', 'therapist', 'supervisor') then
    raise exception 'Target inválido em plans.target: %', v_target;
  end if;

  -- regra por target
  if v_target = 'clinic' then
    if v_intent.tenant_id is null then
      raise exception 'Intent sem tenant_id';
    end if;
  else
    -- therapist ou supervisor: vinculado ao user
    v_user_id := v_intent.user_id;
    if v_user_id is null then
      v_user_id := v_intent.created_by_user_id;
    end if;
  end if;

  if v_target in ('therapist', 'supervisor') and v_user_id is null then
    raise exception 'Não foi possível determinar user_id para assinatura %.', v_target;
  end if;

  -- cancela assinatura ativa anterior
  if v_target = 'clinic' then
    update public.subscriptions
    set status = 'cancelled',
        cancelled_at = now()
    where tenant_id = v_intent.tenant_id
      and plan_id = v_plan_id
      and status = 'active';
  else
    -- therapist ou supervisor
    update public.subscriptions
    set status = 'cancelled',
        cancelled_at = now()
    where user_id = v_user_id
      and plan_id = v_plan_id
      and status = 'active'
      and tenant_id is null;
  end if;

  -- duração do plano (30 dias para mensal)
  v_days := case
    when lower(coalesce(v_intent.interval, 'month')) = 'year' then 365
    else 30
  end;

  -- cria nova assinatura
  insert into public.subscriptions (
    user_id,
    plan_id,
    status,
    started_at,
    expires_at,
    cancelled_at,
    activated_at,
    tenant_id,
    plan_key,
    interval,
    source,
    created_at,
    updated_at
  )
  values (
    case when v_target = 'clinic' then null else v_user_id end,
    v_plan_id,
    'active',
    now(),
    now() + make_interval(days => v_days),
    null,
    now(),
    case when v_target = 'clinic' then v_intent.tenant_id else null end,
    v_intent.plan_key,
    v_intent.interval,
    'manual',
    now(),
    now()
  )
  returning * into v_sub;

  -- grava vínculo intent → subscription
  if v_target = 'clinic' then
    update public.subscription_intents_tenant
    set subscription_id = v_sub.id
    where id = p_intent_id;
  else
    update public.subscription_intents_personal
    set subscription_id = v_sub.id
    where id = p_intent_id;
  end if;

  return v_sub;
end;
$$;


ALTER FUNCTION "public"."activate_subscription_from_intent"("p_intent_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."admin_fix_plan_target"("p_plan_key" "text", "p_new_target" "text") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_plan_id uuid;
begin
  -- (opcional) restringe targets válidos
  if p_new_target not in ('clinic','therapist') then
    raise exception 'Target inválido: %', p_new_target using errcode='P0001';
  end if;

  -- trava o plano
  select id into v_plan_id
  from public.plans
  where key = p_plan_key
  for update;

  if v_plan_id is null then
    raise exception 'Plano não encontrado: %', p_plan_key using errcode='P0001';
  end if;

  -- segurança: não mexer se existe subscription
  if exists (select 1 from public.subscriptions s where s.plan_id = v_plan_id) then
    raise exception 'Plano % possui subscriptions. Migração bloqueada.', p_plan_key using errcode='P0001';
  end if;

  -- liga bypass SOMENTE nesta transação
  perform set_config('app.plan_migration_bypass', '1', true);

  update public.plans
  set target = p_new_target
  where id = v_plan_id;

end
$$;


ALTER FUNCTION "public"."admin_fix_plan_target"("p_plan_key" "text", "p_new_target" "text") OWNER TO "supabase_admin";


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;
$$;


ALTER FUNCTION "public"."agenda_cfg_sync"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."agendador_dias_disponiveis"("p_slug" "text", "p_ano" integer, "p_mes" integer) RETURNS TABLE("data" "date", "tem_slots" boolean)
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
DECLARE
  v_owner_id     uuid;
  v_antecedencia int;
  v_agora        timestamptz;
  v_data         date;
  v_data_inicio  date;
  v_data_fim     date;
  v_db_dow       int;
  v_tem_slot     boolean;
BEGIN
  SELECT c.owner_id, c.antecedencia_minima_horas
  INTO v_owner_id, v_antecedencia
  FROM public.agendador_configuracoes c
  WHERE c.link_slug = p_slug AND c.ativo = true
  LIMIT 1;

  IF v_owner_id IS NULL THEN RETURN; END IF;

  v_agora       := now();
  v_data_inicio := make_date(p_ano, p_mes, 1);
  v_data_fim    := (v_data_inicio + interval '1 month' - interval '1 day')::date;

  v_data := v_data_inicio;
  WHILE v_data <= v_data_fim LOOP
    v_db_dow := extract(dow from v_data::timestamp)::int;

    SELECT EXISTS (
      SELECT 1 FROM public.agenda_online_slots s
      WHERE s.owner_id = v_owner_id
        AND s.weekday  = v_db_dow
        AND s.enabled  = true
        AND (v_data::text || ' ' || s.time::text)::timestamp
              AT TIME ZONE 'America/Sao_Paulo'
            >= v_agora + (v_antecedencia || ' hours')::interval
    ) INTO v_tem_slot;

    IF v_tem_slot THEN
      data      := v_data;
      tem_slots := true;
      RETURN NEXT;
    END IF;

    v_data := v_data + 1;
  END LOOP;
END;
$$;


ALTER FUNCTION "public"."agendador_dias_disponiveis"("p_slug" "text", "p_ano" integer, "p_mes" integer) OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."agendador_gerar_slug"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
DECLARE
  v_slug text;
  v_exists boolean;
BEGIN
  -- só gera se ativou e não tem slug ainda
  IF NEW.ativo = true AND (NEW.link_slug IS NULL OR NEW.link_slug = '') THEN
    LOOP
      v_slug := lower(substring(replace(gen_random_uuid()::text, '-', ''), 1, 8));
      SELECT EXISTS (
        SELECT 1 FROM public.agendador_configuracoes
        WHERE link_slug = v_slug AND owner_id <> NEW.owner_id
      ) INTO v_exists;
      EXIT WHEN NOT v_exists;
    END LOOP;
    NEW.link_slug := v_slug;
  END IF;
  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."agendador_gerar_slug"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."agendador_slots_disponiveis"("p_slug" "text", "p_data" "date") RETURNS TABLE("hora" time without time zone, "disponivel" boolean)
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
DECLARE
  v_owner_id       uuid;
  v_duracao        int;
  v_antecedencia   int;
  v_agora          timestamptz;
  v_db_dow         int;
  v_slot           time;
  v_slot_fim       time;
  v_slot_ts        timestamptz;
  v_ocupado        boolean;
  -- loop de recorrências
  v_rule           RECORD;
  v_rule_start_dow int;
  v_first_occ      date;
  v_day_diff       int;
  v_ex_type        text;
BEGIN
  SELECT c.owner_id, c.duracao_sessao_min, c.antecedencia_minima_horas
  INTO v_owner_id, v_duracao, v_antecedencia
  FROM public.agendador_configuracoes c
  WHERE c.link_slug = p_slug AND c.ativo = true
  LIMIT 1;

  IF v_owner_id IS NULL THEN RETURN; END IF;

  v_agora  := now();
  v_db_dow := extract(dow from p_data::timestamp)::int;

  FOR v_slot IN
    SELECT s.time
    FROM public.agenda_online_slots s
    WHERE s.owner_id = v_owner_id
      AND s.weekday  = v_db_dow
      AND s.enabled  = true
    ORDER BY s.time
  LOOP
    v_slot_fim := v_slot + (v_duracao || ' minutes')::interval;
    v_ocupado  := false;

    -- ── Antecedência mínima ──────────────────────────────────────────────────
    v_slot_ts := (p_data::text || ' ' || v_slot::text)::timestamp
                  AT TIME ZONE 'America/Sao_Paulo';
    IF v_slot_ts < v_agora + (v_antecedencia || ' hours')::interval THEN
      v_ocupado := true;
    END IF;

    -- ── Eventos avulsos internos (agenda_eventos) ────────────────────────────
    IF NOT v_ocupado THEN
      SELECT EXISTS (
        SELECT 1 FROM public.agenda_eventos e
        WHERE e.owner_id = v_owner_id
          AND e.status::text NOT IN ('cancelado', 'faltou')
          AND (e.inicio_em AT TIME ZONE 'America/Sao_Paulo')::date = p_data
          AND (e.inicio_em AT TIME ZONE 'America/Sao_Paulo')::time < v_slot_fim
          AND (e.fim_em    AT TIME ZONE 'America/Sao_Paulo')::time > v_slot
      ) INTO v_ocupado;
    END IF;

    -- ── Recorrências ativas (recurrence_rules) ───────────────────────────────
    -- Loop explícito para evitar erros de tipo no cálculo do ciclo semanal
    IF NOT v_ocupado THEN
      FOR v_rule IN
        SELECT
          r.id,
          r.start_date::date                AS start_date,
          r.end_date::date                  AS end_date,
          r.start_time::time                AS start_time,
          r.end_time::time                  AS end_time,
          COALESCE(r.interval, 1)::int      AS interval
        FROM public.recurrence_rules r
        WHERE r.owner_id = v_owner_id
          AND r.status   = 'ativo'
          AND p_data    >= r.start_date::date
          AND (r.end_date IS NULL OR p_data <= r.end_date::date)
          AND v_db_dow = ANY(r.weekdays)
          AND r.start_time::time < v_slot_fim
          AND r.end_time::time   > v_slot
      LOOP
        -- Calcula a primeira ocorrência do dia-da-semana a partir do start_date
        v_rule_start_dow := extract(dow from v_rule.start_date)::int;
        v_first_occ      := v_rule.start_date
                              + (((v_db_dow - v_rule_start_dow + 7) % 7))::int;
        v_day_diff       := (p_data - v_first_occ)::int;

        -- Ocorrência válida: diff >= 0 e divisível pelo ciclo semanal
        IF v_day_diff >= 0 AND v_day_diff % (7 * v_rule.interval) = 0 THEN

          -- Verifica se há exceção para esta data
          v_ex_type := NULL;
          SELECT ex.type INTO v_ex_type
          FROM public.recurrence_exceptions ex
          WHERE ex.recurrence_id = v_rule.id
            AND ex.original_date = p_data
          LIMIT 1;

          -- Sem exceção, ou exceção que não cancela → bloqueia o slot
          IF v_ex_type IS NULL OR v_ex_type NOT IN (
            'cancel_session', 'patient_missed',
            'therapist_canceled', 'holiday_block',
            'reschedule_session'
          ) THEN
            v_ocupado := true;
            EXIT; -- já basta uma regra que conflite
          END IF;

        END IF;
      END LOOP;
    END IF;

    -- ── Recorrências remarcadas para este dia (reschedule → new_date = p_data) ─
    IF NOT v_ocupado THEN
      SELECT EXISTS (
        SELECT 1
        FROM public.recurrence_exceptions ex
        JOIN public.recurrence_rules r ON r.id = ex.recurrence_id
        WHERE r.owner_id  = v_owner_id
          AND r.status    = 'ativo'
          AND ex.type     = 'reschedule_session'
          AND ex.new_date = p_data
          AND COALESCE(ex.new_start_time, r.start_time)::time < v_slot_fim
          AND COALESCE(ex.new_end_time,   r.end_time)::time   > v_slot
      ) INTO v_ocupado;
    END IF;

    -- ── Solicitações públicas pendentes ──────────────────────────────────────
    IF NOT v_ocupado THEN
      SELECT EXISTS (
        SELECT 1 FROM public.agendador_solicitacoes sol
        WHERE sol.owner_id        = v_owner_id
          AND sol.status          = 'pendente'
          AND sol.data_solicitada = p_data
          AND sol.hora_solicitada = v_slot
          AND (sol.reservado_ate IS NULL OR sol.reservado_ate > v_agora)
      ) INTO v_ocupado;
    END IF;

    hora       := v_slot;
    disponivel := NOT v_ocupado;
    RETURN NEXT;
  END LOOP;
END;
$$;


ALTER FUNCTION "public"."agendador_slots_disponiveis"("p_slug" "text", "p_data" "date") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."cancel_recurrence_from"("p_recurrence_id" "uuid", "p_from_date" "date") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
BEGIN
  UPDATE public.recurrence_rules
  SET
    end_date   = p_from_date - INTERVAL '1 day',
    open_ended = false,
    status     = CASE
                   WHEN p_from_date <= start_date THEN 'cancelado'
                   ELSE status
                 END,
    updated_at = now()
  WHERE id = p_recurrence_id;
END;
$$;


ALTER FUNCTION "public"."cancel_recurrence_from"("p_recurrence_id" "uuid", "p_from_date" "date") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."cancel_subscription"("p_subscription_id" "uuid") RETURNS "public"."subscriptions"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_sub public.subscriptions;
  v_owner_type text;
  v_owner_ref uuid;
begin

  select *
  into v_sub
  from public.subscriptions
  where id = p_subscription_id
  for update;

  if not found then
    raise exception 'Subscription não encontrada';
  end if;

  if v_sub.status = 'canceled' then
    return v_sub;
  end if;

  if v_sub.tenant_id is not null then
    v_owner_type := 'clinic';
    v_owner_ref := v_sub.tenant_id;
  elsif v_sub.user_id is not null then
    v_owner_type := 'therapist';
    v_owner_ref := v_sub.user_id;
  else
    v_owner_type := null;
    v_owner_ref := null;
  end if;

  update public.subscriptions
  set status = 'canceled',
      cancel_at_period_end = false,
      updated_at = now()
  where id = p_subscription_id
  returning * into v_sub;

  insert into public.subscription_events(
    subscription_id,
    owner_id,
    owner_type,
    owner_ref,
    event_type,
    old_plan_id,
    new_plan_id,
    created_by,
    reason,
    source,
    metadata
  )
  values (
    v_sub.id,
    v_owner_ref,
    v_owner_type,
    v_owner_ref,
    'canceled',
    v_sub.plan_id,
    v_sub.plan_id,
    auth.uid(),
    'Cancelamento manual via admin',
    'admin_panel',
    jsonb_build_object('previous_status', 'active')
  );

  if v_owner_ref is not null then
    insert into public.entitlements_invalidation(owner_id, changed_at)
    values (v_owner_ref, now())
    on conflict (owner_id)
    do update set changed_at = excluded.changed_at;
  end if;

  return v_sub;

end;
$$;


ALTER FUNCTION "public"."cancel_subscription"("p_subscription_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."cancelar_eventos_serie"("p_serie_id" "uuid", "p_a_partir_de" timestamp with time zone DEFAULT "now"()) RETURNS integer
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
DECLARE
  v_count integer;
BEGIN
  UPDATE public.agenda_eventos
     SET status     = 'cancelado',
         updated_at = now()
   WHERE serie_id  = p_serie_id
     AND inicio_em >= p_a_partir_de
     AND status NOT IN ('realizado', 'cancelado');

  GET DIAGNOSTICS v_count = ROW_COUNT;
  RETURN v_count;
END;
$$;


ALTER FUNCTION "public"."cancelar_eventos_serie"("p_serie_id" "uuid", "p_a_partir_de" timestamp with time zone) OWNER TO "supabase_admin";


COMMENT ON FUNCTION "public"."cancelar_eventos_serie"("p_serie_id" "uuid", "p_a_partir_de" timestamp with time zone) IS 'Cancela todos os eventos futuros de uma série a partir de p_a_partir_de (inclusive).
   Não cancela eventos já realizados.';



CREATE OR REPLACE FUNCTION "public"."change_subscription_plan"("p_subscription_id" "uuid", "p_new_plan_id" "uuid") RETURNS "public"."subscriptions"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_sub public.subscriptions;
  v_old_plan uuid;
  v_new_key text;

  v_owner_type text;
  v_owner_ref uuid;

  v_new_target text;
  v_sub_target text;
begin
  select *
    into v_sub
  from public.subscriptions
  where id = p_subscription_id
  for update;

  if not found then
    raise exception 'Subscription não encontrada';
  end if;

  v_old_plan := v_sub.plan_id;

  if v_old_plan = p_new_plan_id then
    return v_sub;
  end if;

  select key, target
    into v_new_key, v_new_target
  from public.plans
  where id = p_new_plan_id;

  if v_new_key is null then
    raise exception 'Plano não encontrado';
  end if;

  v_new_target := lower(coalesce(v_new_target, ''));

  v_sub_target := case
    when v_sub.tenant_id is not null then 'clinic'
    else 'therapist'
  end;

  if v_new_target <> v_sub_target then
    raise exception 'Plano inválido para este tipo de assinatura. Assinatura é % e o plano é %.',
      v_sub_target, v_new_target
      using errcode = 'P0001';
  end if;

  if v_sub.tenant_id is not null then
    v_owner_type := 'clinic';
    v_owner_ref := v_sub.tenant_id;
  elsif v_sub.user_id is not null then
    v_owner_type := 'therapist';
    v_owner_ref := v_sub.user_id;
  else
    v_owner_type := null;
    v_owner_ref := null;
  end if;

  update public.subscriptions
  set plan_id = p_new_plan_id,
      plan_key = v_new_key,
      updated_at = now()
  where id = p_subscription_id
  returning * into v_sub;

  insert into public.subscription_events(
    subscription_id,
    owner_id,
    owner_type,
    owner_ref,
    event_type,
    old_plan_id,
    new_plan_id,
    created_by,
    reason,
    source,
    metadata
  )
  values (
    v_sub.id,
    v_owner_ref,
    v_owner_type,
    v_owner_ref,
    'plan_changed',
    v_old_plan,
    p_new_plan_id,
    auth.uid(),
    'Plan change via DEV menu',
    'dev_menu',
    jsonb_build_object(
      'previous_plan', v_old_plan,
      'new_plan', p_new_plan_id,
      'new_plan_key', v_new_key,
      'new_plan_target', v_new_target
    )
  );

  if v_owner_ref is not null then
    insert into public.entitlements_invalidation (owner_id, changed_at)
    values (v_owner_ref, now())
    on conflict (owner_id)
    do update set changed_at = excluded.changed_at;
  end if;

  return v_sub;
end;
$$;


ALTER FUNCTION "public"."change_subscription_plan"("p_subscription_id" "uuid", "p_new_plan_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."create_clinic_tenant"("p_name" "text") RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_uid uuid;
  v_tenant uuid;
  v_name text;
begin
  v_uid := auth.uid();
  if v_uid is null then
    raise exception 'Not authenticated';
  end if;

  v_name := nullif(trim(coalesce(p_name, '')), '');
  if v_name is null then
    v_name := 'Clínica';
  end if;

  insert into public.tenants (name, kind, created_at)
  values (v_name, 'clinic', now())
  returning id into v_tenant;

  insert into public.tenant_members (tenant_id, user_id, role, status, created_at)
  values (v_tenant, v_uid, 'tenant_admin', 'active', now());

  return v_tenant;
end;
$$;


ALTER FUNCTION "public"."create_clinic_tenant"("p_name" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."create_patient_intake_request"("p_token" "text", "p_name" "text", "p_email" "text" DEFAULT NULL::"text", "p_phone" "text" DEFAULT NULL::"text", "p_notes" "text" DEFAULT NULL::"text", "p_consent" boolean DEFAULT false) RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
declare
  v_owner uuid;
  v_active boolean;
  v_expires timestamptz;
  v_max_uses int;
  v_uses int;
  v_id uuid;
begin
  select owner_id, active, expires_at, max_uses, uses
    into v_owner, v_active, v_expires, v_max_uses, v_uses
  from public.patient_invites
  where token = p_token
  limit 1;

  if v_owner is null then
    raise exception 'Token inválido';
  end if;

  if v_active is not true then
    raise exception 'Link desativado';
  end if;

  if v_expires is not null and now() > v_expires then
    raise exception 'Link expirado';
  end if;

  if v_max_uses is not null and v_uses >= v_max_uses then
    raise exception 'Limite de uso atingido';
  end if;

  if p_name is null or length(trim(p_name)) = 0 then
    raise exception 'Nome é obrigatório';
  end if;

  insert into public.patient_intake_requests
    (owner_id, token, name, email, phone, notes, consent, status)
  values
    (v_owner, p_token, trim(p_name),
     nullif(lower(trim(p_email)), ''),
     nullif(trim(p_phone), ''),
     nullif(trim(p_notes), ''),
     coalesce(p_consent, false),
     'new')
  returning id into v_id;

  update public.patient_invites
    set uses = uses + 1
  where token = p_token;

  return v_id;
end;
$$;


ALTER FUNCTION "public"."create_patient_intake_request"("p_token" "text", "p_name" "text", "p_email" "text", "p_phone" "text", "p_notes" "text", "p_consent" boolean) OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."create_patient_intake_request_v2"("p_token" "text", "p_payload" "jsonb") RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $_$
declare
  v_owner_id uuid;
  v_intake_id uuid;
  v_birth_raw text;
  v_birth date;
begin
  select owner_id
    into v_owner_id
  from public.patient_invites
  where token = p_token;

  if v_owner_id is null then
    raise exception 'Token inválido ou expirado';
  end if;

  v_birth_raw := nullif(trim(coalesce(
    p_payload->>'data_nascimento',
    ''
  )), '');

  v_birth := case
    when v_birth_raw is null then null
    when v_birth_raw ~ '^\d{4}-\d{2}-\d{2}$' then v_birth_raw::date
    when v_birth_raw ~ '^\d{2}-\d{2}-\d{4}$' then to_date(v_birth_raw, 'DD-MM-YYYY')
    else null
  end;

  insert into public.patient_intake_requests (
    owner_id,
    token,
    status,
    consent,

    nome_completo,
    email_principal,
    telefone,

    avatar_url,  -- 🔥 AQUI

    data_nascimento,
    cpf,
    rg,
    genero,
    estado_civil,
    profissao,
    escolaridade,
    nacionalidade,
    naturalidade,

    cep,
    pais,
    cidade,
    estado,
    endereco,
    numero,
    complemento,
    bairro,

    observacoes,
    notas_internas,

    encaminhado_por,
    onde_nos_conheceu
  )
  values (
    v_owner_id,
    p_token,
    'new',
    coalesce((p_payload->>'consent')::boolean, false),

    nullif(trim(p_payload->>'nome_completo'), ''),
    nullif(trim(p_payload->>'email_principal'), ''),
    nullif(regexp_replace(coalesce(p_payload->>'telefone',''), '\D', '', 'g'), ''),

    nullif(trim(p_payload->>'avatar_url'), ''), -- 🔥 AQUI

    v_birth,
    nullif(regexp_replace(coalesce(p_payload->>'cpf',''), '\D', '', 'g'), ''),
    nullif(trim(p_payload->>'rg'), ''),
    nullif(trim(p_payload->>'genero'), ''),
    nullif(trim(p_payload->>'estado_civil'), ''),
    nullif(trim(p_payload->>'profissao'), ''),
    nullif(trim(p_payload->>'escolaridade'), ''),
    nullif(trim(p_payload->>'nacionalidade'), ''),
    nullif(trim(p_payload->>'naturalidade'), ''),

    nullif(regexp_replace(coalesce(p_payload->>'cep',''), '\D', '', 'g'), ''),
    nullif(trim(p_payload->>'pais'), ''),
    nullif(trim(p_payload->>'cidade'), ''),
    nullif(trim(p_payload->>'estado'), ''),
    nullif(trim(p_payload->>'endereco'), ''),
    nullif(trim(p_payload->>'numero'), ''),
    nullif(trim(p_payload->>'complemento'), ''),
    nullif(trim(p_payload->>'bairro'), ''),

    nullif(trim(p_payload->>'observacoes'), ''),
    nullif(trim(p_payload->>'notas_internas'), ''),

    nullif(trim(p_payload->>'encaminhado_por'), ''),
    nullif(trim(p_payload->>'onde_nos_conheceu'), '')
  )
  returning id into v_intake_id;

  return v_intake_id;
end;
$_$;


ALTER FUNCTION "public"."create_patient_intake_request_v2"("p_token" "text", "p_payload" "jsonb") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."current_member_id"("p_tenant_id" "uuid") RETURNS "uuid"
    LANGUAGE "sql" STABLE
    AS $$
  select tm.id
  from public.tenant_members tm
  where tm.tenant_id = p_tenant_id
    and tm.user_id = auth.uid()
  limit 1
$$;


ALTER FUNCTION "public"."current_member_id"("p_tenant_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."current_member_role"("p_tenant_id" "uuid") RETURNS "text"
    LANGUAGE "sql" STABLE
    AS $$
  select tm.role
  from public.tenant_members tm
  where tm.tenant_id = p_tenant_id
    and tm.user_id = auth.uid()
  limit 1
$$;


ALTER FUNCTION "public"."current_member_role"("p_tenant_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."delete_commitment_full"("p_tenant_id" "uuid", "p_commitment_id" "uuid") RETURNS "jsonb"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
declare
  v_is_native boolean;
  v_fields int := 0;
  v_logs int := 0;
  v_parent int := 0;
begin
  if auth.uid() is null then
    raise exception 'Not authenticated';
  end if;

  if not exists (
    select 1
    from public.tenant_members tm
    where tm.tenant_id = p_tenant_id
      and tm.user_id = auth.uid()
      and tm.status = 'active'
  ) then
    raise exception 'Not allowed';
  end if;

  select dc.is_native
    into v_is_native
  from public.determined_commitments dc
  where dc.tenant_id = p_tenant_id
    and dc.id = p_commitment_id;

  if v_is_native is null then
    raise exception 'Commitment not found';
  end if;

  if v_is_native = true then
    raise exception 'Cannot delete native commitment';
  end if;

  delete from public.determined_commitment_fields
   where tenant_id = p_tenant_id
     and commitment_id = p_commitment_id;
  get diagnostics v_fields = row_count;

  delete from public.commitment_time_logs
   where tenant_id = p_tenant_id
     and commitment_id = p_commitment_id;
  get diagnostics v_logs = row_count;

  delete from public.determined_commitments
   where tenant_id = p_tenant_id
     and id = p_commitment_id;
  get diagnostics v_parent = row_count;

  if v_parent <> 1 then
    raise exception 'Parent not deleted (RLS/owner issue).';
  end if;

  return jsonb_build_object(
    'ok', true,
    'deleted', jsonb_build_object(
      'fields', v_fields,
      'logs', v_logs,
      'commitment', v_parent
    )
  );
end;
$$;


ALTER FUNCTION "public"."delete_commitment_full"("p_tenant_id" "uuid", "p_commitment_id" "uuid") OWNER TO "postgres";


CREATE OR REPLACE FUNCTION "public"."delete_determined_commitment"("p_tenant_id" "uuid", "p_commitment_id" "uuid") RETURNS "jsonb"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
declare
  v_is_native boolean;
  v_fields_deleted int := 0;
  v_logs_deleted int := 0;
  v_commitment_deleted int := 0;
begin
  if auth.uid() is null then
    raise exception 'Not authenticated';
  end if;

  if not exists (
    select 1
    from public.tenant_members tm
    where tm.tenant_id = p_tenant_id
      and tm.user_id = auth.uid()
      and tm.status = 'active'
  ) then
    raise exception 'Not allowed';
  end if;

  select dc.is_native
    into v_is_native
  from public.determined_commitments dc
  where dc.tenant_id = p_tenant_id
    and dc.id = p_commitment_id;

  if v_is_native is null then
    raise exception 'Commitment not found for tenant';
  end if;

  if v_is_native = true then
    raise exception 'Cannot delete native commitment';
  end if;

  delete from public.determined_commitment_fields f
   where f.tenant_id = p_tenant_id
     and f.commitment_id = p_commitment_id;
  get diagnostics v_fields_deleted = row_count;

  delete from public.commitment_time_logs l
   where l.tenant_id = p_tenant_id
     and l.commitment_id = p_commitment_id;
  get diagnostics v_logs_deleted = row_count;

  delete from public.determined_commitments dc
   where dc.tenant_id = p_tenant_id
     and dc.id = p_commitment_id;
  get diagnostics v_commitment_deleted = row_count;

  if v_commitment_deleted <> 1 then
    raise exception 'Delete did not remove the commitment (tenant mismatch?)';
  end if;

  return jsonb_build_object(
    'ok', true,
    'tenant_id', p_tenant_id,
    'commitment_id', p_commitment_id,
    'deleted', jsonb_build_object(
      'fields', v_fields_deleted,
      'logs', v_logs_deleted,
      'commitment', v_commitment_deleted
    )
  );
end;
$$;


ALTER FUNCTION "public"."delete_determined_commitment"("p_tenant_id" "uuid", "p_commitment_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."dev_list_auth_users"("p_limit" integer DEFAULT 50) RETURNS TABLE("id" "uuid", "email" "text", "created_at" timestamp with time zone)
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public', 'auth'
    AS $$
begin
  -- só saas_admin pode ver
  if not exists (
    select 1
    from public.profiles p
    where p.id = auth.uid()
      and p.role = 'saas_admin'
  ) then
    return;
  end if;

  return query
  select
    u.id,
    u.email,
    u.created_at
  from auth.users u
  order by u.created_at desc
  limit greatest(1, least(coalesce(p_limit, 50), 500));
end;
$$;


ALTER FUNCTION "public"."dev_list_auth_users"("p_limit" integer) OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."dev_list_custom_users"() RETURNS TABLE("user_id" "uuid", "email" "text", "created_at" timestamp with time zone, "global_role" "text", "tenant_role" "text", "tenant_id" "uuid", "password_dev" "text", "kind" "text")
    LANGUAGE "sql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
  with base as (
    select
      u.id as user_id,
      lower(u.email) as email,
      u.created_at
    from auth.users u
    where lower(u.email) not in (
      'clinic@agenciapsi.com.br',
      'therapist@agenciapsi.com.br',
      'patient@agenciapsi.com.br',
      'saas@agenciapsi.com.br'
    )
  ),
  prof as (
    select p.id, p.role as global_role
    from public.profiles p
  ),
  last_membership as (
    select distinct on (tm.user_id)
      tm.user_id,
      tm.tenant_id,
      tm.role as tenant_role,
      tm.created_at
    from public.tenant_members tm
    where tm.status = 'active'
    order by tm.user_id, tm.created_at desc
  )
  select
    b.user_id,
    b.email,
    b.created_at,
    pr.global_role,
    lm.tenant_role,
    lm.tenant_id,
    dc.password_dev,
    dc.kind
  from base b
  left join prof pr on pr.id = b.user_id
  left join last_membership lm on lm.user_id = b.user_id
  left join public.dev_user_credentials dc on lower(dc.email) = b.email
  order by b.created_at desc;
$$;


ALTER FUNCTION "public"."dev_list_custom_users"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."dev_list_intent_leads"() RETURNS TABLE("email" "text", "last_intent_at" timestamp with time zone, "plan_key" "text", "billing_interval" "text", "status" "text", "tenant_id" "uuid")
    LANGUAGE "sql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
  select
    lower(si.email) as email,
    max(si.created_at) as last_intent_at,
    (array_agg(si.plan_key order by si.created_at desc))[1] as plan_key,
    (array_agg(si.interval order by si.created_at desc))[1] as billing_interval,
    (array_agg(si.status order by si.created_at desc))[1] as status,
    (array_agg(si.tenant_id order by si.created_at desc))[1] as tenant_id
  from public.subscription_intents si
  where si.email is not null
    and not exists (
      select 1
      from auth.users au
      where lower(au.email) = lower(si.email)
    )
  group by lower(si.email)
  order by max(si.created_at) desc;
$$;


ALTER FUNCTION "public"."dev_list_intent_leads"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."dev_public_debug_snapshot"() RETURNS TABLE("users_total" integer, "tenants_total" integer, "intents_new_total" integer, "latest_intents" "jsonb")
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $_$
declare
  v_latest jsonb;
begin
  select jsonb_agg(
    jsonb_build_object(
      'created_at', si.created_at,
      'email_masked',
        regexp_replace(lower(si.email), '(^.).*(@.*$)', '\1***\2'),
      'plan_key', si.plan_key,
      'status', si.status
    )
    order by si.created_at desc
  )
  into v_latest
  from (
    select si.*
    from public.subscription_intents si
    where si.email is not null
    order by si.created_at desc
    limit 5
  ) si;

  return query
  select
    (select count(*)::int from auth.users) as users_total,
    (select count(*)::int from public.tenants) as tenants_total,
    (select count(*)::int from public.subscription_intents where status = 'new') as intents_new_total,
    coalesce(v_latest, '[]'::jsonb) as latest_intents;
end;
$_$;


ALTER FUNCTION "public"."dev_public_debug_snapshot"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."ensure_personal_tenant"() RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
DECLARE
  v_uid      uuid;
  v_existing uuid;
BEGIN
  v_uid := auth.uid();
  IF v_uid IS NULL THEN
    RAISE EXCEPTION 'Not authenticated';
  END IF;

  SELECT tm.tenant_id INTO v_existing
  FROM public.tenant_members tm
  JOIN public.tenants t ON t.id = tm.tenant_id
  WHERE tm.user_id = v_uid
    AND tm.status = 'active'
    AND t.kind IN ('therapist', 'saas')
  ORDER BY tm.created_at DESC
  LIMIT 1;

  IF v_existing IS NOT NULL THEN
    RETURN v_existing;
  END IF;

  RETURN public.provision_account_tenant(v_uid, 'therapist');
END;
$$;


ALTER FUNCTION "public"."ensure_personal_tenant"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."ensure_personal_tenant_for_user"("p_user_id" "uuid") RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_uid uuid;
  v_existing uuid;
  v_tenant uuid;
  v_email text;
  v_name text;
begin
  v_uid := p_user_id;
  if v_uid is null then
    raise exception 'Missing user id';
  end if;

  -- só considera tenant pessoal (kind='saas')
  select tm.tenant_id
    into v_existing
  from public.tenant_members tm
  join public.tenants t on t.id = tm.tenant_id
  where tm.user_id = v_uid
    and tm.status = 'active'
    and t.kind = 'saas'
  order by tm.created_at desc
  limit 1;

  if v_existing is not null then
    return v_existing;
  end if;

  select email into v_email
  from auth.users
  where id = v_uid;

  v_name := coalesce(split_part(v_email, '@', 1), 'Conta');

  insert into public.tenants (name, kind, created_at)
  values (v_name || ' (Pessoal)', 'saas', now())
  returning id into v_tenant;

  insert into public.tenant_members (tenant_id, user_id, role, status, created_at)
  values (v_tenant, v_uid, 'tenant_admin', 'active', now());

  return v_tenant;
end;
$$;


ALTER FUNCTION "public"."ensure_personal_tenant_for_user"("p_user_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."faq_votar"("faq_id" "uuid") RETURNS "void"
    LANGUAGE "sql" SECURITY DEFINER
    AS $$
  update public.saas_faq
  set votos = votos + 1,
      updated_at = now()
  where id = faq_id
    and ativo = true;
$$;


ALTER FUNCTION "public"."faq_votar"("faq_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."fix_all_subscription_mismatches"() RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  r record;
begin
  for r in
    select distinct s.user_id as owner_id
    from public.subscriptions s
    where s.status = 'active'
      and s.user_id is not null
  loop
    perform public.rebuild_owner_entitlements(r.owner_id);
  end loop;
end;
$$;


ALTER FUNCTION "public"."fix_all_subscription_mismatches"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."fn_agenda_regras_semanais_no_overlap"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
declare
  v_count int;
begin
  if new.ativo is false then
    return new;
  end if;

  select count(*) into v_count
  from public.agenda_regras_semanais r
  where r.owner_id = new.owner_id
    and r.dia_semana = new.dia_semana
    and r.ativo is true
    and (tg_op = 'INSERT' or r.id <> new.id)
    and (new.hora_inicio < r.hora_fim and new.hora_fim > r.hora_inicio);

  if v_count > 0 then
    raise exception 'Janela sobreposta: já existe uma regra ativa nesse intervalo.';
  end if;

  return new;
end;
$$;


ALTER FUNCTION "public"."fn_agenda_regras_semanais_no_overlap"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."get_my_email"() RETURNS "text"
    LANGUAGE "sql" SECURITY DEFINER
    SET "search_path" TO 'public', 'auth'
    AS $$
  select lower(email)
  from auth.users
  where id = auth.uid();
$$;


ALTER FUNCTION "public"."get_my_email"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."guard_account_type_immutable"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
BEGIN
  IF OLD.account_type <> 'free' AND NEW.account_type IS DISTINCT FROM OLD.account_type THEN
    RAISE EXCEPTION 'account_type é imutável após escolha (atual: "%" para tentativa: "%"). Para mudar de perfil, crie uma nova conta.', OLD.account_type, NEW.account_type
      USING ERRCODE = 'P0001';
  END IF;
  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."guard_account_type_immutable"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."guard_locked_commitment"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
begin
  if (old.is_locked = true) then
    if (tg_op = 'DELETE') then
      raise exception 'Compromisso bloqueado não pode ser excluído.';
    end if;

    if (tg_op = 'UPDATE') then
      if (new.active = false) then
        raise exception 'Compromisso bloqueado não pode ser desativado.';
      end if;

      -- trava renomear (mantém o "Sessão" sempre igual)
      if (new.name is distinct from old.name) then
        raise exception 'Compromisso bloqueado não pode ser renomeado.';
      end if;

      -- se quiser travar descrição também, descomente:
      -- if (new.description is distinct from old.description) then
      --   raise exception 'Compromisso bloqueado não pode alterar descrição.';
      -- end if;
    end if;
  end if;

  return new;
end;
$$;


ALTER FUNCTION "public"."guard_locked_commitment"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."guard_no_change_core_plan_key"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
begin
  if old.key in ('clinic_free','clinic_pro','therapist_free','therapist_pro')
     and new.key is distinct from old.key then
    raise exception 'Não é permitido alterar a key do plano padrão (%).', old.key
      using errcode = 'P0001';
  end if;

  return new;
end $$;


ALTER FUNCTION "public"."guard_no_change_core_plan_key"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."guard_no_change_plan_target"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
declare
  v_bypass text;
begin
  -- bypass controlado por sessão/transação:
  -- só passa se app.plan_migration_bypass = '1'
  v_bypass := current_setting('app.plan_migration_bypass', true);

  if v_bypass = '1' then
    return new;
  end if;

  -- comportamento original (bloqueia qualquer mudança)
  if new.target is distinct from old.target then
    raise exception 'Não é permitido alterar target do plano (%) de % para %.',
      old.key, old.target, new.target
      using errcode = 'P0001';
  end if;

  return new;
end
$$;


ALTER FUNCTION "public"."guard_no_change_plan_target"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."guard_no_delete_core_plans"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
begin
  if old.key in ('clinic_free','clinic_pro','therapist_free','therapist_pro') then
    raise exception 'Plano padrão (%) não pode ser removido.', old.key
      using errcode = 'P0001';
  end if;

  return old;
end $$;


ALTER FUNCTION "public"."guard_no_delete_core_plans"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."guard_patient_cannot_own_tenant"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
DECLARE
  v_account_type text;
BEGIN
  SELECT account_type INTO v_account_type
  FROM public.profiles
  WHERE id = NEW.user_id;

  IF v_account_type = 'patient' AND NEW.role IN ('tenant_admin', 'therapist') THEN
    RAISE EXCEPTION 'Usuário com perfil "patient" não pode ser proprietário ou terapeuta de um tenant. Se tornou profissional? Crie uma nova conta.'
      USING ERRCODE = 'P0001';
  END IF;

  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."guard_patient_cannot_own_tenant"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."guard_tenant_kind_immutable"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
BEGIN
  IF NEW.kind IS DISTINCT FROM OLD.kind THEN
    RAISE EXCEPTION 'tenants.kind é imutável após criação. Tentativa de alterar "%" para "%".', OLD.kind, NEW.kind
      USING ERRCODE = 'P0001';
  END IF;
  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."guard_tenant_kind_immutable"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."handle_new_user"() RETURNS "trigger"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
BEGIN
  INSERT INTO public.profiles (id, role, account_type)
  VALUES (NEW.id, 'portal_user', 'free')
  ON CONFLICT (id) DO NOTHING;
  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."handle_new_user"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."handle_new_user_create_personal_tenant"() RETURNS "trigger"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
BEGIN
  -- Desabilitado. Tenant criado no onboarding via provision_account_tenant().
  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."handle_new_user_create_personal_tenant"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."has_feature"("p_owner_id" "uuid", "p_feature_key" "text") RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  select exists (
    select 1
    from public.owner_feature_entitlements e
    where e.owner_id = p_owner_id
      and e.feature_key = p_feature_key
  );
$$;


ALTER FUNCTION "public"."has_feature"("p_owner_id" "uuid", "p_feature_key" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."is_clinic_tenant"("_tenant_id" "uuid") RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  SELECT EXISTS (
    SELECT 1 FROM public.tenants t
    WHERE t.id = _tenant_id
      AND t.kind IN ('clinic', 'clinic_coworking', 'clinic_reception', 'clinic_full')
  );
$$;


ALTER FUNCTION "public"."is_clinic_tenant"("_tenant_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."is_saas_admin"() RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  select exists (
    select 1 from public.saas_admins sa
    where sa.user_id = auth.uid()
  );
$$;


ALTER FUNCTION "public"."is_saas_admin"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."is_tenant_admin"("p_tenant_id" "uuid") RETURNS boolean
    LANGUAGE "sql" STABLE SECURITY DEFINER
    SET "search_path" TO 'public'
    SET "row_security" TO 'off'
    AS $$
  select exists (
    select 1
    from public.tenant_members tm
    where tm.tenant_id = p_tenant_id
      and tm.user_id = auth.uid()
      and tm.role = 'tenant_admin'
      and tm.status = 'active'
  );
$$;


ALTER FUNCTION "public"."is_tenant_admin"("p_tenant_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."is_tenant_member"("_tenant_id" "uuid") RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  select exists (
    select 1
    from public.tenant_members m
    where m.tenant_id = _tenant_id
      and m.user_id = auth.uid()
      and m.status = 'active'
  );
$$;


ALTER FUNCTION "public"."is_tenant_member"("_tenant_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."is_therapist_tenant"("_tenant_id" "uuid") RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  SELECT EXISTS (
    SELECT 1 FROM public.tenants t
    WHERE t.id = _tenant_id AND t.kind = 'therapist'
  );
$$;


ALTER FUNCTION "public"."is_therapist_tenant"("_tenant_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."jwt_email"() RETURNS "text"
    LANGUAGE "sql" STABLE
    AS $$
  select nullif(lower(current_setting('request.jwt.claim.email', true)), '');
$$;


ALTER FUNCTION "public"."jwt_email"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."my_tenants"() RETURNS TABLE("tenant_id" "uuid", "role" "text", "status" "text", "kind" "text")
    LANGUAGE "sql" STABLE
    AS $$
  select
    tm.tenant_id,
    tm.role,
    tm.status,
    t.kind
  from public.tenant_members tm
  join public.tenants t on t.id = tm.tenant_id
  where tm.user_id = auth.uid();
$$;


ALTER FUNCTION "public"."my_tenants"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."on_new_user_seed_patient_groups"() RETURNS "trigger"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
  BEGIN
    PERFORM public.seed_default_patient_groups(NEW.id);
    RETURN NEW;
  END;
  $$;


ALTER FUNCTION "public"."on_new_user_seed_patient_groups"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."patients_validate_member_consistency"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
DECLARE
  v_tenant_responsible uuid;
  v_tenant_therapist uuid;
BEGIN
  -- responsible_member sempre deve existir e ser do tenant
  SELECT tenant_id INTO v_tenant_responsible
  FROM public.tenant_members
  WHERE id = NEW.responsible_member_id;

  IF v_tenant_responsible IS NULL THEN
    RAISE EXCEPTION 'Responsible member not found';
  END IF;

  IF NEW.tenant_id IS NULL THEN
    RAISE EXCEPTION 'tenant_id is required';
  END IF;

  IF v_tenant_responsible <> NEW.tenant_id THEN
    RAISE EXCEPTION 'Responsible member must belong to the same tenant';
  END IF;

  -- therapist scope: therapist_member_id deve existir e ser do mesmo tenant
  IF NEW.patient_scope = 'therapist' THEN
    IF NEW.therapist_member_id IS NULL THEN
      RAISE EXCEPTION 'therapist_member_id is required when patient_scope=therapist';
    END IF;

    SELECT tenant_id INTO v_tenant_therapist
    FROM public.tenant_members
    WHERE id = NEW.therapist_member_id;

    IF v_tenant_therapist IS NULL THEN
      RAISE EXCEPTION 'Therapist member not found';
    END IF;

    IF v_tenant_therapist <> NEW.tenant_id THEN
      RAISE EXCEPTION 'Therapist member must belong to the same tenant';
    END IF;
  END IF;

  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."patients_validate_member_consistency"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."patients_validate_responsible_member_tenant"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
declare
  m_tenant uuid;
begin
  select tenant_id into m_tenant
  from public.tenant_members
  where id = new.responsible_member_id;

  if m_tenant is null then
    raise exception 'Responsible member not found';
  end if;

  if new.tenant_id is null then
    raise exception 'tenant_id is required';
  end if;

  if m_tenant <> new.tenant_id then
    raise exception 'Responsible member must belong to the same tenant';
  end if;

  return new;
end;
$$;


ALTER FUNCTION "public"."patients_validate_responsible_member_tenant"() OWNER TO "supabase_admin";


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;
$$;


ALTER FUNCTION "public"."prevent_promoting_to_system"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."prevent_saas_membership"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
BEGIN
  IF EXISTS (
    SELECT 1
    FROM public.profiles
    WHERE id = NEW.user_id
    AND role = 'saas_admin'
  ) THEN
    RAISE EXCEPTION 'SaaS admin cannot belong to tenant';
  END IF;

  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."prevent_saas_membership"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."prevent_system_group_changes"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
begin
  -- Se for grupo do sistema, regras rígidas:
  if old.is_system = true then

    -- nunca pode deletar
    if tg_op = 'DELETE' then
      raise exception 'Grupos padrão do sistema não podem ser alterados ou excluídos.';
    end if;

    if tg_op = 'UPDATE' then
      -- permite SOMENTE mudar tenant_id e/ou updated_at
      -- qualquer mudança de conteúdo permanece proibida
      if
        new.nome         is distinct from old.nome or
        new.descricao    is distinct from old.descricao or
        new.cor          is distinct from old.cor or
        new.is_active    is distinct from old.is_active or
        new.is_system    is distinct from old.is_system or
        new.owner_id     is distinct from old.owner_id or
        new.therapist_id is distinct from old.therapist_id or
        new.created_at   is distinct from old.created_at
      then
        raise exception 'Grupos padrão do sistema não podem ser alterados ou excluídos.';
      end if;

      -- chegou aqui: só tenant_id/updated_at mudaram -> ok
      return new;
    end if;

  end if;

  -- não-system: deixa passar
  if tg_op = 'DELETE' then
    return old;
  end if;

  return new;
end;
$$;


ALTER FUNCTION "public"."prevent_system_group_changes"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."provision_account_tenant"("p_user_id" "uuid", "p_kind" "text", "p_name" "text" DEFAULT NULL::"text") RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
DECLARE
  v_tenant_id    uuid;
  v_account_type text;
  v_name         text;
BEGIN
  IF p_kind NOT IN ('therapist', 'clinic_coworking', 'clinic_reception', 'clinic_full') THEN
    RAISE EXCEPTION 'kind inválido: "%". Use: therapist, clinic_coworking, clinic_reception, clinic_full.', p_kind
      USING ERRCODE = 'P0001';
  END IF;

  v_account_type := CASE WHEN p_kind = 'therapist' THEN 'therapist' ELSE 'clinic' END;

  IF EXISTS (
    SELECT 1
    FROM public.tenant_members tm
    JOIN public.tenants t ON t.id = tm.tenant_id
    WHERE tm.user_id = p_user_id
      AND tm.role = 'tenant_admin'
      AND tm.status = 'active'
      AND t.kind = p_kind
  ) THEN
    RAISE EXCEPTION 'Usuário já possui um tenant do tipo "%".', p_kind
      USING ERRCODE = 'P0001';
  END IF;

  v_name := COALESCE(
    NULLIF(TRIM(p_name), ''),
    (
      SELECT COALESCE(NULLIF(TRIM(pr.full_name), ''), SPLIT_PART(au.email, '@', 1))
      FROM public.profiles pr
      JOIN auth.users au ON au.id = pr.id
      WHERE pr.id = p_user_id
    ),
    'Conta'
  );

  INSERT INTO public.tenants (name, kind, created_at)
  VALUES (v_name, p_kind, now())
  RETURNING id INTO v_tenant_id;

  INSERT INTO public.tenant_members (tenant_id, user_id, role, status, created_at)
  VALUES (v_tenant_id, p_user_id, 'tenant_admin', 'active', now());

  UPDATE public.profiles
  SET account_type = v_account_type
  WHERE id = p_user_id;

  PERFORM public.seed_determined_commitments(v_tenant_id);

  RETURN v_tenant_id;
END;
$$;


ALTER FUNCTION "public"."provision_account_tenant"("p_user_id" "uuid", "p_kind" "text", "p_name" "text") OWNER TO "supabase_admin";


COMMENT ON FUNCTION "public"."provision_account_tenant"("p_user_id" "uuid", "p_kind" "text", "p_name" "text") IS 'Cria o tenant do tipo correto e atualiza account_type no profile. Chamar no onboarding após escolha/pagamento de plano therapist ou clinic. p_kind: therapist | clinic_coworking | clinic_reception | clinic_full';



CREATE OR REPLACE FUNCTION "public"."reactivate_subscription"("p_subscription_id" "uuid") RETURNS "public"."subscriptions"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_sub public.subscriptions;
  v_owner_type text;
  v_owner_ref uuid;
begin

  select *
  into v_sub
  from public.subscriptions
  where id = p_subscription_id
  for update;

  if not found then
    raise exception 'Subscription não encontrada';
  end if;

  if v_sub.status = 'active' then
    return v_sub;
  end if;

  if v_sub.tenant_id is not null then
    v_owner_type := 'clinic';
    v_owner_ref := v_sub.tenant_id;
  elsif v_sub.user_id is not null then
    v_owner_type := 'therapist';
    v_owner_ref := v_sub.user_id;
  else
    v_owner_type := null;
    v_owner_ref := null;
  end if;

  update public.subscriptions
  set status = 'active',
      cancel_at_period_end = false,
      updated_at = now()
  where id = p_subscription_id
  returning * into v_sub;

  insert into public.subscription_events(
    subscription_id,
    owner_id,
    owner_type,
    owner_ref,
    event_type,
    old_plan_id,
    new_plan_id,
    created_by,
    reason,
    source,
    metadata
  )
  values (
    v_sub.id,
    v_owner_ref,
    v_owner_type,
    v_owner_ref,
    'reactivated',
    v_sub.plan_id,
    v_sub.plan_id,
    auth.uid(),
    'Reativação manual via admin',
    'admin_panel',
    jsonb_build_object('previous_status', 'canceled')
  );

  if v_owner_ref is not null then
    insert into public.entitlements_invalidation(owner_id, changed_at)
    values (v_owner_ref, now())
    on conflict (owner_id)
    do update set changed_at = excluded.changed_at;
  end if;

  return v_sub;

end;
$$;


ALTER FUNCTION "public"."reactivate_subscription"("p_subscription_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."rebuild_owner_entitlements"("p_owner_id" "uuid") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_plan_id uuid;
begin
  -- Plano ativo do owner (owner = subscriptions.user_id)
  select s.plan_id
    into v_plan_id
  from public.subscriptions s
  where s.user_id = p_owner_id
    and s.status = 'active'
  order by s.created_at desc
  limit 1;

  -- Sempre zera entitlements do owner (rebuild)
  delete from public.owner_feature_entitlements e
  where e.owner_id = p_owner_id;

  -- Se não tem assinatura ativa, acabou
  if v_plan_id is null then
    return;
  end if;

  -- Recria entitlements esperados pelo plano
  insert into public.owner_feature_entitlements (owner_id, feature_key, sources, limits_list)
  select
    p_owner_id as owner_id,
    f.key as feature_key,
    array['plan'::text] as sources,
    '{}'::jsonb as limits_list
  from public.plan_features pf
  join public.features f on f.id = pf.feature_id
  where pf.plan_id = v_plan_id;

end;
$$;


ALTER FUNCTION "public"."rebuild_owner_entitlements"("p_owner_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."rotate_patient_invite_token"("p_new_token" "text") RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
declare
  v_uid uuid;
  v_id uuid;
begin
  -- pega o usuário logado
  v_uid := auth.uid();
  if v_uid is null then
    raise exception 'Usuário não autenticado';
  end if;

  -- desativa tokens antigos ativos do usuário
  update public.patient_invites
    set active = false
  where owner_id = v_uid
    and active = true;

  -- cria novo token
  insert into public.patient_invites (owner_id, token, active)
  values (v_uid, p_new_token, true)
  returning id into v_id;

  return v_id;
end;
$$;


ALTER FUNCTION "public"."rotate_patient_invite_token"("p_new_token" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."saas_votar_doc"("p_doc_id" "uuid", "p_util" boolean) RETURNS "jsonb"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_uid         uuid := auth.uid();
  v_voto_antigo boolean;
begin
  if v_uid is null then
    raise exception 'Não autenticado';
  end if;

  -- Verifica se já votou
  select util into v_voto_antigo
  from public.saas_doc_votos
  where doc_id = p_doc_id and user_id = v_uid;

  if found then
    -- Já votou igual → cancela o voto (toggle)
    if v_voto_antigo = p_util then
      delete from public.saas_doc_votos
      where doc_id = p_doc_id and user_id = v_uid;

      update public.saas_docs set
        votos_util     = greatest(0, votos_util     - (case when p_util  then 1 else 0 end)),
        votos_nao_util = greatest(0, votos_nao_util - (case when not p_util then 1 else 0 end)),
        updated_at = now()
      where id = p_doc_id;

      return jsonb_build_object('acao', 'removido', 'util', null);
    else
      -- Mudou de voto
      update public.saas_doc_votos set util = p_util, updated_at = now()
      where doc_id = p_doc_id and user_id = v_uid;

      update public.saas_docs set
        votos_util     = greatest(0, votos_util     + (case when p_util  then 1 else -1 end)),
        votos_nao_util = greatest(0, votos_nao_util + (case when not p_util then 1 else -1 end)),
        updated_at = now()
      where id = p_doc_id;

      return jsonb_build_object('acao', 'atualizado', 'util', p_util);
    end if;
  else
    -- Primeiro voto
    insert into public.saas_doc_votos (doc_id, user_id, util)
    values (p_doc_id, v_uid, p_util);

    update public.saas_docs set
      votos_util     = votos_util     + (case when p_util  then 1 else 0 end),
      votos_nao_util = votos_nao_util + (case when not p_util then 1 else 0 end),
      updated_at = now()
    where id = p_doc_id;

    return jsonb_build_object('acao', 'registrado', 'util', p_util);
  end if;
end;
$$;


ALTER FUNCTION "public"."saas_votar_doc"("p_doc_id" "uuid", "p_util" boolean) OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."seed_determined_commitments"("p_tenant_id" "uuid") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_id uuid;
begin
  -- Sessão (locked + sempre ativa)
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'session'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'session', true, true, 'Sessão', 'Sessão com paciente');
  end if;

  -- Leitura
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'reading'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'reading', false, true, 'Leitura', 'Praticar leitura');
  end if;

  -- Supervisão
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'supervision'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'supervision', false, true, 'Supervisão', 'Supervisão');
  end if;

  -- Aula ✅ (corrigido)
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'class'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'class', false, false, 'Aula', 'Dar aula');
  end if;

  -- Análise pessoal
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'analysis'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'analysis', false, true, 'Análise Pessoal', 'Minha análise pessoal');
  end if;

  -- -------------------------------------------------------
  -- Campos padrão (idempotentes por (commitment_id, key))
  -- -------------------------------------------------------

  -- Leitura
  select id into v_id
  from public.determined_commitments
  where tenant_id = p_tenant_id and is_native = true and native_key = 'reading'
  limit 1;

  if v_id is not null then
    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'book') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'book', 'Livro', 'text', false, 10);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'author') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'author', 'Autor', 'text', false, 20);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'notes') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'notes', 'Observação', 'textarea', false, 30);
    end if;
  end if;

  -- Supervisão
  select id into v_id
  from public.determined_commitments
  where tenant_id = p_tenant_id and is_native = true and native_key = 'supervision'
  limit 1;

  if v_id is not null then
    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'supervisor') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'supervisor', 'Supervisor', 'text', false, 10);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'topic') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'topic', 'Assunto', 'text', false, 20);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'notes') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'notes', 'Observação', 'textarea', false, 30);
    end if;
  end if;

  -- Aula
  select id into v_id
  from public.determined_commitments
  where tenant_id = p_tenant_id and is_native = true and native_key = 'class'
  limit 1;

  if v_id is not null then
    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'theme') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'theme', 'Tema', 'text', false, 10);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'group') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'group', 'Turma', 'text', false, 20);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'notes') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'notes', 'Observação', 'textarea', false, 30);
    end if;
  end if;

  -- Análise
  select id into v_id
  from public.determined_commitments
  where tenant_id = p_tenant_id and is_native = true and native_key = 'analysis'
  limit 1;

  if v_id is not null then
    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'analyst') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'analyst', 'Analista', 'text', false, 10);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'focus') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'focus', 'Foco', 'text', false, 20);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'notes') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'notes', 'Observação', 'textarea', false, 30);
    end if;
  end if;
end;
$$;


ALTER FUNCTION "public"."seed_determined_commitments"("p_tenant_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."set_owner_id"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
begin
  if new.owner_id is null then
    new.owner_id := auth.uid();
  end if;
  return new;
end;
$$;


ALTER FUNCTION "public"."set_owner_id"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."set_tenant_feature_exception"("p_tenant_id" "uuid", "p_feature_key" "text", "p_enabled" boolean, "p_reason" "text" DEFAULT NULL::"text") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
begin
  -- ✅ Só owner ou admin do tenant podem alterar features
  if not exists (
    select 1 from public.tenant_members
    where tenant_id = p_tenant_id
      and user_id = auth.uid()
      and role in ('owner', 'admin')
      and status = 'active'
  ) then
    raise exception 'Acesso negado: apenas owner/admin pode alterar features do tenant.';
  end if;

  insert into public.tenant_features (tenant_id, feature_key, enabled)
  values (p_tenant_id, p_feature_key, p_enabled)
  on conflict (tenant_id, feature_key)
  do update set enabled = excluded.enabled;

  insert into public.tenant_feature_exceptions_log (
    tenant_id, feature_key, enabled, reason, created_by
  ) values (
    p_tenant_id, p_feature_key, p_enabled, p_reason, auth.uid()
  );
end;
$$;


ALTER FUNCTION "public"."set_tenant_feature_exception"("p_tenant_id" "uuid", "p_feature_key" "text", "p_enabled" boolean, "p_reason" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."set_updated_at"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
begin
  new.updated_at = now();
  return new;
end;
$$;


ALTER FUNCTION "public"."set_updated_at"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."set_updated_at_recurrence"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
BEGIN NEW.updated_at = now(); RETURN NEW; END;
$$;


ALTER FUNCTION "public"."set_updated_at_recurrence"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."split_recurrence_at"("p_recurrence_id" "uuid", "p_from_date" "date") RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
DECLARE
  v_old   public.recurrence_rules;
  v_new_id uuid;
BEGIN
  -- busca a regra original
  SELECT * INTO v_old
  FROM public.recurrence_rules
  WHERE id = p_recurrence_id;

  IF NOT FOUND THEN
    RAISE EXCEPTION 'recurrence_rule % não encontrada', p_recurrence_id;
  END IF;

  -- encerra a regra antiga na data anterior
  UPDATE public.recurrence_rules
  SET
    end_date   = p_from_date - INTERVAL '1 day',
    open_ended = false,
    updated_at = now()
  WHERE id = p_recurrence_id;

  -- cria nova regra a partir de p_from_date
  INSERT INTO public.recurrence_rules (
    tenant_id, owner_id, therapist_id, patient_id,
    determined_commitment_id, type, interval, weekdays,
    start_time, end_time, timezone, duration_min,
    start_date, end_date, max_occurrences, open_ended,
    modalidade, titulo_custom, observacoes, extra_fields, status
  )
  SELECT
    tenant_id, owner_id, therapist_id, patient_id,
    determined_commitment_id, type, interval, weekdays,
    start_time, end_time, timezone, duration_min,
    p_from_date, v_old.end_date, v_old.max_occurrences, v_old.open_ended,
    modalidade, titulo_custom, observacoes, extra_fields, status
  FROM public.recurrence_rules
  WHERE id = p_recurrence_id
  RETURNING id INTO v_new_id;

  RETURN v_new_id;
END;
$$;


ALTER FUNCTION "public"."split_recurrence_at"("p_recurrence_id" "uuid", "p_from_date" "date") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."subscription_intents_view_insert"() RETURNS "trigger"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_target text;
  v_plan_id uuid;
begin
  select p.id, p.target into v_plan_id, v_target
  from public.plans p
  where p.key = new.plan_key;

  if v_plan_id is null then
    raise exception 'Plano inválido: plan_key=%', new.plan_key;
  end if;

  if lower(v_target) = 'clinic' then
    if new.tenant_id is null then
      raise exception 'Intenção clinic exige tenant_id.';
    end if;

    insert into public.subscription_intents_tenant (
      id, tenant_id, created_by_user_id, email,
      plan_id, plan_key, interval, amount_cents, currency,
      status, source, notes, created_at, paid_at
    ) values (
      coalesce(new.id, gen_random_uuid()),
      new.tenant_id, new.created_by_user_id, new.email,
      v_plan_id, new.plan_key, coalesce(new.interval,'month'),
      new.amount_cents, coalesce(new.currency,'BRL'),
      coalesce(new.status,'pending'), coalesce(new.source,'manual'),
      new.notes, coalesce(new.created_at, now()), new.paid_at
    );

    new.plan_target := 'clinic';
    return new;
  end if;

  -- therapist ou supervisor → tabela personal
  if lower(v_target) in ('therapist', 'supervisor') then
    insert into public.subscription_intents_personal (
      id, user_id, created_by_user_id, email,
      plan_id, plan_key, interval, amount_cents, currency,
      status, source, notes, created_at, paid_at
    ) values (
      coalesce(new.id, gen_random_uuid()),
      new.user_id, new.created_by_user_id, new.email,
      v_plan_id, new.plan_key, coalesce(new.interval,'month'),
      new.amount_cents, coalesce(new.currency,'BRL'),
      coalesce(new.status,'pending'), coalesce(new.source,'manual'),
      new.notes, coalesce(new.created_at, now()), new.paid_at
    );

    new.plan_target := lower(v_target); -- 'therapist' ou 'supervisor'
    return new;
  end if;

  raise exception 'Target de plano não suportado: %', v_target;
end;
$$;


ALTER FUNCTION "public"."subscription_intents_view_insert"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."subscriptions_validate_scope"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
DECLARE
  v_target text;
BEGIN
  SELECT lower(p.target) INTO v_target
  FROM public.plans p
  WHERE p.id = NEW.plan_id;

  IF v_target IS NULL THEN
    RAISE EXCEPTION 'Plano inválido (target nulo).';
  END IF;

  IF v_target = 'clinic' THEN
    IF NEW.tenant_id IS NULL THEN
      RAISE EXCEPTION 'Assinatura clinic exige tenant_id.';
    END IF;
    IF NEW.user_id IS NOT NULL THEN
      RAISE EXCEPTION 'Assinatura clinic não pode ter user_id (XOR).';
    END IF;

  ELSIF v_target IN ('therapist', 'supervisor') THEN
    -- supervisor é pessoal como therapist
    IF NEW.tenant_id IS NOT NULL THEN
      RAISE EXCEPTION 'Assinatura % não deve ter tenant_id.', v_target;
    END IF;
    IF NEW.user_id IS NULL THEN
      RAISE EXCEPTION 'Assinatura % exige user_id.', v_target;
    END IF;

  ELSIF v_target = 'patient' THEN
    IF NEW.tenant_id IS NOT NULL THEN
      RAISE EXCEPTION 'Assinatura patient não deve ter tenant_id.';
    END IF;
    IF NEW.user_id IS NULL THEN
      RAISE EXCEPTION 'Assinatura patient exige user_id.';
    END IF;

  ELSE
    RAISE EXCEPTION 'Target de plano inválido: %', v_target;
  END IF;

  RETURN NEW;
END;
$$;


ALTER FUNCTION "public"."subscriptions_validate_scope"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."sync_busy_mirror_agenda_eventos"() RETURNS "trigger"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    AS $$
declare
  clinic_tenant uuid;
  is_personal boolean;
  should_mirror boolean;
begin
  -- Anti-recursão: espelho não espelha
  if (tg_op <> 'DELETE') then
    if new.mirror_of_event_id is not null then
      return new;
    end if;
  else
    if old.mirror_of_event_id is not null then
      return old;
    end if;
  end if;

  -- Define se é pessoal e se deve espelhar
  if (tg_op = 'DELETE') then
    is_personal := (old.tenant_id = old.owner_id);
    should_mirror := (old.visibility_scope in ('busy_only','private'));
  else
    is_personal := (new.tenant_id = new.owner_id);
    should_mirror := (new.visibility_scope in ('busy_only','private'));
  end if;

  -- Se não é pessoal, não faz nada
  if not is_personal then
    if (tg_op = 'DELETE') then
      return old;
    end if;
    return new;
  end if;

  -- DELETE: remove espelhos existentes
  if (tg_op = 'DELETE') then
    delete from public.agenda_eventos e
    where e.mirror_of_event_id = old.id
      and e.mirror_source = 'personal_busy_mirror';

    return old;
  end if;

  -- INSERT/UPDATE:
  -- Se não deve espelhar, remove espelhos e sai
  if not should_mirror then
    delete from public.agenda_eventos e
    where e.mirror_of_event_id = new.id
      and e.mirror_source = 'personal_busy_mirror';

    return new;
  end if;

  -- Para cada clínica onde o usuário é therapist active, cria/atualiza o "Ocupado"
  for clinic_tenant in
    select tm.tenant_id
    from public.tenant_members tm
    where tm.user_id = new.owner_id
      and tm.role = 'therapist'
      and tm.status = 'active'
      and tm.tenant_id <> new.owner_id
  loop
    insert into public.agenda_eventos (
      tenant_id,
      owner_id,
      terapeuta_id,
      paciente_id,
      tipo,
      status,
      titulo,
      observacoes,
      inicio_em,
      fim_em,
      mirror_of_event_id,
      mirror_source,
      visibility_scope,
      created_at,
      updated_at
    ) values (
      clinic_tenant,
      new.owner_id,
      new.owner_id,
      null,
      'bloqueio'::public.tipo_evento_agenda,
      'agendado'::public.status_evento_agenda,
      'Ocupado',
      null,
      new.inicio_em,
      new.fim_em,
      new.id,
      'personal_busy_mirror',
      'public',
      now(),
      now()
    )
    on conflict (tenant_id, mirror_of_event_id) where mirror_of_event_id is not null
    do update set
      owner_id = excluded.owner_id,
      terapeuta_id = excluded.terapeuta_id,
      tipo = excluded.tipo,
      status = excluded.status,
      titulo = excluded.titulo,
      observacoes = excluded.observacoes,
      inicio_em = excluded.inicio_em,
      fim_em = excluded.fim_em,
      updated_at = now();
  end loop;

  -- Limpa espelhos de clínicas onde o vínculo therapist active não existe mais
  delete from public.agenda_eventos e
  where e.mirror_of_event_id = new.id
    and e.mirror_source = 'personal_busy_mirror'
    and not exists (
      select 1
      from public.tenant_members tm
      where tm.user_id = new.owner_id
        and tm.role = 'therapist'
        and tm.status = 'active'
        and tm.tenant_id = e.tenant_id
    );

  return new;
end;
$$;


ALTER FUNCTION "public"."sync_busy_mirror_agenda_eventos"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_accept_invite"("p_token" "uuid") RETURNS "jsonb"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public', 'auth'
    AS $$
declare
  v_uid uuid;
  v_email text;
  v_invite public.tenant_invites%rowtype;
begin
  -- 1) precisa estar autenticado
  v_uid := auth.uid();
  if v_uid is null then
    raise exception 'not_authenticated' using errcode = 'P0001';
  end if;

  -- 2) pega email real do usuário logado sem depender do JWT claim
  select u.email
    into v_email
  from auth.users u
  where u.id = v_uid;

  if v_email is null or length(trim(v_email)) = 0 then
    raise exception 'missing_user_email' using errcode = 'P0001';
  end if;

  -- 3) carrega o invite e trava linha (evita 2 aceites concorrentes)
  select *
    into v_invite
  from public.tenant_invites i
  where i.token = p_token
  for update;

  if not found then
    raise exception 'invite_not_found' using errcode = 'P0001';
  end if;

  -- 4) validações de estado
  if v_invite.revoked_at is not null then
    raise exception 'invite_revoked' using errcode = 'P0001';
  end if;

  if v_invite.accepted_at is not null then
    raise exception 'invite_already_accepted' using errcode = 'P0001';
  end if;

  if v_invite.expires_at is not null and v_invite.expires_at <= now() then
    raise exception 'invite_expired' using errcode = 'P0001';
  end if;

  -- 5) valida email (case-insensitive)
  if lower(trim(v_invite.email)) <> lower(trim(v_email)) then
    raise exception 'email_mismatch' using errcode = 'P0001';
  end if;

  -- 6) consome o invite
  update public.tenant_invites
  set accepted_at = now(),
      accepted_by = v_uid
  where id = v_invite.id;

  -- 7) cria ou reativa o membership
  insert into public.tenant_members (tenant_id, user_id, role, status, created_at)
  values (v_invite.tenant_id, v_uid, v_invite.role, 'active', now())
  on conflict (tenant_id, user_id)
  do update set
    role = excluded.role,
    status = 'active';

  -- 8) retorno útil pro front (você já tenta ler tenant_id no AcceptInvitePage)
  return jsonb_build_object(
    'ok', true,
    'tenant_id', v_invite.tenant_id,
    'role', v_invite.role
  );
end;
$$;


ALTER FUNCTION "public"."tenant_accept_invite"("p_token" "uuid") OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."tenant_members" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    "user_id" "uuid" NOT NULL,
    "role" "text" NOT NULL,
    "status" "text" DEFAULT 'active'::"text" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."tenant_members" OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_add_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text" DEFAULT 'therapist'::"text") RETURNS "public"."tenant_members"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public', 'auth'
    AS $$
declare
  v_target_uid uuid;
  v_member public.tenant_members%rowtype;
  v_is_admin boolean;
  v_email text;
begin
  if p_tenant_id is null then
    raise exception 'tenant_id é obrigatório';
  end if;

  v_email := lower(trim(coalesce(p_email, '')));
  if v_email = '' then
    raise exception 'email é obrigatório';
  end if;

  -- valida role permitida
  if p_role not in ('tenant_admin','therapist','secretary','patient') then
    raise exception 'role inválida: %', p_role;
  end if;

  -- apenas admin do tenant (role real no banco)
  select exists (
    select 1
    from public.tenant_members tm
    where tm.tenant_id = p_tenant_id
      and tm.user_id = auth.uid()
      and tm.role = 'tenant_admin'
      and coalesce(tm.status,'active') = 'active'
  ) into v_is_admin;

  if not v_is_admin then
    raise exception 'sem permissão: apenas admin da clínica pode adicionar membros';
  end if;

  -- acha usuário pelo e-mail no Supabase Auth
  select u.id
  into v_target_uid
  from auth.users u
  where lower(u.email) = v_email
  limit 1;

  if v_target_uid is null then
    raise exception 'nenhum usuário encontrado com este e-mail';
  end if;

  -- cria ou reativa membro
  insert into public.tenant_members (tenant_id, user_id, role, status)
  values (p_tenant_id, v_target_uid, p_role, 'active')
  on conflict (tenant_id, user_id)
  do update set
    role = excluded.role,
    status = 'active'
  returning * into v_member;

  return v_member;
end;
$$;


ALTER FUNCTION "public"."tenant_add_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_feature_allowed"("p_tenant_id" "uuid", "p_feature_key" "text") RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  select exists (
    select 1
    from public.v_tenant_entitlements v
    where v.tenant_id = p_tenant_id
      and v.feature_key = p_feature_key
      and coalesce(v.allowed, false) = true
  );
$$;


ALTER FUNCTION "public"."tenant_feature_allowed"("p_tenant_id" "uuid", "p_feature_key" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_feature_enabled"("p_tenant_id" "uuid", "p_feature_key" "text") RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  select coalesce(
    (select tf.enabled
     from public.tenant_features tf
     where tf.tenant_id = p_tenant_id and tf.feature_key = p_feature_key),
    false
  );
$$;


ALTER FUNCTION "public"."tenant_feature_enabled"("p_tenant_id" "uuid", "p_feature_key" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_features_guard_with_plan"() RETURNS "trigger"
    LANGUAGE "plpgsql"
    AS $$
declare
  v_allowed boolean;
begin
  -- só valida quando está habilitando
  if new.enabled is distinct from true then
    return new;
  end if;

  -- permitido pelo plano do tenant?
  select exists (
    select 1
    from public.v_tenant_entitlements_full v
    where v.tenant_id = new.tenant_id
      and v.feature_key = new.feature_key
      and v.allowed = true
  )
  into v_allowed;

  if not v_allowed then
    raise exception 'Feature % não permitida pelo plano atual do tenant %.',
      new.feature_key, new.tenant_id
      using errcode = 'P0001';
  end if;

  return new;
end;
$$;


ALTER FUNCTION "public"."tenant_features_guard_with_plan"() OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_has_feature"("_tenant_id" "uuid", "_feature" "text") RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  select
    exists (
      select 1
      from public.v_tenant_entitlements e
      where e.tenant_id = _tenant_id
        and e.feature_key = _feature
        and e.allowed = true
    )
    or exists (
      select 1
      from public.tenant_features tf
      where tf.tenant_id = _tenant_id
        and tf.feature_key = _feature
        and tf.enabled = true
    );
$$;


ALTER FUNCTION "public"."tenant_has_feature"("_tenant_id" "uuid", "_feature" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_invite_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") RETURNS "uuid"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public', 'auth'
    AS $$
declare
  v_email text;
  v_my_email text;
  v_token uuid;
  v_updated int;
begin
  -- validações básicas
  if p_tenant_id is null then
    raise exception 'tenant_id inválido' using errcode = 'P0001';
  end if;

  v_email := lower(trim(coalesce(p_email, '')));
  if v_email = '' then
    raise exception 'Informe um email' using errcode = 'P0001';
  end if;

  -- role permitido (ajuste se quiser)
  if p_role is null or p_role not in ('therapist', 'secretary') then
    raise exception 'Role inválido (use therapist/secretary)' using errcode = 'P0001';
  end if;

  -- ✅ bloqueio: auto-convite
  v_my_email := public.get_my_email();
  if v_my_email is not null and v_email = v_my_email then
    raise exception 'Você não pode convidar o seu próprio email.' using errcode = 'P0001';
  end if;

  -- ✅ bloqueio: já é membro ativo do tenant
  if exists (
    select 1
    from tenant_members tm
    join auth.users au on au.id = tm.user_id
    where tm.tenant_id = p_tenant_id
      and tm.status = 'active'
      and lower(au.email) = v_email
  ) then
    raise exception 'Este email já está vinculado a esta clínica.' using errcode = 'P0001';
  end if;

  -- ✅ permissão: só admin do tenant pode convidar
  if not exists (
    select 1
    from tenant_members me
    where me.tenant_id = p_tenant_id
      and me.user_id = auth.uid()
      and me.status = 'active'
      and me.role in ('tenant_admin','clinic_admin')
  ) then
    raise exception 'Sem permissão para convidar membros.' using errcode = 'P0001';
  end if;

  -- Gera token (reenvio simples / regeneração)
  v_token := gen_random_uuid();

  -- 1) tenta "regerar" um convite pendente existente (mesmo email)
  update tenant_invites
     set token = v_token,
         role = p_role,
         created_at = now(),
         expires_at = now() + interval '7 days',
         accepted_at = null,
         revoked_at = null
   where tenant_id = p_tenant_id
     and lower(email) = v_email
     and accepted_at is null
     and revoked_at is null;

  get diagnostics v_updated = row_count;

  -- 2) se não atualizou nada, cria convite novo
  if v_updated = 0 then
    insert into tenant_invites (tenant_id, email, role, token, created_at, expires_at)
    values (p_tenant_id, v_email, p_role, v_token, now(), now() + interval '7 days');
  end if;

  return v_token;
end;
$$;


ALTER FUNCTION "public"."tenant_invite_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_reactivate_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    SET "row_security" TO 'off'
    AS $$
begin
  if auth.uid() is null then
    raise exception 'not_authenticated';
  end if;

  if not public.is_tenant_admin(p_tenant_id) then
    raise exception 'not_allowed';
  end if;

  update public.tenant_members
     set status = 'active'
   where tenant_id = p_tenant_id
     and user_id = p_member_user_id;

  if not found then
    raise exception 'membership_not_found';
  end if;
end;
$$;


ALTER FUNCTION "public"."tenant_reactivate_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_remove_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    SET "row_security" TO 'off'
    AS $$
declare
  v_role text;
begin
  if auth.uid() is null then
    raise exception 'not_authenticated';
  end if;

  if not public.is_tenant_admin(p_tenant_id) then
    raise exception 'not_allowed';
  end if;

  if p_member_user_id = auth.uid() then
    raise exception 'cannot_remove_self';
  end if;

  -- pega role atual do membro (se não existir, erro)
  select role into v_role
  from public.tenant_members
  where tenant_id = p_tenant_id
    and user_id = p_member_user_id;

  if v_role is null then
    raise exception 'membership_not_found';
  end if;

  -- trava: se for therapist, não pode remover com eventos futuros
  if v_role = 'therapist' then
    if exists (
      select 1
      from public.agenda_eventos e
      where e.owner_id = p_tenant_id
        and e.terapeuta_id = p_member_user_id
        and e.inicio_em >= now()
        and e.status::text not in ('cancelado','cancelled','canceled')
      limit 1
    ) then
      raise exception 'cannot_remove_therapist_with_future_events';
    end if;
  end if;

  update public.tenant_members
     set status = 'inactive'
   where tenant_id = p_tenant_id
     and user_id = p_member_user_id;

  if not found then
    raise exception 'membership_not_found';
  end if;
end;
$$;


ALTER FUNCTION "public"."tenant_remove_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_remove_member_soft"("p_tenant_id" "uuid", "p_member_user_id" "uuid") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    SET "row_security" TO 'off'
    AS $$
begin
  if auth.uid() is null then
    raise exception 'not_authenticated';
  end if;

  if not public.is_tenant_admin(p_tenant_id) then
    raise exception 'not_allowed';
  end if;

  if p_member_user_id = auth.uid() then
    raise exception 'cannot_remove_self';
  end if;

  update public.tenant_members
     set status = 'inactive'
   where tenant_id = p_tenant_id
     and user_id = p_member_user_id;

  if not found then
    raise exception 'membership_not_found';
  end if;
end;
$$;


ALTER FUNCTION "public"."tenant_remove_member_soft"("p_tenant_id" "uuid", "p_member_user_id" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_revoke_invite"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    SET "row_security" TO 'off'
    AS $$
declare
  v_email text;
begin
  if auth.uid() is null then
    raise exception 'not_authenticated';
  end if;

  if not public.is_tenant_admin(p_tenant_id) then
    raise exception 'not_allowed';
  end if;

  v_email := lower(trim(p_email));

  update public.tenant_invites
     set revoked_at = now(),
         revoked_by = auth.uid()
   where tenant_id = p_tenant_id
     and lower(email) = v_email
     and role = p_role
     and accepted_at is null
     and revoked_at is null;

  if not found then
    raise exception 'invite_not_found';
  end if;
end;
$$;


ALTER FUNCTION "public"."tenant_revoke_invite"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_set_member_status"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_status" "text") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    SET "row_security" TO 'off'
    AS $$
begin
  if auth.uid() is null then
    raise exception 'not_authenticated';
  end if;

  -- valida status (adapte aos seus valores reais)
  if p_new_status not in ('active','inactive','suspended','invited') then
    raise exception 'invalid_status: %', p_new_status;
  end if;

  if not public.is_tenant_admin(p_tenant_id) then
    raise exception 'not_allowed';
  end if;

  -- evita desativar a si mesmo (opcional)
  if p_member_user_id = auth.uid() and p_new_status <> 'active' then
    raise exception 'cannot_disable_self';
  end if;

  update public.tenant_members
     set status = p_new_status
   where tenant_id = p_tenant_id
     and user_id = p_member_user_id;

  if not found then
    raise exception 'membership_not_found';
  end if;
end;
$$;


ALTER FUNCTION "public"."tenant_set_member_status"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_status" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."tenant_update_member_role"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_role" "text") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    SET "search_path" TO 'public'
    SET "row_security" TO 'off'
    AS $$
begin
  -- exige auth
  if auth.uid() is null then
    raise exception 'not_authenticated';
  end if;

  -- valida role
  if p_new_role not in ('tenant_admin','therapist','secretary','patient') then
    raise exception 'invalid_role: %', p_new_role;
  end if;

  -- somente tenant_admin ativo pode alterar role
  if not public.is_tenant_admin(p_tenant_id) then
    raise exception 'not_allowed';
  end if;

  -- evita o admin remover o próprio admin sem querer (opcional mas recomendado)
  if p_member_user_id = auth.uid() and p_new_role <> 'tenant_admin' then
    raise exception 'cannot_demote_self';
  end if;

  update public.tenant_members
     set role = p_new_role
   where tenant_id = p_tenant_id
     and user_id = p_member_user_id;

  if not found then
    raise exception 'membership_not_found';
  end if;
end;
$$;


ALTER FUNCTION "public"."tenant_update_member_role"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_role" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."toggle_plan"("owner" "uuid") RETURNS "void"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  current_key text;
  new_key text;
begin
  select p.key into current_key
  from subscriptions s
  join plans p on p.id = s.plan_id
  where s.owner_id = owner
    and s.status = 'active';

  new_key := case
    when current_key = 'pro' then 'free'
    else 'pro'
  end;

  update subscriptions s
  set plan_id = p.id
  from plans p
  where p.key = new_key
    and s.owner_id = owner
    and s.status = 'active';
end;
$$;


ALTER FUNCTION "public"."toggle_plan"("owner" "uuid") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."transition_subscription"("p_subscription_id" "uuid", "p_to_status" "text", "p_reason" "text" DEFAULT NULL::"text", "p_metadata" "jsonb" DEFAULT NULL::"jsonb") RETURNS "public"."subscriptions"
    LANGUAGE "plpgsql" SECURITY DEFINER
    AS $$
declare
  v_sub public.subscriptions;
  v_uid uuid;
  v_is_allowed boolean := false;
begin
  v_uid := auth.uid();

  select *
    into v_sub
  from public.subscriptions
  where id = p_subscription_id;

  if not found then
    raise exception 'Assinatura não encontrada';
  end if;

  -- =====================================================
  -- 🔐 BLOCO DE AUTORIZAÇÃO
  -- =====================================================

  -- 1) SaaS admin pode tudo
  if is_saas_admin() then
    v_is_allowed := true;
  end if;

  -- 2) Assinatura pessoal (therapist)
  if not v_is_allowed
     and v_sub.tenant_id is null
     and v_sub.user_id = v_uid then
    v_is_allowed := true;
  end if;

  -- 3) Assinatura de clinic (tenant)
  if not v_is_allowed
     and v_sub.tenant_id is not null then

    if exists (
      select 1
      from public.tenant_members tm
      where tm.tenant_id = v_sub.tenant_id
        and tm.user_id = v_uid
        and tm.status = 'active'
        and tm.role = 'tenant_admin'
    ) then
      v_is_allowed := true;
    end if;

  end if;

  if not v_is_allowed then
    raise exception 'Sem permissão para transicionar esta assinatura';
  end if;

  -- =====================================================
  -- 🧠 TRANSIÇÃO
  -- =====================================================

  update public.subscriptions
  set status = p_to_status,
      updated_at = now(),
      cancelled_at = case when p_to_status = 'cancelled' then now() else cancelled_at end,
      suspended_at = case when p_to_status = 'suspended' then now() else suspended_at end,
      past_due_since = case when p_to_status = 'past_due' then now() else past_due_since end,
      expired_at = case when p_to_status = 'expired' then now() else expired_at end,
      activated_at = case when p_to_status = 'active' then now() else activated_at end
  where id = p_subscription_id
  returning * into v_sub;

  -- =====================================================
  -- 🧾 EVENT LOG
  -- =====================================================

  insert into public.subscription_events (
    subscription_id,
    owner_id,
    event_type,
    created_at,
    created_by,
    source,
    reason,
    metadata,
    owner_type,
    owner_ref
  )
  values (
    v_sub.id,
    coalesce(v_sub.tenant_id, v_sub.user_id),
    'status_changed',
    now(),
    v_uid,
    'manual_transition',
    p_reason,
    p_metadata,
    case when v_sub.tenant_id is not null then 'tenant' else 'personal' end,
    coalesce(v_sub.tenant_id, v_sub.user_id)
  );

  return v_sub;
end;
$$;


ALTER FUNCTION "public"."transition_subscription"("p_subscription_id" "uuid", "p_to_status" "text", "p_reason" "text", "p_metadata" "jsonb") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."user_has_feature"("_user_id" "uuid", "_feature" "text") RETURNS boolean
    LANGUAGE "sql" STABLE
    AS $$
  select exists (
    select 1
    from public.v_user_entitlements e
    where e.user_id = _user_id
      and e.feature_key = _feature
      and e.allowed = true
  );
$$;


ALTER FUNCTION "public"."user_has_feature"("_user_id" "uuid", "_feature" "text") OWNER TO "supabase_admin";


CREATE OR REPLACE FUNCTION "public"."whoami"() RETURNS TABLE("uid" "uuid", "role" "text")
    LANGUAGE "sql" STABLE
    AS $$
  select auth.uid() as uid, auth.role() as role;
$$;


ALTER FUNCTION "public"."whoami"() OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agenda_bloqueios" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "tenant_id" "uuid",
    "tipo" "text" NOT NULL,
    "titulo" "text" NOT NULL,
    "data_inicio" "date" NOT NULL,
    "data_fim" "date",
    "hora_inicio" time without time zone,
    "hora_fim" time without time zone,
    "recorrente" boolean DEFAULT false NOT NULL,
    "dia_semana" smallint,
    "observacao" "text",
    "origem" "text" DEFAULT 'manual'::"text" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    CONSTRAINT "agenda_bloqueios_tipo_check" CHECK (("tipo" = ANY (ARRAY['feriado_nacional'::"text", 'feriado_municipal'::"text", 'bloqueio'::"text"])))
);


ALTER TABLE "public"."agenda_bloqueios" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agenda_configuracoes" (
    "owner_id" "uuid" NOT NULL,
    "duracao_padrao_minutos" integer DEFAULT 50 NOT NULL,
    "intervalo_padrao_minutos" integer DEFAULT 0 NOT NULL,
    "timezone" "text" DEFAULT 'America/Sao_Paulo'::"text" NOT NULL,
    "usar_horario_admin_custom" boolean DEFAULT false NOT NULL,
    "admin_inicio_visualizacao" time without time zone,
    "admin_fim_visualizacao" time without time zone,
    "admin_slot_visual_minutos" integer DEFAULT 30 NOT NULL,
    "online_ativo" boolean DEFAULT false NOT NULL,
    "online_min_antecedencia_horas" integer DEFAULT 24 NOT NULL,
    "online_max_dias_futuro" integer DEFAULT 60 NOT NULL,
    "online_cancelar_ate_horas" integer DEFAULT 12 NOT NULL,
    "online_reagendar_ate_horas" integer DEFAULT 12 NOT NULL,
    "online_limite_agendamentos_futuros" integer DEFAULT 1 NOT NULL,
    "online_modo" "text" DEFAULT 'automatico'::"text" NOT NULL,
    "online_buffer_antes_min" integer DEFAULT 0 NOT NULL,
    "online_buffer_depois_min" integer DEFAULT 0 NOT NULL,
    "online_modalidade" "text" DEFAULT 'ambos'::"text" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "usar_granularidade_custom" boolean DEFAULT false NOT NULL,
    "granularidade_min" integer,
    "setup_concluido" boolean DEFAULT false NOT NULL,
    "setup_concluido_em" timestamp with time zone,
    "agenda_view_mode" "text" DEFAULT 'full_24h'::"text" NOT NULL,
    "agenda_custom_start" time without time zone,
    "agenda_custom_end" time without time zone,
    "session_duration_min" integer DEFAULT 50 NOT NULL,
    "session_break_min" integer DEFAULT 10 NOT NULL,
    "pausas_semanais" "jsonb" DEFAULT '[]'::"jsonb" NOT NULL,
    "setup_clinica_concluido" boolean DEFAULT false NOT NULL,
    "setup_clinica_concluido_em" timestamp with time zone,
    "tenant_id" "uuid",
    "jornada_igual_todos" boolean DEFAULT true,
    CONSTRAINT "agenda_configuracoes_admin_slot_visual_minutos_check" CHECK (("admin_slot_visual_minutos" = ANY (ARRAY[5, 10, 15, 20, 30, 60]))),
    CONSTRAINT "agenda_configuracoes_check" CHECK ((("usar_horario_admin_custom" = false) OR (("admin_inicio_visualizacao" IS NOT NULL) AND ("admin_fim_visualizacao" IS NOT NULL) AND ("admin_fim_visualizacao" > "admin_inicio_visualizacao")))),
    CONSTRAINT "agenda_configuracoes_duracao_padrao_minutos_check" CHECK ((("duracao_padrao_minutos" >= 10) AND ("duracao_padrao_minutos" <= 240))),
    CONSTRAINT "agenda_configuracoes_granularidade_min_check" CHECK ((("granularidade_min" IS NULL) OR ("granularidade_min" = ANY (ARRAY[5, 10, 15, 20, 30, 45, 50, 60])))),
    CONSTRAINT "agenda_configuracoes_intervalo_padrao_minutos_check" CHECK ((("intervalo_padrao_minutos" >= 0) AND ("intervalo_padrao_minutos" <= 120))),
    CONSTRAINT "agenda_configuracoes_online_buffer_antes_min_check" CHECK ((("online_buffer_antes_min" >= 0) AND ("online_buffer_antes_min" <= 120))),
    CONSTRAINT "agenda_configuracoes_online_buffer_depois_min_check" CHECK ((("online_buffer_depois_min" >= 0) AND ("online_buffer_depois_min" <= 120))),
    CONSTRAINT "agenda_configuracoes_online_cancelar_ate_horas_check" CHECK ((("online_cancelar_ate_horas" >= 0) AND ("online_cancelar_ate_horas" <= 720))),
    CONSTRAINT "agenda_configuracoes_online_limite_agendamentos_futuros_check" CHECK ((("online_limite_agendamentos_futuros" >= 1) AND ("online_limite_agendamentos_futuros" <= 10))),
    CONSTRAINT "agenda_configuracoes_online_max_dias_futuro_check" CHECK ((("online_max_dias_futuro" >= 1) AND ("online_max_dias_futuro" <= 365))),
    CONSTRAINT "agenda_configuracoes_online_min_antecedencia_horas_check" CHECK ((("online_min_antecedencia_horas" >= 0) AND ("online_min_antecedencia_horas" <= 720))),
    CONSTRAINT "agenda_configuracoes_online_modalidade_check" CHECK (("online_modalidade" = ANY (ARRAY['online'::"text", 'presencial'::"text", 'ambos'::"text"]))),
    CONSTRAINT "agenda_configuracoes_online_modo_check" CHECK (("online_modo" = ANY (ARRAY['automatico'::"text", 'aprovacao'::"text"]))),
    CONSTRAINT "agenda_configuracoes_online_reagendar_ate_horas_check" CHECK ((("online_reagendar_ate_horas" >= 0) AND ("online_reagendar_ate_horas" <= 720))),
    CONSTRAINT "session_break_min_chk" CHECK ((("session_break_min" >= 0) AND ("session_break_min" <= 60))),
    CONSTRAINT "session_duration_min_chk" CHECK ((("session_duration_min" >= 10) AND ("session_duration_min" <= 240)))
);


ALTER TABLE "public"."agenda_configuracoes" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agenda_eventos" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "paciente_id" "uuid",
    "tipo" "public"."tipo_evento_agenda" DEFAULT 'sessao'::"public"."tipo_evento_agenda" NOT NULL,
    "status" "public"."status_evento_agenda" DEFAULT 'agendado'::"public"."status_evento_agenda" NOT NULL,
    "titulo" "text",
    "observacoes" "text",
    "inicio_em" timestamp with time zone NOT NULL,
    "fim_em" timestamp with time zone NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "terapeuta_id" "uuid",
    "tenant_id" "uuid" NOT NULL,
    "visibility_scope" "text" DEFAULT 'public'::"text" NOT NULL,
    "mirror_of_event_id" "uuid",
    "mirror_source" "text",
    "patient_id" "uuid",
    "determined_commitment_id" "uuid",
    "link_online" "text",
    "titulo_custom" "text",
    "extra_fields" "jsonb",
    "recurrence_id" "uuid",
    "recurrence_date" "date",
    "modalidade" "text" DEFAULT 'presencial'::"text",
    CONSTRAINT "agenda_eventos_check" CHECK (("fim_em" > "inicio_em"))
);


ALTER TABLE "public"."agenda_eventos" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agenda_excecoes" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "data" "date" NOT NULL,
    "hora_inicio" time without time zone,
    "hora_fim" time without time zone,
    "tipo" "public"."tipo_excecao_agenda" NOT NULL,
    "motivo" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "status" "public"."status_excecao_agenda" DEFAULT 'ativo'::"public"."status_excecao_agenda" NOT NULL,
    "fonte" "text" DEFAULT 'manual'::"text" NOT NULL,
    "aplicavel_online" boolean DEFAULT true NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    CONSTRAINT "agenda_excecoes_check" CHECK (((("hora_inicio" IS NULL) AND ("hora_fim" IS NULL)) OR (("hora_inicio" IS NOT NULL) AND ("hora_fim" IS NOT NULL) AND ("hora_fim" > "hora_inicio")))),
    CONSTRAINT "agenda_excecoes_fonte_check" CHECK (("fonte" = ANY (ARRAY['manual'::"text", 'feriado_google'::"text", 'sistema'::"text"])))
);


ALTER TABLE "public"."agenda_excecoes" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agenda_online_slots" (
    "id" bigint NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "weekday" integer NOT NULL,
    "time" time without time zone NOT NULL,
    "enabled" boolean DEFAULT true NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    CONSTRAINT "agenda_online_slots_weekday_check" CHECK (("weekday" = ANY (ARRAY[0, 1, 2, 3, 4, 5, 6])))
);


ALTER TABLE "public"."agenda_online_slots" OWNER TO "supabase_admin";


CREATE SEQUENCE IF NOT EXISTS "public"."agenda_online_slots_id_seq"
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER SEQUENCE "public"."agenda_online_slots_id_seq" OWNER TO "supabase_admin";


ALTER SEQUENCE "public"."agenda_online_slots_id_seq" OWNED BY "public"."agenda_online_slots"."id";



CREATE TABLE IF NOT EXISTS "public"."agenda_regras_semanais" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "dia_semana" smallint NOT NULL,
    "hora_inicio" time without time zone NOT NULL,
    "hora_fim" time without time zone NOT NULL,
    "modalidade" "text" DEFAULT 'ambos'::"text" NOT NULL,
    "ativo" boolean DEFAULT true NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    CONSTRAINT "agenda_regras_semanais_check" CHECK (("hora_fim" > "hora_inicio")),
    CONSTRAINT "agenda_regras_semanais_dia_semana_check" CHECK ((("dia_semana" >= 0) AND ("dia_semana" <= 6))),
    CONSTRAINT "agenda_regras_semanais_modalidade_check" CHECK ((("modalidade" = ANY (ARRAY['online'::"text", 'presencial'::"text", 'ambos'::"text"])) OR ("modalidade" IS NULL)))
);


ALTER TABLE "public"."agenda_regras_semanais" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agenda_slots_bloqueados_semanais" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "dia_semana" smallint NOT NULL,
    "hora_inicio" time without time zone NOT NULL,
    "motivo" "text",
    "ativo" boolean DEFAULT true NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    CONSTRAINT "agenda_slots_bloqueados_semanais_dia_semana_check" CHECK ((("dia_semana" >= 0) AND ("dia_semana" <= 6)))
);


ALTER TABLE "public"."agenda_slots_bloqueados_semanais" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agenda_slots_regras" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "dia_semana" smallint NOT NULL,
    "passo_minutos" integer NOT NULL,
    "offset_minutos" integer DEFAULT 0 NOT NULL,
    "buffer_antes_min" integer DEFAULT 0 NOT NULL,
    "buffer_depois_min" integer DEFAULT 0 NOT NULL,
    "min_antecedencia_horas" integer DEFAULT 0 NOT NULL,
    "ativo" boolean DEFAULT true NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    CONSTRAINT "agenda_slots_regras_buffer_antes_min_check" CHECK ((("buffer_antes_min" >= 0) AND ("buffer_antes_min" <= 240))),
    CONSTRAINT "agenda_slots_regras_buffer_depois_min_check" CHECK ((("buffer_depois_min" >= 0) AND ("buffer_depois_min" <= 240))),
    CONSTRAINT "agenda_slots_regras_dia_semana_check" CHECK ((("dia_semana" >= 0) AND ("dia_semana" <= 6))),
    CONSTRAINT "agenda_slots_regras_min_antecedencia_horas_check" CHECK ((("min_antecedencia_horas" >= 0) AND ("min_antecedencia_horas" <= 720))),
    CONSTRAINT "agenda_slots_regras_offset_minutos_check" CHECK ((("offset_minutos" >= 0) AND ("offset_minutos" <= 55))),
    CONSTRAINT "agenda_slots_regras_passo_minutos_check" CHECK ((("passo_minutos" >= 5) AND ("passo_minutos" <= 240)))
);


ALTER TABLE "public"."agenda_slots_regras" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agendador_configuracoes" (
    "owner_id" "uuid" NOT NULL,
    "tenant_id" "uuid",
    "ativo" boolean DEFAULT false NOT NULL,
    "link_slug" "text",
    "imagem_fundo_url" "text",
    "imagem_header_url" "text",
    "logomarca_url" "text",
    "cor_primaria" "text" DEFAULT '#4b6bff'::"text",
    "nome_exibicao" "text",
    "endereco" "text",
    "botao_como_chegar_ativo" boolean DEFAULT true NOT NULL,
    "maps_url" "text",
    "modo_aprovacao" "text" DEFAULT 'aprovacao'::"text" NOT NULL,
    "modalidade" "text" DEFAULT 'presencial'::"text" NOT NULL,
    "tipos_habilitados" "jsonb" DEFAULT '["primeira", "retorno"]'::"jsonb" NOT NULL,
    "duracao_sessao_min" integer DEFAULT 50 NOT NULL,
    "antecedencia_minima_horas" integer DEFAULT 24 NOT NULL,
    "prazo_resposta_horas" integer DEFAULT 2 NOT NULL,
    "reserva_horas" integer DEFAULT 2 NOT NULL,
    "pagamento_obrigatorio" boolean DEFAULT false NOT NULL,
    "pix_chave" "text",
    "pix_countdown_minutos" integer DEFAULT 20 NOT NULL,
    "triagem_motivo" boolean DEFAULT true NOT NULL,
    "triagem_como_conheceu" boolean DEFAULT false NOT NULL,
    "verificacao_email" boolean DEFAULT false NOT NULL,
    "exigir_aceite_lgpd" boolean DEFAULT true NOT NULL,
    "mensagem_boas_vindas" "text",
    "texto_como_se_preparar" "text",
    "texto_termos_lgpd" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    CONSTRAINT "agendador_configuracoes_antecedencia_check" CHECK ((("antecedencia_minima_horas" >= 0) AND ("antecedencia_minima_horas" <= 720))),
    CONSTRAINT "agendador_configuracoes_duracao_check" CHECK ((("duracao_sessao_min" >= 10) AND ("duracao_sessao_min" <= 240))),
    CONSTRAINT "agendador_configuracoes_modalidade_check" CHECK (("modalidade" = ANY (ARRAY['presencial'::"text", 'online'::"text", 'ambos'::"text"]))),
    CONSTRAINT "agendador_configuracoes_modo_check" CHECK (("modo_aprovacao" = ANY (ARRAY['automatico'::"text", 'aprovacao'::"text"]))),
    CONSTRAINT "agendador_configuracoes_pix_countdown_check" CHECK ((("pix_countdown_minutos" >= 5) AND ("pix_countdown_minutos" <= 120))),
    CONSTRAINT "agendador_configuracoes_prazo_check" CHECK ((("prazo_resposta_horas" >= 1) AND ("prazo_resposta_horas" <= 72))),
    CONSTRAINT "agendador_configuracoes_reserva_check" CHECK ((("reserva_horas" >= 1) AND ("reserva_horas" <= 48)))
);


ALTER TABLE "public"."agendador_configuracoes" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."agendador_solicitacoes" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "tenant_id" "uuid",
    "paciente_nome" "text" NOT NULL,
    "paciente_sobrenome" "text",
    "paciente_email" "text" NOT NULL,
    "paciente_celular" "text",
    "paciente_cpf" "text",
    "tipo" "text" NOT NULL,
    "modalidade" "text" NOT NULL,
    "data_solicitada" "date" NOT NULL,
    "hora_solicitada" time without time zone NOT NULL,
    "reservado_ate" timestamp with time zone,
    "motivo" "text",
    "como_conheceu" "text",
    "pix_status" "text" DEFAULT 'pendente'::"text",
    "pix_pago_em" timestamp with time zone,
    "status" "text" DEFAULT 'pendente'::"text" NOT NULL,
    "recusado_motivo" "text",
    "autorizado_em" timestamp with time zone,
    "autorizado_por" "uuid",
    "user_id" "uuid",
    "patient_id" "uuid",
    "evento_id" "uuid",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    CONSTRAINT "agendador_sol_modalidade_check" CHECK (("modalidade" = ANY (ARRAY['presencial'::"text", 'online'::"text"]))),
    CONSTRAINT "agendador_sol_pix_check" CHECK ((("pix_status" IS NULL) OR ("pix_status" = ANY (ARRAY['pendente'::"text", 'pago'::"text", 'expirado'::"text"])))),
    CONSTRAINT "agendador_sol_status_check" CHECK (("status" = ANY (ARRAY['pendente'::"text", 'autorizado'::"text", 'recusado'::"text", 'expirado'::"text", 'convertido'::"text"]))),
    CONSTRAINT "agendador_sol_tipo_check" CHECK (("tipo" = ANY (ARRAY['primeira'::"text", 'retorno'::"text", 'reagendar'::"text"])))
);


ALTER TABLE "public"."agendador_solicitacoes" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."commitment_time_logs" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    "commitment_id" "uuid" NOT NULL,
    "calendar_event_id" "uuid",
    "source" "public"."commitment_log_source" DEFAULT 'manual'::"public"."commitment_log_source" NOT NULL,
    "started_at" timestamp with time zone NOT NULL,
    "ended_at" timestamp with time zone NOT NULL,
    "minutes" integer NOT NULL,
    "created_by" "uuid",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."commitment_time_logs" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."current_tenant_id" AS
 SELECT "current_setting"('request.jwt.claim.tenant_id'::"text", true) AS "current_setting";


ALTER VIEW "public"."current_tenant_id" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."determined_commitment_fields" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    "commitment_id" "uuid" NOT NULL,
    "key" "text" NOT NULL,
    "label" "text" NOT NULL,
    "field_type" "public"."determined_field_type" DEFAULT 'text'::"public"."determined_field_type" NOT NULL,
    "required" boolean DEFAULT false NOT NULL,
    "sort_order" integer DEFAULT 0 NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."determined_commitment_fields" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."determined_commitments" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    "created_by" "uuid",
    "is_native" boolean DEFAULT false NOT NULL,
    "native_key" "text",
    "is_locked" boolean DEFAULT false NOT NULL,
    "active" boolean DEFAULT true NOT NULL,
    "name" "text" NOT NULL,
    "description" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "bg_color" "text",
    "text_color" "text"
);


ALTER TABLE "public"."determined_commitments" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."dev_user_credentials" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "user_id" "uuid",
    "email" "text" NOT NULL,
    "password_dev" "text" NOT NULL,
    "kind" "text" DEFAULT 'custom'::"text" NOT NULL,
    "note" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."dev_user_credentials" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."entitlements_invalidation" (
    "owner_id" "uuid" NOT NULL,
    "changed_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."entitlements_invalidation" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."features" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "key" "text" NOT NULL,
    "description" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "descricao" "text" DEFAULT ''::"text" NOT NULL,
    "name" "text" DEFAULT ''::"text" NOT NULL
);


ALTER TABLE "public"."features" OWNER TO "supabase_admin";


COMMENT ON COLUMN "public"."features"."descricao" IS 'Descrição humana da feature (exibição no admin e documentação).';



CREATE TABLE IF NOT EXISTS "public"."feriados" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "tenant_id" "uuid",
    "owner_id" "uuid",
    "tipo" "text" DEFAULT 'municipal'::"text" NOT NULL,
    "nome" "text" NOT NULL,
    "data" "date" NOT NULL,
    "cidade" "text",
    "estado" "text",
    "observacao" "text",
    "bloqueia_sessoes" boolean DEFAULT false NOT NULL,
    "criado_em" timestamp with time zone DEFAULT "now"() NOT NULL,
    CONSTRAINT "feriados_tipo_check" CHECK (("tipo" = ANY (ARRAY['municipal'::"text", 'personalizado'::"text"])))
);


ALTER TABLE "public"."feriados" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."module_features" (
    "module_id" "uuid" NOT NULL,
    "feature_id" "uuid" NOT NULL,
    "enabled" boolean DEFAULT true NOT NULL,
    "limits" "jsonb",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."module_features" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."modules" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "key" "text" NOT NULL,
    "name" "text" NOT NULL,
    "description" "text",
    "is_active" boolean DEFAULT true NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."modules" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."plan_features" (
    "plan_id" "uuid" NOT NULL,
    "feature_id" "uuid" NOT NULL,
    "enabled" boolean DEFAULT true NOT NULL,
    "limits" "jsonb",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."plan_features" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."tenant_modules" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "module_id" "uuid" NOT NULL,
    "status" "text" DEFAULT 'active'::"text" NOT NULL,
    "settings" "jsonb",
    "provider" "text" DEFAULT 'manual'::"text" NOT NULL,
    "provider_item_id" "text",
    "installed_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."tenant_modules" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."owner_feature_entitlements" AS
 WITH "base" AS (
         SELECT "s"."user_id" AS "owner_id",
            "f"."key" AS "feature_key",
            "pf"."limits",
            'plan'::"text" AS "source"
           FROM (("public"."subscriptions" "s"
             JOIN "public"."plan_features" "pf" ON ((("pf"."plan_id" = "s"."plan_id") AND ("pf"."enabled" = true))))
             JOIN "public"."features" "f" ON (("f"."id" = "pf"."feature_id")))
          WHERE (("s"."status" = 'active'::"text") AND ("s"."user_id" IS NOT NULL))
        UNION ALL
         SELECT "tm"."owner_id",
            "f"."key" AS "feature_key",
            "mf"."limits",
            'module'::"text" AS "source"
           FROM ((("public"."tenant_modules" "tm"
             JOIN "public"."modules" "m" ON ((("m"."id" = "tm"."module_id") AND ("m"."is_active" = true))))
             JOIN "public"."module_features" "mf" ON ((("mf"."module_id" = "m"."id") AND ("mf"."enabled" = true))))
             JOIN "public"."features" "f" ON (("f"."id" = "mf"."feature_id")))
          WHERE (("tm"."status" = 'active'::"text") AND ("tm"."owner_id" IS NOT NULL))
        )
 SELECT "owner_id",
    "feature_key",
    "array_agg"(DISTINCT "source") AS "sources",
    "jsonb_agg"("limits") FILTER (WHERE ("limits" IS NOT NULL)) AS "limits_list"
   FROM "base"
  GROUP BY "owner_id", "feature_key";


ALTER VIEW "public"."owner_feature_entitlements" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."owner_users" (
    "owner_id" "uuid" NOT NULL,
    "user_id" "uuid" NOT NULL,
    "role" "text" DEFAULT 'admin'::"text" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."owner_users" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."patient_group_patient" (
    "patient_group_id" "uuid" NOT NULL,
    "patient_id" "uuid" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"(),
    "tenant_id" "uuid" NOT NULL
);


ALTER TABLE "public"."patient_group_patient" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."patient_groups" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "nome" "text" NOT NULL,
    "descricao" "text",
    "cor" "text",
    "is_active" boolean DEFAULT true NOT NULL,
    "is_system" boolean DEFAULT false NOT NULL,
    "owner_id" "uuid" DEFAULT "auth"."uid"() NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "therapist_id" "uuid",
    "tenant_id" "uuid" NOT NULL
);


ALTER TABLE "public"."patient_groups" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."patient_intake_requests" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "token" "text" NOT NULL,
    "consent" boolean DEFAULT false NOT NULL,
    "status" "text" DEFAULT 'new'::"text" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "converted_patient_id" "uuid",
    "rejected_reason" "text",
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "cpf" "text",
    "rg" "text",
    "cep" "text",
    "nome_completo" "text",
    "email_principal" "text",
    "telefone" "text",
    "pais" "text",
    "cidade" "text",
    "estado" "text",
    "endereco" "text",
    "numero" "text",
    "bairro" "text",
    "complemento" "text",
    "data_nascimento" "date",
    "naturalidade" "text",
    "genero" "text",
    "estado_civil" "text",
    "onde_nos_conheceu" "text",
    "encaminhado_por" "text",
    "observacoes" "text",
    "notas_internas" "text",
    "email_alternativo" "text",
    "telefone_alternativo" "text",
    "profissao" "text",
    "escolaridade" "text",
    "nacionalidade" "text",
    "avatar_url" "text",
    "tenant_id" "uuid",
    CONSTRAINT "chk_intakes_status" CHECK (("status" = ANY (ARRAY['new'::"text", 'converted'::"text", 'rejected'::"text"])))
);


ALTER TABLE "public"."patient_intake_requests" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."patient_invites" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "token" "text" NOT NULL,
    "active" boolean DEFAULT true NOT NULL,
    "expires_at" timestamp with time zone,
    "max_uses" integer,
    "uses" integer DEFAULT 0 NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "tenant_id" "uuid"
);


ALTER TABLE "public"."patient_invites" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."patient_patient_tag" (
    "owner_id" "uuid" NOT NULL,
    "patient_id" "uuid" NOT NULL,
    "tag_id" "uuid" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "tenant_id" "uuid" NOT NULL
);


ALTER TABLE "public"."patient_patient_tag" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."patient_tags" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "nome" "text" NOT NULL,
    "cor" "text",
    "is_padrao" boolean DEFAULT false NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone,
    "tenant_id" "uuid" NOT NULL
);


ALTER TABLE "public"."patient_tags" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."patients" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "nome_completo" "text" NOT NULL,
    "email_principal" "text",
    "telefone" "text",
    "created_at" timestamp with time zone DEFAULT "now"(),
    "owner_id" "uuid",
    "avatar_url" "text",
    "status" "text" DEFAULT 'Ativo'::"text",
    "last_attended_at" timestamp with time zone,
    "is_native" boolean DEFAULT false,
    "naturalidade" "text",
    "data_nascimento" "date",
    "rg" "text",
    "cpf" "text",
    "identification_color" "text",
    "genero" "text",
    "estado_civil" "text",
    "email_alternativo" "text",
    "pais" "text" DEFAULT 'Brasil'::"text",
    "cep" "text",
    "cidade" "text",
    "estado" "text",
    "endereco" "text",
    "numero" "text",
    "bairro" "text",
    "complemento" "text",
    "escolaridade" "text",
    "profissao" "text",
    "nome_parente" "text",
    "grau_parentesco" "text",
    "telefone_alternativo" "text",
    "onde_nos_conheceu" "text",
    "encaminhado_por" "text",
    "nome_responsavel" "text",
    "telefone_responsavel" "text",
    "cpf_responsavel" "text",
    "observacao_responsavel" "text",
    "cobranca_no_responsavel" boolean DEFAULT false,
    "observacoes" "text",
    "notas_internas" "text",
    "updated_at" timestamp with time zone DEFAULT "now"(),
    "telefone_parente" "text",
    "tenant_id" "uuid" NOT NULL,
    "responsible_member_id" "uuid" NOT NULL,
    "user_id" "uuid",
    "patient_scope" "text" DEFAULT 'clinic'::"text" NOT NULL,
    "therapist_member_id" "uuid",
    CONSTRAINT "cpf_responsavel_format_check" CHECK ((("cpf_responsavel" IS NULL) OR ("cpf_responsavel" ~ '^\d{11}$'::"text"))),
    CONSTRAINT "patients_cpf_format_check" CHECK ((("cpf" IS NULL) OR ("cpf" ~ '^\d{11}$'::"text"))),
    CONSTRAINT "patients_patient_scope_check" CHECK (("patient_scope" = ANY (ARRAY['clinic'::"text", 'therapist'::"text"]))),
    CONSTRAINT "patients_status_check" CHECK (("status" = ANY (ARRAY['Ativo'::"text", 'Inativo'::"text", 'Alta'::"text", 'Encaminhado'::"text"]))),
    CONSTRAINT "patients_therapist_scope_consistency" CHECK (((("patient_scope" = 'clinic'::"text") AND ("therapist_member_id" IS NULL)) OR (("patient_scope" = 'therapist'::"text") AND ("therapist_member_id" IS NOT NULL))))
);


ALTER TABLE "public"."patients" OWNER TO "supabase_admin";


COMMENT ON COLUMN "public"."patients"."avatar_url" IS 'URL pública da imagem de avatar armazenada no Supabase Storage';



CREATE TABLE IF NOT EXISTS "public"."plan_prices" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "plan_id" "uuid" NOT NULL,
    "currency" "text" DEFAULT 'BRL'::"text" NOT NULL,
    "interval" "text" NOT NULL,
    "amount_cents" integer NOT NULL,
    "is_active" boolean DEFAULT true NOT NULL,
    "active_from" timestamp with time zone DEFAULT "now"() NOT NULL,
    "active_to" timestamp with time zone,
    "source" "text" DEFAULT 'manual'::"text" NOT NULL,
    "provider" "text",
    "provider_price_id" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    CONSTRAINT "plan_prices_amount_cents_check" CHECK (("amount_cents" >= 0)),
    CONSTRAINT "plan_prices_interval_check" CHECK (("interval" = ANY (ARRAY['month'::"text", 'year'::"text"])))
);


ALTER TABLE "public"."plan_prices" OWNER TO "supabase_admin";


COMMENT ON TABLE "public"."plan_prices" IS 'Histórico de preços por plano (fonte: manual/gateway).';



CREATE TABLE IF NOT EXISTS "public"."plan_public" (
    "plan_id" "uuid" NOT NULL,
    "public_name" "text" DEFAULT ''::"text" NOT NULL,
    "public_description" "text" DEFAULT ''::"text" NOT NULL,
    "badge" "text",
    "is_featured" boolean DEFAULT false NOT NULL,
    "is_visible" boolean DEFAULT true NOT NULL,
    "sort_order" integer DEFAULT 0 NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."plan_public" OWNER TO "supabase_admin";


COMMENT ON TABLE "public"."plan_public" IS 'Configuração de vitrine (página pública) dos planos.';



CREATE TABLE IF NOT EXISTS "public"."plan_public_bullets" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "plan_id" "uuid" NOT NULL,
    "text" "text" NOT NULL,
    "sort_order" integer DEFAULT 0 NOT NULL,
    "highlight" boolean DEFAULT false NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."plan_public_bullets" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."plans" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "key" "text" NOT NULL,
    "name" "text" NOT NULL,
    "description" "text",
    "is_active" boolean DEFAULT true NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "price_cents" integer DEFAULT 0 NOT NULL,
    "currency" "text" DEFAULT 'BRL'::"text" NOT NULL,
    "billing_interval" "text" DEFAULT 'month'::"text" NOT NULL,
    "target" "text",
    "max_supervisees" integer,
    CONSTRAINT "plans_target_check" CHECK (("target" = ANY (ARRAY['patient'::"text", 'therapist'::"text", 'clinic'::"text", 'supervisor'::"text"])))
);


ALTER TABLE "public"."plans" OWNER TO "supabase_admin";


COMMENT ON COLUMN "public"."plans"."name" IS 'Nome interno do plano (admin). A key é técnica/imutável.';



COMMENT ON COLUMN "public"."plans"."target" IS 'Público-alvo do plano: patient, therapist ou clinic.';



COMMENT ON COLUMN "public"."plans"."max_supervisees" IS 'Limite de terapeutas que podem ser supervisionados. Apenas para planos target=supervisor. NULL = sem limite.';



CREATE TABLE IF NOT EXISTS "public"."profiles" (
    "id" "uuid" NOT NULL,
    "role" "text" DEFAULT 'tenant_member'::"text" NOT NULL,
    "full_name" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "avatar_url" "text",
    "phone" "text",
    "bio" "text",
    "language" "text" DEFAULT 'pt-BR'::"text" NOT NULL,
    "timezone" "text" DEFAULT 'America/Sao_Paulo'::"text" NOT NULL,
    "notify_system_email" boolean DEFAULT true NOT NULL,
    "notify_reminders" boolean DEFAULT true NOT NULL,
    "notify_news" boolean DEFAULT false NOT NULL,
    "account_type" "text" DEFAULT 'free'::"text" NOT NULL,
    "platform_roles" "text"[] DEFAULT '{}'::"text"[] NOT NULL,
    CONSTRAINT "profiles_account_type_check" CHECK (("account_type" = ANY (ARRAY['free'::"text", 'patient'::"text", 'therapist'::"text", 'clinic'::"text"]))),
    CONSTRAINT "profiles_role_check" CHECK (("role" = ANY (ARRAY['saas_admin'::"text", 'tenant_member'::"text", 'portal_user'::"text", 'patient'::"text"])))
);


ALTER TABLE "public"."profiles" OWNER TO "supabase_admin";


COMMENT ON COLUMN "public"."profiles"."account_type" IS 'Tipo de conta: free=sem perfil ainda, patient=paciente (imutável), therapist=terapeuta (imutável), clinic=clínica (imutável).';



COMMENT ON COLUMN "public"."profiles"."platform_roles" IS 'Papéis globais de plataforma, independentes de tenant. Ex: editor de microlearning. Atribuído pelo saas_admin.';



CREATE TABLE IF NOT EXISTS "public"."recurrence_exceptions" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "recurrence_id" "uuid" NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    "original_date" "date" NOT NULL,
    "type" "public"."recurrence_exception_type" NOT NULL,
    "new_date" "date",
    "new_start_time" time without time zone,
    "new_end_time" time without time zone,
    "modalidade" "text",
    "observacoes" "text",
    "titulo_custom" "text",
    "extra_fields" "jsonb",
    "reason" "text",
    "agenda_evento_id" "uuid",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."recurrence_exceptions" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."recurrence_rules" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "therapist_id" "uuid",
    "patient_id" "uuid",
    "determined_commitment_id" "uuid",
    "type" "public"."recurrence_type" DEFAULT 'weekly'::"public"."recurrence_type" NOT NULL,
    "interval" smallint DEFAULT 1 NOT NULL,
    "weekdays" smallint[] DEFAULT '{}'::smallint[] NOT NULL,
    "start_time" time without time zone NOT NULL,
    "end_time" time without time zone NOT NULL,
    "timezone" "text" DEFAULT 'America/Sao_Paulo'::"text" NOT NULL,
    "duration_min" smallint DEFAULT 50 NOT NULL,
    "start_date" "date" NOT NULL,
    "end_date" "date",
    "max_occurrences" integer,
    "open_ended" boolean DEFAULT true NOT NULL,
    "modalidade" "text" DEFAULT 'presencial'::"text",
    "titulo_custom" "text",
    "observacoes" "text",
    "extra_fields" "jsonb",
    "status" "text" DEFAULT 'ativo'::"text" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    CONSTRAINT "recurrence_rules_dates_chk" CHECK ((("end_date" IS NULL) OR ("end_date" >= "start_date"))),
    CONSTRAINT "recurrence_rules_interval_chk" CHECK (("interval" >= 1)),
    CONSTRAINT "recurrence_rules_status_check" CHECK (("status" = ANY (ARRAY['ativo'::"text", 'pausado'::"text", 'cancelado'::"text"]))),
    CONSTRAINT "recurrence_rules_times_chk" CHECK (("end_time" > "start_time"))
);


ALTER TABLE "public"."recurrence_rules" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."saas_admins" (
    "user_id" "uuid" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."saas_admins" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."saas_doc_votos" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "doc_id" "uuid" NOT NULL,
    "user_id" "uuid" NOT NULL,
    "util" boolean NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."saas_doc_votos" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."saas_docs" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "titulo" "text" NOT NULL,
    "conteudo" "text" DEFAULT ''::"text" NOT NULL,
    "medias" "jsonb" DEFAULT '[]'::"jsonb" NOT NULL,
    "tipo_acesso" "text" DEFAULT 'usuario'::"text" NOT NULL,
    "pagina_path" "text" NOT NULL,
    "docs_relacionados" "uuid"[] DEFAULT '{}'::"uuid"[] NOT NULL,
    "ativo" boolean DEFAULT true NOT NULL,
    "ordem" integer DEFAULT 0 NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "categoria" "text",
    "exibir_no_faq" boolean DEFAULT false NOT NULL,
    "votos_util" integer DEFAULT 0 NOT NULL,
    "votos_nao_util" integer DEFAULT 0 NOT NULL,
    CONSTRAINT "saas_docs_tipo_acesso_check" CHECK (("tipo_acesso" = ANY (ARRAY['admin'::"text", 'usuario'::"text"])))
);


ALTER TABLE "public"."saas_docs" OWNER TO "supabase_admin";


COMMENT ON COLUMN "public"."saas_docs"."categoria" IS 'Agrupa docs no portal FAQ (ex: Conta, Agenda, Pagamentos)';



COMMENT ON COLUMN "public"."saas_docs"."exibir_no_faq" IS 'Se true, a doc e seus itens FAQ aparecem no portal de FAQ';



CREATE TABLE IF NOT EXISTS "public"."saas_faq" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "pergunta" "text" NOT NULL,
    "categoria" "text",
    "publico" boolean DEFAULT false NOT NULL,
    "votos" integer DEFAULT 0 NOT NULL,
    "titulo" "text",
    "conteudo" "text",
    "tipo_acesso" "text" DEFAULT 'usuario'::"text" NOT NULL,
    "pagina_path" "text" NOT NULL,
    "pagina_label" "text",
    "medias" "jsonb" DEFAULT '[]'::"jsonb" NOT NULL,
    "faqs_relacionados" "uuid"[] DEFAULT '{}'::"uuid"[] NOT NULL,
    "ativo" boolean DEFAULT true NOT NULL,
    "ordem" integer DEFAULT 0 NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."saas_faq" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."saas_faq_itens" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "doc_id" "uuid" NOT NULL,
    "pergunta" "text" NOT NULL,
    "resposta" "text",
    "ordem" integer DEFAULT 0 NOT NULL,
    "ativo" boolean DEFAULT true NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."saas_faq_itens" OWNER TO "supabase_admin";


COMMENT ON TABLE "public"."saas_faq_itens" IS 'Pares pergunta/resposta vinculados a um documento de ajuda';



CREATE TABLE IF NOT EXISTS "public"."subscription_events" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "subscription_id" "uuid" NOT NULL,
    "owner_id" "uuid" NOT NULL,
    "event_type" "text" NOT NULL,
    "old_plan_id" "uuid",
    "new_plan_id" "uuid",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "created_by" "uuid",
    "source" "text" DEFAULT 'admin_ui'::"text",
    "reason" "text",
    "metadata" "jsonb",
    "owner_type" "text" NOT NULL,
    "owner_ref" "uuid" NOT NULL,
    CONSTRAINT "subscription_events_owner_ref_consistency_chk" CHECK (("owner_id" = "owner_ref")),
    CONSTRAINT "subscription_events_owner_type_chk" CHECK ((("owner_type" IS NULL) OR ("owner_type" = ANY (ARRAY['clinic'::"text", 'therapist'::"text"]))))
);


ALTER TABLE "public"."subscription_events" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."subscription_intents_personal" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "user_id" "uuid" NOT NULL,
    "created_by_user_id" "uuid",
    "email" "text" NOT NULL,
    "plan_id" "uuid" NOT NULL,
    "plan_key" "text",
    "interval" "text",
    "amount_cents" integer,
    "currency" "text",
    "status" "text" DEFAULT 'new'::"text" NOT NULL,
    "source" "text" DEFAULT 'manual'::"text" NOT NULL,
    "notes" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "paid_at" timestamp with time zone,
    "subscription_id" "uuid",
    CONSTRAINT "sint_personal_interval_check" CHECK ((("interval" IS NULL) OR ("interval" = ANY (ARRAY['month'::"text", 'year'::"text"])))),
    CONSTRAINT "sint_personal_status_check" CHECK (("status" = ANY (ARRAY['new'::"text", 'waiting_payment'::"text", 'paid'::"text", 'canceled'::"text"])))
);


ALTER TABLE "public"."subscription_intents_personal" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."subscription_intents_tenant" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "user_id" "uuid" NOT NULL,
    "created_by_user_id" "uuid",
    "email" "text" NOT NULL,
    "plan_id" "uuid" NOT NULL,
    "plan_key" "text",
    "interval" "text",
    "amount_cents" integer,
    "currency" "text",
    "status" "text" DEFAULT 'new'::"text" NOT NULL,
    "source" "text" DEFAULT 'manual'::"text" NOT NULL,
    "notes" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "paid_at" timestamp with time zone,
    "tenant_id" "uuid" NOT NULL,
    "subscription_id" "uuid",
    CONSTRAINT "sint_tenant_interval_check" CHECK ((("interval" IS NULL) OR ("interval" = ANY (ARRAY['month'::"text", 'year'::"text"])))),
    CONSTRAINT "sint_tenant_status_check" CHECK (("status" = ANY (ARRAY['new'::"text", 'waiting_payment'::"text", 'paid'::"text", 'canceled'::"text"])))
);


ALTER TABLE "public"."subscription_intents_tenant" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."subscription_intents" AS
 SELECT "t"."id",
    "t"."user_id",
    "t"."created_by_user_id",
    "t"."email",
    "t"."plan_id",
    "t"."plan_key",
    "t"."interval",
    "t"."amount_cents",
    "t"."currency",
    "t"."status",
    "t"."source",
    "t"."notes",
    "t"."created_at",
    "t"."paid_at",
    "t"."tenant_id",
    "t"."subscription_id",
    'clinic'::"text" AS "plan_target"
   FROM "public"."subscription_intents_tenant" "t"
UNION ALL
 SELECT "p"."id",
    "p"."user_id",
    "p"."created_by_user_id",
    "p"."email",
    "p"."plan_id",
    "p"."plan_key",
    "p"."interval",
    "p"."amount_cents",
    "p"."currency",
    "p"."status",
    "p"."source",
    "p"."notes",
    "p"."created_at",
    "p"."paid_at",
    NULL::"uuid" AS "tenant_id",
    "p"."subscription_id",
    'therapist'::"text" AS "plan_target"
   FROM "public"."subscription_intents_personal" "p";


ALTER VIEW "public"."subscription_intents" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."subscription_intents_legacy" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "user_id" "uuid",
    "email" "text",
    "plan_key" "text" NOT NULL,
    "interval" "text" NOT NULL,
    "amount_cents" integer NOT NULL,
    "currency" "text" DEFAULT 'BRL'::"text" NOT NULL,
    "status" "text" DEFAULT 'new'::"text" NOT NULL,
    "source" "text" DEFAULT 'landing'::"text" NOT NULL,
    "notes" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "paid_at" timestamp with time zone,
    "tenant_id" "uuid" NOT NULL,
    "created_by_user_id" "uuid",
    CONSTRAINT "subscription_intents_interval_check" CHECK (("interval" = ANY (ARRAY['month'::"text", 'year'::"text"]))),
    CONSTRAINT "subscription_intents_status_check" CHECK (("status" = ANY (ARRAY['new'::"text", 'waiting_payment'::"text", 'paid'::"text", 'canceled'::"text"])))
);


ALTER TABLE "public"."subscription_intents_legacy" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."tenant_feature_exceptions_log" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    "feature_key" "text" NOT NULL,
    "enabled" boolean NOT NULL,
    "reason" "text",
    "created_by" "uuid",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."tenant_feature_exceptions_log" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."tenant_features" (
    "tenant_id" "uuid" NOT NULL,
    "feature_key" "text" NOT NULL,
    "enabled" boolean DEFAULT false NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."tenant_features" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."tenant_invites" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "tenant_id" "uuid" NOT NULL,
    "email" "text" NOT NULL,
    "role" "text" NOT NULL,
    "token" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "invited_by" "uuid",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "expires_at" timestamp with time zone DEFAULT ("now"() + '7 days'::interval) NOT NULL,
    "accepted_at" timestamp with time zone,
    "accepted_by" "uuid",
    "revoked_at" timestamp with time zone,
    "revoked_by" "uuid",
    CONSTRAINT "tenant_invites_role_check" CHECK (("role" = ANY (ARRAY['therapist'::"text", 'secretary'::"text"])))
);


ALTER TABLE "public"."tenant_invites" OWNER TO "supabase_admin";


CREATE TABLE IF NOT EXISTS "public"."tenants" (
    "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
    "name" "text",
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "kind" "text" DEFAULT 'saas'::"text" NOT NULL,
    CONSTRAINT "tenants_kind_check" CHECK (("kind" = ANY (ARRAY['therapist'::"text", 'clinic_coworking'::"text", 'clinic_reception'::"text", 'clinic_full'::"text", 'clinic'::"text", 'saas'::"text", 'supervisor'::"text"])))
);


ALTER TABLE "public"."tenants" OWNER TO "supabase_admin";


COMMENT ON COLUMN "public"."tenants"."kind" IS 'Tipo do tenant. Imutável após criação. therapist=terapeuta solo. clinic_coworking/clinic_reception/clinic_full=clínicas. clinic e saas são legados.';



CREATE TABLE IF NOT EXISTS "public"."user_settings" (
    "user_id" "uuid" NOT NULL,
    "theme_mode" "text" DEFAULT 'dark'::"text" NOT NULL,
    "preset" "text" DEFAULT 'Aura'::"text" NOT NULL,
    "primary_color" "text" DEFAULT 'noir'::"text" NOT NULL,
    "surface_color" "text" DEFAULT 'slate'::"text" NOT NULL,
    "menu_mode" "text" DEFAULT 'static'::"text" NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "updated_at" timestamp with time zone DEFAULT "now"() NOT NULL
);


ALTER TABLE "public"."user_settings" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_auth_users_public" AS
 SELECT "id" AS "user_id",
    "email",
    "created_at",
    "last_sign_in_at"
   FROM "auth"."users" "u";


ALTER VIEW "public"."v_auth_users_public" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_commitment_totals" AS
 SELECT "c"."tenant_id",
    "c"."id" AS "commitment_id",
    (COALESCE("sum"("l"."minutes"), (0)::bigint))::integer AS "total_minutes"
   FROM ("public"."determined_commitments" "c"
     LEFT JOIN "public"."commitment_time_logs" "l" ON (("l"."commitment_id" = "c"."id")))
  GROUP BY "c"."tenant_id", "c"."id";


ALTER VIEW "public"."v_commitment_totals" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_patient_groups_with_counts" AS
 SELECT "pg"."id",
    "pg"."nome",
    "pg"."cor",
    "pg"."owner_id",
    "pg"."is_system",
    "pg"."is_active",
    "pg"."created_at",
    "pg"."updated_at",
    (COALESCE("count"("pgp"."patient_id"), (0)::bigint))::integer AS "patients_count"
   FROM ("public"."patient_groups" "pg"
     LEFT JOIN "public"."patient_group_patient" "pgp" ON (("pgp"."patient_group_id" = "pg"."id")))
  GROUP BY "pg"."id", "pg"."nome", "pg"."cor", "pg"."owner_id", "pg"."is_system", "pg"."is_active", "pg"."created_at", "pg"."updated_at";


ALTER VIEW "public"."v_patient_groups_with_counts" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_plan_active_prices" AS
 SELECT "plan_id",
    "max"(
        CASE
            WHEN (("interval" = 'month'::"text") AND "is_active") THEN "amount_cents"
            ELSE NULL::integer
        END) AS "monthly_cents",
    "max"(
        CASE
            WHEN (("interval" = 'year'::"text") AND "is_active") THEN "amount_cents"
            ELSE NULL::integer
        END) AS "yearly_cents",
    "max"(
        CASE
            WHEN (("interval" = 'month'::"text") AND "is_active") THEN "currency"
            ELSE NULL::"text"
        END) AS "monthly_currency",
    "max"(
        CASE
            WHEN (("interval" = 'year'::"text") AND "is_active") THEN "currency"
            ELSE NULL::"text"
        END) AS "yearly_currency"
   FROM "public"."plan_prices"
  GROUP BY "plan_id";


ALTER VIEW "public"."v_plan_active_prices" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_public_pricing" AS
 SELECT "p"."id" AS "plan_id",
    "p"."key" AS "plan_key",
    "p"."name" AS "plan_name",
    COALESCE("pp"."public_name", ''::"text") AS "public_name",
    COALESCE("pp"."public_description", ''::"text") AS "public_description",
    "pp"."badge",
    COALESCE("pp"."is_featured", false) AS "is_featured",
    COALESCE("pp"."is_visible", true) AS "is_visible",
    COALESCE("pp"."sort_order", 0) AS "sort_order",
    "ap"."monthly_cents",
    "ap"."yearly_cents",
    "ap"."monthly_currency",
    "ap"."yearly_currency",
    COALESCE(( SELECT "jsonb_agg"("jsonb_build_object"('id', "b"."id", 'text', "b"."text", 'highlight', "b"."highlight", 'sort_order', "b"."sort_order") ORDER BY "b"."sort_order", "b"."created_at") AS "jsonb_agg"
           FROM "public"."plan_public_bullets" "b"
          WHERE ("b"."plan_id" = "p"."id")), '[]'::"jsonb") AS "bullets",
    "p"."target" AS "plan_target"
   FROM (("public"."plans" "p"
     LEFT JOIN "public"."plan_public" "pp" ON (("pp"."plan_id" = "p"."id")))
     LEFT JOIN "public"."v_plan_active_prices" "ap" ON (("ap"."plan_id" = "p"."id")))
  ORDER BY COALESCE("pp"."sort_order", 0), "p"."key";


ALTER VIEW "public"."v_public_pricing" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_subscription_feature_mismatch" AS
 WITH "expected" AS (
         SELECT "s"."user_id" AS "owner_id",
            "f"."key" AS "feature_key"
           FROM (("public"."subscriptions" "s"
             JOIN "public"."plan_features" "pf" ON ((("pf"."plan_id" = "s"."plan_id") AND ("pf"."enabled" = true))))
             JOIN "public"."features" "f" ON (("f"."id" = "pf"."feature_id")))
          WHERE (("s"."status" = 'active'::"text") AND ("s"."tenant_id" IS NULL) AND ("s"."user_id" IS NOT NULL))
        ), "actual" AS (
         SELECT "e"."owner_id",
            "e"."feature_key"
           FROM "public"."owner_feature_entitlements" "e"
        )
 SELECT COALESCE("expected"."owner_id", "actual"."owner_id") AS "owner_id",
    COALESCE("expected"."feature_key", "actual"."feature_key") AS "feature_key",
        CASE
            WHEN (("expected"."feature_key" IS NOT NULL) AND ("actual"."feature_key" IS NULL)) THEN 'missing_entitlement'::"text"
            WHEN (("expected"."feature_key" IS NULL) AND ("actual"."feature_key" IS NOT NULL)) THEN 'unexpected_entitlement'::"text"
            ELSE NULL::"text"
        END AS "mismatch_type"
   FROM ("expected"
     FULL JOIN "actual" ON ((("expected"."owner_id" = "actual"."owner_id") AND ("expected"."feature_key" = "actual"."feature_key"))))
  WHERE (("expected"."feature_key" IS NULL) OR ("actual"."feature_key" IS NULL));


ALTER VIEW "public"."v_subscription_feature_mismatch" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_subscription_health" AS
 SELECT "s"."id" AS "subscription_id",
    "s"."user_id" AS "owner_id",
    "s"."status",
    "s"."plan_id",
    "p"."key" AS "plan_key",
    "s"."current_period_start",
    "s"."current_period_end",
    "s"."updated_at",
        CASE
            WHEN ("s"."plan_id" IS NULL) THEN 'missing_plan'::"text"
            WHEN ("p"."id" IS NULL) THEN 'invalid_plan'::"text"
            WHEN (("s"."status" = 'active'::"text") AND ("s"."current_period_end" IS NOT NULL) AND ("s"."current_period_end" < "now"())) THEN 'expired_but_active'::"text"
            WHEN (("s"."status" = 'canceled'::"text") AND ("s"."current_period_end" > "now"())) THEN 'canceled_but_still_in_period'::"text"
            ELSE 'ok'::"text"
        END AS "health_status",
        CASE
            WHEN ("s"."tenant_id" IS NOT NULL) THEN 'clinic'::"text"
            ELSE 'therapist'::"text"
        END AS "owner_type",
    COALESCE("s"."tenant_id", "s"."user_id") AS "owner_ref"
   FROM ("public"."subscriptions" "s"
     LEFT JOIN "public"."plans" "p" ON (("p"."id" = "s"."plan_id")));


ALTER VIEW "public"."v_subscription_health" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_subscription_health_v2" AS
 SELECT "s"."id" AS "subscription_id",
    "s"."user_id" AS "owner_id",
        CASE
            WHEN ("s"."tenant_id" IS NOT NULL) THEN 'clinic'::"text"
            ELSE 'therapist'::"text"
        END AS "owner_type",
    COALESCE("s"."tenant_id", "s"."user_id") AS "owner_ref",
    "s"."status",
    "s"."plan_id",
    "p"."key" AS "plan_key",
    "s"."current_period_start",
    "s"."current_period_end",
    "s"."updated_at",
        CASE
            WHEN ("s"."plan_id" IS NULL) THEN 'missing_plan'::"text"
            WHEN ("p"."id" IS NULL) THEN 'invalid_plan'::"text"
            WHEN (("s"."status" = 'active'::"text") AND ("s"."current_period_end" IS NOT NULL) AND ("s"."current_period_end" < "now"())) THEN 'expired_but_active'::"text"
            WHEN (("s"."status" = 'canceled'::"text") AND ("s"."current_period_end" > "now"())) THEN 'canceled_but_still_in_period'::"text"
            ELSE 'ok'::"text"
        END AS "health_status"
   FROM ("public"."subscriptions" "s"
     LEFT JOIN "public"."plans" "p" ON (("p"."id" = "s"."plan_id")));


ALTER VIEW "public"."v_subscription_health_v2" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tag_patient_counts" AS
 SELECT "t"."id",
    "t"."owner_id",
    "t"."nome",
    "t"."cor",
    "t"."is_padrao",
    "t"."created_at",
    "t"."updated_at",
    (COALESCE("count"("ppt"."patient_id"), (0)::bigint))::integer AS "pacientes_count",
    (COALESCE("count"("ppt"."patient_id"), (0)::bigint))::integer AS "patient_count"
   FROM ("public"."patient_tags" "t"
     LEFT JOIN "public"."patient_patient_tag" "ppt" ON ((("ppt"."tag_id" = "t"."id") AND ("ppt"."owner_id" = "t"."owner_id"))))
  GROUP BY "t"."id", "t"."owner_id", "t"."nome", "t"."cor", "t"."is_padrao", "t"."created_at", "t"."updated_at";


ALTER VIEW "public"."v_tag_patient_counts" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_active_subscription" AS
 SELECT DISTINCT ON ("tenant_id") "tenant_id",
    "plan_id",
    "plan_key",
    "interval",
    "status",
    "current_period_start",
    "current_period_end",
    "created_at"
   FROM "public"."subscriptions" "s"
  WHERE (("tenant_id" IS NOT NULL) AND ("status" = 'active'::"text") AND (("current_period_end" IS NULL) OR ("current_period_end" > "now"())))
  ORDER BY "tenant_id", "created_at" DESC;


ALTER VIEW "public"."v_tenant_active_subscription" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_entitlements" AS
 SELECT "a"."tenant_id",
    "f"."key" AS "feature_key",
    true AS "allowed"
   FROM (("public"."v_tenant_active_subscription" "a"
     JOIN "public"."plan_features" "pf" ON ((("pf"."plan_id" = "a"."plan_id") AND ("pf"."enabled" = true))))
     JOIN "public"."features" "f" ON (("f"."id" = "pf"."feature_id")));


ALTER VIEW "public"."v_tenant_entitlements" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_entitlements_full" AS
 SELECT "a"."tenant_id",
    "f"."key" AS "feature_key",
    ("pf"."enabled" = true) AS "allowed",
    "pf"."limits",
    "a"."plan_id",
    "p"."key" AS "plan_key"
   FROM ((("public"."v_tenant_active_subscription" "a"
     JOIN "public"."plan_features" "pf" ON (("pf"."plan_id" = "a"."plan_id")))
     JOIN "public"."features" "f" ON (("f"."id" = "pf"."feature_id")))
     JOIN "public"."plans" "p" ON (("p"."id" = "a"."plan_id")));


ALTER VIEW "public"."v_tenant_entitlements_full" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_entitlements_json" AS
 SELECT "tenant_id",
    "max"("plan_key") AS "plan_key",
    "jsonb_object_agg"("feature_key", "jsonb_build_object"('allowed', "allowed", 'limits', COALESCE("limits", '{}'::"jsonb")) ORDER BY "feature_key") AS "entitlements"
   FROM "public"."v_tenant_entitlements_full"
  GROUP BY "tenant_id";


ALTER VIEW "public"."v_tenant_entitlements_json" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_feature_exceptions" AS
 SELECT "tf"."tenant_id",
    "a"."plan_key",
    "tf"."feature_key",
    'commercial_exception'::"text" AS "exception_type"
   FROM (("public"."tenant_features" "tf"
     JOIN "public"."v_tenant_active_subscription" "a" ON (("a"."tenant_id" = "tf"."tenant_id")))
     LEFT JOIN "public"."v_tenant_entitlements_full" "v" ON ((("v"."tenant_id" = "tf"."tenant_id") AND ("v"."feature_key" = "tf"."feature_key"))))
  WHERE (("tf"."enabled" = true) AND (COALESCE("v"."allowed", false) = false));


ALTER VIEW "public"."v_tenant_feature_exceptions" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_feature_mismatch" AS
 WITH "plan_allowed" AS (
         SELECT "v"."tenant_id",
            "v"."feature_key",
            "v"."allowed"
           FROM "public"."v_tenant_entitlements_full" "v"
        ), "overrides" AS (
         SELECT "tf"."tenant_id",
            "tf"."feature_key",
            "tf"."enabled"
           FROM "public"."tenant_features" "tf"
        )
 SELECT "o"."tenant_id",
    "o"."feature_key",
        CASE
            WHEN (("o"."enabled" = true) AND (COALESCE("p"."allowed", false) = false)) THEN 'unexpected_override'::"text"
            ELSE NULL::"text"
        END AS "mismatch_type"
   FROM ("overrides" "o"
     LEFT JOIN "plan_allowed" "p" ON ((("p"."tenant_id" = "o"."tenant_id") AND ("p"."feature_key" = "o"."feature_key"))))
  WHERE (("o"."enabled" = true) AND (COALESCE("p"."allowed", false) = false));


ALTER VIEW "public"."v_tenant_feature_mismatch" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_members_with_profiles" AS
 SELECT "tm"."id" AS "tenant_member_id",
    "tm"."tenant_id",
    "tm"."user_id",
    "tm"."role",
    "tm"."status",
    "tm"."created_at",
    "p"."full_name",
    "au"."email"
   FROM (("public"."tenant_members" "tm"
     LEFT JOIN "public"."profiles" "p" ON (("p"."id" = "tm"."user_id")))
     LEFT JOIN "auth"."users" "au" ON (("au"."id" = "tm"."user_id")));


ALTER VIEW "public"."v_tenant_members_with_profiles" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_people" AS
 SELECT 'member'::"text" AS "type",
    "m"."tenant_id",
    "m"."user_id",
    "u"."email",
    "m"."role",
    "m"."status",
    NULL::"uuid" AS "invite_token",
    NULL::timestamp with time zone AS "expires_at"
   FROM ("public"."tenant_members" "m"
     JOIN "auth"."users" "u" ON (("u"."id" = "m"."user_id")))
UNION ALL
 SELECT 'invite'::"text" AS "type",
    "i"."tenant_id",
    NULL::"uuid" AS "user_id",
    "i"."email",
    "i"."role",
    'invited'::"text" AS "status",
    "i"."token" AS "invite_token",
    "i"."expires_at"
   FROM "public"."tenant_invites" "i"
  WHERE (("i"."accepted_at" IS NULL) AND ("i"."revoked_at" IS NULL));


ALTER VIEW "public"."v_tenant_people" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_tenant_staff" AS
 SELECT ('m_'::"text" || ("tm"."id")::"text") AS "row_id",
    "tm"."tenant_id",
    "tm"."user_id",
    "tm"."role",
    "tm"."status",
    "tm"."created_at",
    "p"."full_name",
    "au"."email",
    NULL::"uuid" AS "invite_token"
   FROM (("public"."tenant_members" "tm"
     LEFT JOIN "public"."profiles" "p" ON (("p"."id" = "tm"."user_id")))
     LEFT JOIN "auth"."users" "au" ON (("au"."id" = "tm"."user_id")))
UNION ALL
 SELECT ('i_'::"text" || ("ti"."id")::"text") AS "row_id",
    "ti"."tenant_id",
    NULL::"uuid" AS "user_id",
    "ti"."role",
    'invited'::"text" AS "status",
    "ti"."created_at",
    NULL::"text" AS "full_name",
    "ti"."email",
    "ti"."token" AS "invite_token"
   FROM "public"."tenant_invites" "ti"
  WHERE (("ti"."accepted_at" IS NULL) AND ("ti"."revoked_at" IS NULL) AND ("ti"."expires_at" > "now"()));


ALTER VIEW "public"."v_tenant_staff" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_user_active_subscription" AS
 SELECT DISTINCT ON ("user_id") "user_id",
    "plan_id",
    "plan_key",
    "interval",
    "status",
    "current_period_start",
    "current_period_end",
    "created_at"
   FROM "public"."subscriptions" "s"
  WHERE (("tenant_id" IS NULL) AND ("user_id" IS NOT NULL) AND ("status" = 'active'::"text") AND (("current_period_end" IS NULL) OR ("current_period_end" > "now"())))
  ORDER BY "user_id", "created_at" DESC;


ALTER VIEW "public"."v_user_active_subscription" OWNER TO "supabase_admin";


CREATE OR REPLACE VIEW "public"."v_user_entitlements" AS
 SELECT "a"."user_id",
    "f"."key" AS "feature_key",
    true AS "allowed"
   FROM (("public"."v_user_active_subscription" "a"
     JOIN "public"."plan_features" "pf" ON ((("pf"."plan_id" = "a"."plan_id") AND ("pf"."enabled" = true))))
     JOIN "public"."features" "f" ON (("f"."id" = "pf"."feature_id")));


ALTER VIEW "public"."v_user_entitlements" OWNER TO "supabase_admin";


ALTER TABLE ONLY "public"."agenda_online_slots" ALTER COLUMN "id" SET DEFAULT "nextval"('"public"."agenda_online_slots_id_seq"'::"regclass");



ALTER TABLE ONLY "public"."agenda_bloqueios"
    ADD CONSTRAINT "agenda_bloqueios_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."agenda_configuracoes"
    ADD CONSTRAINT "agenda_configuracoes_pkey" PRIMARY KEY ("owner_id");



ALTER TABLE ONLY "public"."agenda_eventos"
    ADD CONSTRAINT "agenda_eventos_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."agenda_eventos"
    ADD CONSTRAINT "agenda_eventos_sem_sobreposicao" EXCLUDE USING "gist" ("owner_id" WITH =, "tstzrange"("inicio_em", "fim_em", '[)'::"text") WITH &&);



ALTER TABLE ONLY "public"."agenda_excecoes"
    ADD CONSTRAINT "agenda_excecoes_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."agenda_online_slots"
    ADD CONSTRAINT "agenda_online_slots_owner_id_weekday_time_key" UNIQUE ("owner_id", "weekday", "time");



ALTER TABLE ONLY "public"."agenda_online_slots"
    ADD CONSTRAINT "agenda_online_slots_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."agenda_regras_semanais"
    ADD CONSTRAINT "agenda_regras_semanais_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."agenda_regras_semanais"
    ADD CONSTRAINT "agenda_regras_semanais_unique" UNIQUE ("owner_id", "dia_semana", "hora_inicio", "hora_fim", "modalidade");



ALTER TABLE ONLY "public"."agenda_slots_bloqueados_semanais"
    ADD CONSTRAINT "agenda_slots_bloqueados_seman_owner_id_dia_semana_hora_inic_key" UNIQUE ("owner_id", "dia_semana", "hora_inicio");



ALTER TABLE ONLY "public"."agenda_slots_bloqueados_semanais"
    ADD CONSTRAINT "agenda_slots_bloqueados_semanais_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."agenda_slots_regras"
    ADD CONSTRAINT "agenda_slots_regras_owner_id_dia_semana_key" UNIQUE ("owner_id", "dia_semana");



ALTER TABLE ONLY "public"."agenda_slots_regras"
    ADD CONSTRAINT "agenda_slots_regras_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."agendador_configuracoes"
    ADD CONSTRAINT "agendador_configuracoes_pkey" PRIMARY KEY ("owner_id");



ALTER TABLE ONLY "public"."agendador_solicitacoes"
    ADD CONSTRAINT "agendador_solicitacoes_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."commitment_time_logs"
    ADD CONSTRAINT "commitment_time_logs_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."determined_commitment_fields"
    ADD CONSTRAINT "determined_commitment_fields_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."determined_commitments"
    ADD CONSTRAINT "determined_commitments_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."determined_commitments"
    ADD CONSTRAINT "determined_commitments_tenant_native_key_uq" UNIQUE ("tenant_id", "native_key");



ALTER TABLE ONLY "public"."dev_user_credentials"
    ADD CONSTRAINT "dev_user_credentials_email_key" UNIQUE ("email");



ALTER TABLE ONLY "public"."dev_user_credentials"
    ADD CONSTRAINT "dev_user_credentials_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."entitlements_invalidation"
    ADD CONSTRAINT "entitlements_invalidation_pkey" PRIMARY KEY ("owner_id");



ALTER TABLE ONLY "public"."features"
    ADD CONSTRAINT "features_key_key" UNIQUE ("key");



ALTER TABLE ONLY "public"."features"
    ADD CONSTRAINT "features_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."feriados"
    ADD CONSTRAINT "feriados_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."feriados"
    ADD CONSTRAINT "feriados_tenant_id_data_nome_key" UNIQUE ("tenant_id", "data", "nome");



ALTER TABLE ONLY "public"."module_features"
    ADD CONSTRAINT "module_features_pkey" PRIMARY KEY ("module_id", "feature_id");



ALTER TABLE ONLY "public"."modules"
    ADD CONSTRAINT "modules_key_key" UNIQUE ("key");



ALTER TABLE ONLY "public"."modules"
    ADD CONSTRAINT "modules_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."owner_users"
    ADD CONSTRAINT "owner_users_pkey" PRIMARY KEY ("owner_id", "user_id");



ALTER TABLE ONLY "public"."patient_group_patient"
    ADD CONSTRAINT "patient_group_patient_pkey" PRIMARY KEY ("patient_group_id", "patient_id");



ALTER TABLE ONLY "public"."patient_groups"
    ADD CONSTRAINT "patient_groups_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."patient_intake_requests"
    ADD CONSTRAINT "patient_intake_requests_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."patient_invites"
    ADD CONSTRAINT "patient_invites_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."patient_invites"
    ADD CONSTRAINT "patient_invites_token_key" UNIQUE ("token");



ALTER TABLE ONLY "public"."patient_patient_tag"
    ADD CONSTRAINT "patient_patient_tag_pkey" PRIMARY KEY ("patient_id", "tag_id");



ALTER TABLE ONLY "public"."patient_tags"
    ADD CONSTRAINT "patient_tags_owner_name_uniq" UNIQUE ("owner_id", "nome");



ALTER TABLE ONLY "public"."patient_tags"
    ADD CONSTRAINT "patient_tags_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."patients"
    ADD CONSTRAINT "patients_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."plan_features"
    ADD CONSTRAINT "plan_features_pkey" PRIMARY KEY ("plan_id", "feature_id");



ALTER TABLE ONLY "public"."plan_prices"
    ADD CONSTRAINT "plan_prices_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."plan_public_bullets"
    ADD CONSTRAINT "plan_public_bullets_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."plan_public"
    ADD CONSTRAINT "plan_public_pkey" PRIMARY KEY ("plan_id");



ALTER TABLE ONLY "public"."plans"
    ADD CONSTRAINT "plans_key_key" UNIQUE ("key");



ALTER TABLE ONLY "public"."plans"
    ADD CONSTRAINT "plans_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."profiles"
    ADD CONSTRAINT "profiles_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."recurrence_exceptions"
    ADD CONSTRAINT "recurrence_exceptions_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."recurrence_exceptions"
    ADD CONSTRAINT "recurrence_exceptions_unique" UNIQUE ("recurrence_id", "original_date");



ALTER TABLE ONLY "public"."recurrence_rules"
    ADD CONSTRAINT "recurrence_rules_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."saas_admins"
    ADD CONSTRAINT "saas_admins_pkey" PRIMARY KEY ("user_id");



ALTER TABLE ONLY "public"."saas_doc_votos"
    ADD CONSTRAINT "saas_doc_votos_doc_id_user_id_key" UNIQUE ("doc_id", "user_id");



ALTER TABLE ONLY "public"."saas_doc_votos"
    ADD CONSTRAINT "saas_doc_votos_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."saas_docs"
    ADD CONSTRAINT "saas_docs_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."saas_faq_itens"
    ADD CONSTRAINT "saas_faq_itens_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."saas_faq"
    ADD CONSTRAINT "saas_faq_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."subscription_events"
    ADD CONSTRAINT "subscription_events_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."subscription_intents_personal"
    ADD CONSTRAINT "subscription_intents_personal_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."subscription_intents_legacy"
    ADD CONSTRAINT "subscription_intents_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."subscription_intents_tenant"
    ADD CONSTRAINT "subscription_intents_tenant_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."subscriptions"
    ADD CONSTRAINT "subscriptions_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."tenant_feature_exceptions_log"
    ADD CONSTRAINT "tenant_feature_exceptions_log_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."tenant_features"
    ADD CONSTRAINT "tenant_features_pkey" PRIMARY KEY ("tenant_id", "feature_key");



ALTER TABLE ONLY "public"."tenant_invites"
    ADD CONSTRAINT "tenant_invites_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."tenant_members"
    ADD CONSTRAINT "tenant_members_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."tenant_members"
    ADD CONSTRAINT "tenant_members_tenant_id_user_id_key" UNIQUE ("tenant_id", "user_id");



ALTER TABLE ONLY "public"."tenant_modules"
    ADD CONSTRAINT "tenant_modules_owner_id_module_id_key" UNIQUE ("owner_id", "module_id");



ALTER TABLE ONLY "public"."tenant_modules"
    ADD CONSTRAINT "tenant_modules_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."tenants"
    ADD CONSTRAINT "tenants_pkey" PRIMARY KEY ("id");



ALTER TABLE ONLY "public"."user_settings"
    ADD CONSTRAINT "user_settings_pkey" PRIMARY KEY ("user_id");



CREATE INDEX "agenda_bloqueios_owner_data_idx" ON "public"."agenda_bloqueios" USING "btree" ("owner_id", "data_inicio", "data_fim");



CREATE INDEX "agenda_bloqueios_owner_id_idx" ON "public"."agenda_bloqueios" USING "btree" ("owner_id");



CREATE INDEX "agenda_bloqueios_recorrente_idx" ON "public"."agenda_bloqueios" USING "btree" ("owner_id", "dia_semana") WHERE ("recorrente" = true);



CREATE INDEX "agenda_bloqueios_tenant_id_idx" ON "public"."agenda_bloqueios" USING "btree" ("tenant_id");



CREATE INDEX "agenda_configuracoes_tenant_idx" ON "public"."agenda_configuracoes" USING "btree" ("tenant_id");



CREATE INDEX "agenda_configuracoes_tenant_owner_idx" ON "public"."agenda_configuracoes" USING "btree" ("tenant_id", "owner_id");



CREATE INDEX "agenda_eventos_owner_inicio_idx" ON "public"."agenda_eventos" USING "btree" ("owner_id", "inicio_em");



CREATE INDEX "agenda_eventos_owner_paciente_idx" ON "public"."agenda_eventos" USING "btree" ("owner_id", "paciente_id");



CREATE INDEX "agenda_eventos_owner_terapeuta_inicio_idx" ON "public"."agenda_eventos" USING "btree" ("owner_id", "terapeuta_id", "inicio_em");



CREATE INDEX "agenda_eventos_recurrence_idx" ON "public"."agenda_eventos" USING "btree" ("recurrence_id") WHERE ("recurrence_id" IS NOT NULL);



CREATE INDEX "agenda_eventos_tenant_inicio_idx" ON "public"."agenda_eventos" USING "btree" ("tenant_id", "inicio_em");



CREATE INDEX "agenda_eventos_tenant_owner_inicio_idx" ON "public"."agenda_eventos" USING "btree" ("tenant_id", "owner_id", "inicio_em");



CREATE INDEX "agenda_excecoes_owner_data_idx" ON "public"."agenda_excecoes" USING "btree" ("owner_id", "data");



CREATE INDEX "agenda_excecoes_tenant_idx" ON "public"."agenda_excecoes" USING "btree" ("tenant_id");



CREATE INDEX "agenda_excecoes_tenant_owner_idx" ON "public"."agenda_excecoes" USING "btree" ("tenant_id", "owner_id");



CREATE INDEX "agenda_online_slots_owner_weekday_idx" ON "public"."agenda_online_slots" USING "btree" ("owner_id", "weekday");



CREATE INDEX "agenda_online_slots_tenant_idx" ON "public"."agenda_online_slots" USING "btree" ("tenant_id");



CREATE INDEX "agenda_online_slots_tenant_owner_idx" ON "public"."agenda_online_slots" USING "btree" ("tenant_id", "owner_id");



CREATE INDEX "agenda_regras_semanais_owner_dia_idx" ON "public"."agenda_regras_semanais" USING "btree" ("owner_id", "dia_semana");



CREATE INDEX "agenda_regras_semanais_tenant_idx" ON "public"."agenda_regras_semanais" USING "btree" ("tenant_id");



CREATE INDEX "agenda_regras_semanais_tenant_owner_idx" ON "public"."agenda_regras_semanais" USING "btree" ("tenant_id", "owner_id");



CREATE INDEX "agenda_slots_bloqueados_semanais_tenant_idx" ON "public"."agenda_slots_bloqueados_semanais" USING "btree" ("tenant_id");



CREATE INDEX "agenda_slots_bloqueados_semanais_tenant_owner_idx" ON "public"."agenda_slots_bloqueados_semanais" USING "btree" ("tenant_id", "owner_id");



CREATE INDEX "agenda_slots_regras_tenant_idx" ON "public"."agenda_slots_regras" USING "btree" ("tenant_id");



CREATE INDEX "agenda_slots_regras_tenant_owner_idx" ON "public"."agenda_slots_regras" USING "btree" ("tenant_id", "owner_id");



CREATE INDEX "agendador_cfg_tenant_idx" ON "public"."agendador_configuracoes" USING "btree" ("tenant_id");



CREATE INDEX "agendador_sol_data_idx" ON "public"."agendador_solicitacoes" USING "btree" ("data_solicitada", "hora_solicitada");



CREATE INDEX "agendador_sol_owner_idx" ON "public"."agendador_solicitacoes" USING "btree" ("owner_id", "status");



CREATE INDEX "agendador_sol_tenant_idx" ON "public"."agendador_solicitacoes" USING "btree" ("tenant_id");



CREATE INDEX "commitment_time_logs_calendar_event_idx" ON "public"."commitment_time_logs" USING "btree" ("calendar_event_id");



CREATE INDEX "commitment_time_logs_commitment_idx" ON "public"."commitment_time_logs" USING "btree" ("commitment_id", "created_at" DESC);



CREATE INDEX "commitment_time_logs_tenant_idx" ON "public"."commitment_time_logs" USING "btree" ("tenant_id", "created_at" DESC);



CREATE INDEX "determined_commitment_fields_commitment_idx" ON "public"."determined_commitment_fields" USING "btree" ("commitment_id", "sort_order");



CREATE UNIQUE INDEX "determined_commitment_fields_key_uniq" ON "public"."determined_commitment_fields" USING "btree" ("commitment_id", "key");



CREATE INDEX "determined_commitment_fields_tenant_idx" ON "public"."determined_commitment_fields" USING "btree" ("tenant_id");



CREATE INDEX "determined_commitments_active_idx" ON "public"."determined_commitments" USING "btree" ("tenant_id", "active");



CREATE INDEX "determined_commitments_tenant_idx" ON "public"."determined_commitments" USING "btree" ("tenant_id");



CREATE UNIQUE INDEX "determined_commitments_tenant_name_uniq" ON "public"."determined_commitments" USING "btree" ("tenant_id", "lower"("name"));



CREATE UNIQUE INDEX "feriados_global_unique" ON "public"."feriados" USING "btree" ("data", "nome") WHERE ("tenant_id" IS NULL);



CREATE INDEX "idx_agenda_eventos_determined_commitment_id" ON "public"."agenda_eventos" USING "btree" ("determined_commitment_id");



CREATE INDEX "idx_agenda_excecoes_owner_data" ON "public"."agenda_excecoes" USING "btree" ("owner_id", "data");



CREATE INDEX "idx_agenda_slots_regras_owner_dia" ON "public"."agenda_slots_regras" USING "btree" ("owner_id", "dia_semana");



CREATE INDEX "idx_intakes_converted_patient_id" ON "public"."patient_intake_requests" USING "btree" ("converted_patient_id");



CREATE INDEX "idx_intakes_owner_cpf" ON "public"."patient_intake_requests" USING "btree" ("owner_id", "cpf");



CREATE INDEX "idx_intakes_owner_created" ON "public"."patient_intake_requests" USING "btree" ("owner_id", "created_at" DESC);



CREATE INDEX "idx_intakes_owner_status_created" ON "public"."patient_intake_requests" USING "btree" ("owner_id", "status", "created_at" DESC);



CREATE INDEX "idx_intakes_status_created" ON "public"."patient_intake_requests" USING "btree" ("status", "created_at" DESC);



CREATE INDEX "idx_patient_group_patient_group_id" ON "public"."patient_group_patient" USING "btree" ("patient_group_id");



CREATE INDEX "idx_patient_groups_owner" ON "public"."patient_groups" USING "btree" ("owner_id");



CREATE INDEX "idx_patient_groups_owner_system_nome" ON "public"."patient_groups" USING "btree" ("owner_id", "is_system", "nome");



CREATE INDEX "idx_patient_tags_owner" ON "public"."patient_tags" USING "btree" ("owner_id");



CREATE INDEX "idx_patients_created_at" ON "public"."patients" USING "btree" ("created_at" DESC);



CREATE INDEX "idx_patients_last_attended" ON "public"."patients" USING "btree" ("last_attended_at" DESC);



CREATE INDEX "idx_patients_owner_email_principal" ON "public"."patients" USING "btree" ("owner_id", "email_principal");



CREATE INDEX "idx_patients_owner_id" ON "public"."patients" USING "btree" ("owner_id");



CREATE INDEX "idx_patients_owner_nome" ON "public"."patients" USING "btree" ("owner_id", "nome_completo");



CREATE INDEX "idx_patients_responsible_member" ON "public"."patients" USING "btree" ("responsible_member_id");



CREATE INDEX "idx_patients_status" ON "public"."patients" USING "btree" ("status");



CREATE INDEX "idx_patients_tenant" ON "public"."patients" USING "btree" ("tenant_id");



CREATE INDEX "idx_patients_tenant_email_norm" ON "public"."patients" USING "btree" ("tenant_id", "lower"(TRIM(BOTH FROM "email_principal")));



CREATE INDEX "idx_pgp_group" ON "public"."patient_group_patient" USING "btree" ("patient_group_id");



CREATE INDEX "idx_pgp_patient" ON "public"."patient_group_patient" USING "btree" ("patient_id");



CREATE INDEX "idx_ppt_patient" ON "public"."patient_patient_tag" USING "btree" ("patient_id");



CREATE INDEX "idx_ppt_tag" ON "public"."patient_patient_tag" USING "btree" ("tag_id");



CREATE INDEX "idx_slots_bloq_owner_dia" ON "public"."agenda_slots_bloqueados_semanais" USING "btree" ("owner_id", "dia_semana");



CREATE INDEX "idx_subscription_intents_plan_interval" ON "public"."subscription_intents_legacy" USING "btree" ("plan_key", "interval");



CREATE INDEX "idx_subscription_intents_status" ON "public"."subscription_intents_legacy" USING "btree" ("status");



CREATE INDEX "idx_subscription_intents_user_id" ON "public"."subscription_intents_legacy" USING "btree" ("user_id");



CREATE INDEX "idx_tenant_features_tenant" ON "public"."tenant_features" USING "btree" ("tenant_id");



CREATE INDEX "idx_tenant_invites_tenant" ON "public"."tenant_invites" USING "btree" ("tenant_id");



CREATE INDEX "idx_tenant_invites_token" ON "public"."tenant_invites" USING "btree" ("token");



CREATE INDEX "ix_plan_prices_plan" ON "public"."plan_prices" USING "btree" ("plan_id");



CREATE INDEX "ix_plan_public_bullets_plan" ON "public"."plan_public_bullets" USING "btree" ("plan_id");



CREATE INDEX "ix_plan_public_sort" ON "public"."plan_public" USING "btree" ("sort_order");



CREATE INDEX "patient_group_patient_tenant_idx" ON "public"."patient_group_patient" USING "btree" ("tenant_id");



CREATE UNIQUE INDEX "patient_groups_owner_nome_uniq" ON "public"."patient_groups" USING "btree" ("owner_id", "nome");



CREATE INDEX "patient_groups_tenant_idx" ON "public"."patient_groups" USING "btree" ("tenant_id");



CREATE INDEX "patient_intake_owner_id_idx" ON "public"."patient_intake_requests" USING "btree" ("owner_id");



CREATE INDEX "patient_intake_requests_tenant_idx" ON "public"."patient_intake_requests" USING "btree" ("tenant_id");



CREATE INDEX "patient_intake_status_idx" ON "public"."patient_intake_requests" USING "btree" ("status");



CREATE INDEX "patient_intake_token_idx" ON "public"."patient_intake_requests" USING "btree" ("token");



CREATE UNIQUE INDEX "patient_invites_one_active_per_owner" ON "public"."patient_invites" USING "btree" ("owner_id") WHERE ("active" = true);



CREATE INDEX "patient_invites_owner_id_idx" ON "public"."patient_invites" USING "btree" ("owner_id");



CREATE INDEX "patient_invites_tenant_idx" ON "public"."patient_invites" USING "btree" ("tenant_id");



CREATE INDEX "patient_invites_token_idx" ON "public"."patient_invites" USING "btree" ("token");



CREATE INDEX "patient_patient_tag_tenant_idx" ON "public"."patient_patient_tag" USING "btree" ("tenant_id");



CREATE UNIQUE INDEX "patient_tags_owner_name_uq" ON "public"."patient_tags" USING "btree" ("owner_id", "lower"("nome"));



CREATE INDEX "patient_tags_tenant_idx" ON "public"."patient_tags" USING "btree" ("tenant_id");



CREATE INDEX "ppt_owner_idx" ON "public"."patient_patient_tag" USING "btree" ("owner_id");



CREATE INDEX "ppt_patient_idx" ON "public"."patient_patient_tag" USING "btree" ("patient_id");



CREATE INDEX "ppt_tag_idx" ON "public"."patient_patient_tag" USING "btree" ("tag_id");



CREATE INDEX "recurrence_exceptions_rule_idx" ON "public"."recurrence_exceptions" USING "btree" ("recurrence_id");



CREATE INDEX "recurrence_exceptions_tenant_idx" ON "public"."recurrence_exceptions" USING "btree" ("tenant_id");



CREATE INDEX "recurrence_rules_active_idx" ON "public"."recurrence_rules" USING "btree" ("owner_id", "status") WHERE ("status" = 'ativo'::"text");



CREATE INDEX "recurrence_rules_owner_idx" ON "public"."recurrence_rules" USING "btree" ("owner_id");



CREATE INDEX "recurrence_rules_patient_idx" ON "public"."recurrence_rules" USING "btree" ("patient_id");



CREATE INDEX "recurrence_rules_tenant_idx" ON "public"."recurrence_rules" USING "btree" ("tenant_id");



CREATE INDEX "saas_doc_votos_doc_id_idx" ON "public"."saas_doc_votos" USING "btree" ("doc_id");



CREATE INDEX "saas_doc_votos_user_id_idx" ON "public"."saas_doc_votos" USING "btree" ("user_id");



CREATE INDEX "saas_docs_categoria_idx" ON "public"."saas_docs" USING "btree" ("categoria");



CREATE INDEX "saas_docs_exibir_no_faq_idx" ON "public"."saas_docs" USING "btree" ("exibir_no_faq") WHERE ("exibir_no_faq" = true);



CREATE INDEX "saas_docs_path_ativo_idx" ON "public"."saas_docs" USING "btree" ("pagina_path", "ativo");



CREATE INDEX "saas_faq_ativo_idx" ON "public"."saas_faq" USING "btree" ("ativo");



CREATE INDEX "saas_faq_categoria_idx" ON "public"."saas_faq" USING "btree" ("categoria");



CREATE INDEX "saas_faq_fts_idx" ON "public"."saas_faq" USING "gin" ("to_tsvector"('"portuguese"'::"regconfig", ((COALESCE("pergunta", ''::"text") || ' '::"text") || COALESCE("conteudo", ''::"text"))));



CREATE INDEX "saas_faq_itens_ativo_idx" ON "public"."saas_faq_itens" USING "btree" ("ativo");



CREATE INDEX "saas_faq_itens_doc_id_idx" ON "public"."saas_faq_itens" USING "btree" ("doc_id");



CREATE INDEX "saas_faq_pagina_path_idx" ON "public"."saas_faq" USING "btree" ("pagina_path");



CREATE INDEX "saas_faq_publico_idx" ON "public"."saas_faq" USING "btree" ("publico");



CREATE INDEX "saas_faq_votos_idx" ON "public"."saas_faq" USING "btree" ("votos" DESC);



CREATE INDEX "sint_personal_created_idx" ON "public"."subscription_intents_personal" USING "btree" ("created_at" DESC);



CREATE INDEX "sint_personal_status_idx" ON "public"."subscription_intents_personal" USING "btree" ("status");



CREATE INDEX "sint_tenant_created_idx" ON "public"."subscription_intents_tenant" USING "btree" ("created_at" DESC);



CREATE INDEX "sint_tenant_status_idx" ON "public"."subscription_intents_tenant" USING "btree" ("status");



CREATE INDEX "sint_tenant_tenant_idx" ON "public"."subscription_intents_tenant" USING "btree" ("tenant_id");



CREATE INDEX "subscription_events_created_at_idx" ON "public"."subscription_events" USING "btree" ("created_at" DESC);



CREATE INDEX "subscription_events_owner_ref_idx" ON "public"."subscription_events" USING "btree" ("owner_type", "owner_ref");



CREATE INDEX "subscription_events_sub_created_idx" ON "public"."subscription_events" USING "btree" ("subscription_id", "created_at" DESC);



CREATE INDEX "subscription_events_subscription_id_idx" ON "public"."subscription_events" USING "btree" ("subscription_id");



CREATE UNIQUE INDEX "subscriptions_one_active_per_tenant" ON "public"."subscriptions" USING "btree" ("tenant_id") WHERE ("status" = 'active'::"text");



CREATE UNIQUE INDEX "subscriptions_one_active_per_user" ON "public"."subscriptions" USING "btree" ("user_id") WHERE ("status" = 'active'::"text");



CREATE UNIQUE INDEX "subscriptions_one_active_per_user_personal" ON "public"."subscriptions" USING "btree" ("user_id") WHERE (("tenant_id" IS NULL) AND ("status" = 'active'::"text"));



CREATE INDEX "subscriptions_owner_idx" ON "public"."subscriptions" USING "btree" ("user_id");



CREATE INDEX "subscriptions_plan_key_idx" ON "public"."subscriptions" USING "btree" ("plan_key");



CREATE INDEX "subscriptions_status_idx" ON "public"."subscriptions" USING "btree" ("status");



CREATE INDEX "subscriptions_tenant_id_idx" ON "public"."subscriptions" USING "btree" ("tenant_id");



CREATE INDEX "subscriptions_tenant_period_end_idx" ON "public"."subscriptions" USING "btree" ("tenant_id", "current_period_end");



CREATE INDEX "subscriptions_tenant_status_idx" ON "public"."subscriptions" USING "btree" ("tenant_id", "status");



CREATE INDEX "subscriptions_user_status_idx" ON "public"."subscriptions" USING "btree" ("user_id", "status", "created_at" DESC);



CREATE INDEX "tenant_members_tenant_idx" ON "public"."tenant_members" USING "btree" ("tenant_id");



CREATE INDEX "tenant_members_user_idx" ON "public"."tenant_members" USING "btree" ("user_id");



CREATE INDEX "tenant_modules_owner_idx" ON "public"."tenant_modules" USING "btree" ("owner_id");



CREATE UNIQUE INDEX "unique_member_per_tenant" ON "public"."tenant_members" USING "btree" ("tenant_id", "user_id");



CREATE UNIQUE INDEX "uq_patients_tenant_user" ON "public"."patients" USING "btree" ("tenant_id", "user_id") WHERE ("user_id" IS NOT NULL);



CREATE UNIQUE INDEX "uq_plan_price_active" ON "public"."plan_prices" USING "btree" ("plan_id", "interval", "currency") WHERE (("is_active" = true) AND ("active_to" IS NULL));



CREATE UNIQUE INDEX "uq_plan_prices_active" ON "public"."plan_prices" USING "btree" ("plan_id", "interval") WHERE ("is_active" = true);



CREATE UNIQUE INDEX "uq_subscriptions_active_by_tenant" ON "public"."subscriptions" USING "btree" ("tenant_id") WHERE (("tenant_id" IS NOT NULL) AND ("status" = 'active'::"text"));



CREATE UNIQUE INDEX "uq_subscriptions_active_personal_by_user" ON "public"."subscriptions" USING "btree" ("user_id") WHERE (("tenant_id" IS NULL) AND ("status" = 'active'::"text"));



CREATE UNIQUE INDEX "uq_tenant_invites_pending" ON "public"."tenant_invites" USING "btree" ("tenant_id", "lower"("email"), "role") WHERE (("accepted_at" IS NULL) AND ("revoked_at" IS NULL));



CREATE UNIQUE INDEX "uq_tenant_members_tenant_user" ON "public"."tenant_members" USING "btree" ("tenant_id", "user_id");



CREATE UNIQUE INDEX "ux_subscriptions_active_per_personal_user" ON "public"."subscriptions" USING "btree" ("user_id") WHERE (("status" = 'active'::"text") AND ("tenant_id" IS NULL));



CREATE UNIQUE INDEX "ux_subscriptions_active_per_tenant" ON "public"."subscriptions" USING "btree" ("tenant_id") WHERE (("status" = 'active'::"text") AND ("tenant_id" IS NOT NULL));



CREATE OR REPLACE TRIGGER "agenda_bloqueios_updated_at" BEFORE UPDATE ON "public"."agenda_bloqueios" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "agendador_slug_trigger" BEFORE INSERT OR UPDATE ON "public"."agendador_configuracoes" FOR EACH ROW EXECUTE FUNCTION "public"."agendador_gerar_slug"();



CREATE OR REPLACE TRIGGER "prevent_saas_membership_trigger" BEFORE INSERT ON "public"."tenant_members" FOR EACH ROW EXECUTE FUNCTION "public"."prevent_saas_membership"();



CREATE OR REPLACE TRIGGER "tg_agenda_configuracoes_updated_at" BEFORE UPDATE ON "public"."agenda_configuracoes" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "tg_agenda_eventos_updated_at" BEFORE UPDATE ON "public"."agenda_eventos" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "tg_agenda_excecoes_updated_at" BEFORE UPDATE ON "public"."agenda_excecoes" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "tg_agenda_regras_semanais_updated_at" BEFORE UPDATE ON "public"."agenda_regras_semanais" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "tg_recurrence_rules_updated_at" BEFORE UPDATE ON "public"."recurrence_rules" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at_recurrence"();



CREATE OR REPLACE TRIGGER "tr_plan_public_updated_at" BEFORE UPDATE ON "public"."plan_public" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_account_type_immutable" BEFORE UPDATE OF "account_type" ON "public"."profiles" FOR EACH ROW EXECUTE FUNCTION "public"."guard_account_type_immutable"();



CREATE OR REPLACE TRIGGER "trg_agenda_cfg_sync" BEFORE INSERT OR UPDATE ON "public"."agenda_configuracoes" FOR EACH ROW EXECUTE FUNCTION "public"."agenda_cfg_sync"();



CREATE OR REPLACE TRIGGER "trg_agenda_eventos_busy_mirror_del" AFTER DELETE ON "public"."agenda_eventos" FOR EACH ROW WHEN ((("old"."mirror_of_event_id" IS NULL) AND ("old"."tenant_id" = "old"."owner_id"))) EXECUTE FUNCTION "public"."sync_busy_mirror_agenda_eventos"();



CREATE OR REPLACE TRIGGER "trg_agenda_eventos_busy_mirror_ins" AFTER INSERT ON "public"."agenda_eventos" FOR EACH ROW WHEN ((("new"."mirror_of_event_id" IS NULL) AND ("new"."tenant_id" = "new"."owner_id") AND ("new"."visibility_scope" = ANY (ARRAY['busy_only'::"text", 'private'::"text"])))) EXECUTE FUNCTION "public"."sync_busy_mirror_agenda_eventos"();



CREATE OR REPLACE TRIGGER "trg_agenda_eventos_busy_mirror_upd" AFTER UPDATE ON "public"."agenda_eventos" FOR EACH ROW WHEN ((("new"."mirror_of_event_id" IS NULL) AND ("new"."tenant_id" = "new"."owner_id") AND (("new"."visibility_scope" IS DISTINCT FROM "old"."visibility_scope") OR ("new"."inicio_em" IS DISTINCT FROM "old"."inicio_em") OR ("new"."fim_em" IS DISTINCT FROM "old"."fim_em") OR ("new"."owner_id" IS DISTINCT FROM "old"."owner_id") OR ("new"."tenant_id" IS DISTINCT FROM "old"."tenant_id")))) EXECUTE FUNCTION "public"."sync_busy_mirror_agenda_eventos"();



CREATE OR REPLACE TRIGGER "trg_agenda_regras_semanais_no_overlap" BEFORE INSERT OR UPDATE ON "public"."agenda_regras_semanais" FOR EACH ROW EXECUTE FUNCTION "public"."fn_agenda_regras_semanais_no_overlap"();



CREATE OR REPLACE TRIGGER "trg_determined_commitment_fields_updated_at" BEFORE UPDATE ON "public"."determined_commitment_fields" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_determined_commitments_updated_at" BEFORE UPDATE ON "public"."determined_commitments" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_no_change_core_plan_key" BEFORE UPDATE ON "public"."plans" FOR EACH ROW EXECUTE FUNCTION "public"."guard_no_change_core_plan_key"();



CREATE OR REPLACE TRIGGER "trg_no_change_plan_target" BEFORE UPDATE ON "public"."plans" FOR EACH ROW EXECUTE FUNCTION "public"."guard_no_change_plan_target"();



CREATE OR REPLACE TRIGGER "trg_no_delete_core_plans" BEFORE DELETE ON "public"."plans" FOR EACH ROW EXECUTE FUNCTION "public"."guard_no_delete_core_plans"();



CREATE OR REPLACE TRIGGER "trg_patient_cannot_own_tenant" BEFORE INSERT OR UPDATE ON "public"."tenant_members" FOR EACH ROW EXECUTE FUNCTION "public"."guard_patient_cannot_own_tenant"();



CREATE OR REPLACE TRIGGER "trg_patient_groups_set_updated_at" BEFORE UPDATE ON "public"."patient_groups" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_patient_intake_requests_updated_at" BEFORE UPDATE ON "public"."patient_intake_requests" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_patient_tags_set_updated_at" BEFORE UPDATE ON "public"."patient_tags" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_patients_updated_at" BEFORE UPDATE ON "public"."patients" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_patients_validate_members" BEFORE INSERT OR UPDATE OF "tenant_id", "responsible_member_id", "patient_scope", "therapist_member_id" ON "public"."patients" FOR EACH ROW EXECUTE FUNCTION "public"."patients_validate_member_consistency"();



CREATE OR REPLACE TRIGGER "trg_prevent_promoting_to_system" BEFORE UPDATE ON "public"."patient_groups" FOR EACH ROW EXECUTE FUNCTION "public"."prevent_promoting_to_system"();



CREATE OR REPLACE TRIGGER "trg_prevent_system_group_changes" BEFORE DELETE OR UPDATE ON "public"."patient_groups" FOR EACH ROW EXECUTE FUNCTION "public"."prevent_system_group_changes"();



CREATE OR REPLACE TRIGGER "trg_profiles_updated_at" BEFORE UPDATE ON "public"."profiles" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_subscription_intents_view_insert" INSTEAD OF INSERT ON "public"."subscription_intents" FOR EACH ROW EXECUTE FUNCTION "public"."subscription_intents_view_insert"();



CREATE OR REPLACE TRIGGER "trg_subscriptions_validate_scope" BEFORE INSERT OR UPDATE ON "public"."subscriptions" FOR EACH ROW EXECUTE FUNCTION "public"."subscriptions_validate_scope"();



CREATE OR REPLACE TRIGGER "trg_tenant_features_guard_with_plan" BEFORE INSERT OR UPDATE ON "public"."tenant_features" FOR EACH ROW EXECUTE FUNCTION "public"."tenant_features_guard_with_plan"();



CREATE OR REPLACE TRIGGER "trg_tenant_features_updated_at" BEFORE UPDATE ON "public"."tenant_features" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



CREATE OR REPLACE TRIGGER "trg_tenant_kind_immutable" BEFORE UPDATE OF "kind" ON "public"."tenants" FOR EACH ROW EXECUTE FUNCTION "public"."guard_tenant_kind_immutable"();



CREATE OR REPLACE TRIGGER "trg_user_settings_updated_at" BEFORE UPDATE ON "public"."user_settings" FOR EACH ROW EXECUTE FUNCTION "public"."set_updated_at"();



ALTER TABLE ONLY "public"."agenda_bloqueios"
    ADD CONSTRAINT "agenda_bloqueios_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agenda_bloqueios"
    ADD CONSTRAINT "agenda_bloqueios_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."agenda_configuracoes"
    ADD CONSTRAINT "agenda_configuracoes_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agenda_eventos"
    ADD CONSTRAINT "agenda_eventos_determined_commitment_fk" FOREIGN KEY ("determined_commitment_id") REFERENCES "public"."determined_commitments"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."agenda_eventos"
    ADD CONSTRAINT "agenda_eventos_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "public"."patients"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."agenda_eventos"
    ADD CONSTRAINT "agenda_eventos_recurrence_id_fkey" FOREIGN KEY ("recurrence_id") REFERENCES "public"."recurrence_rules"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."agenda_eventos"
    ADD CONSTRAINT "agenda_eventos_terapeuta_fk" FOREIGN KEY ("terapeuta_id") REFERENCES "auth"."users"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."agenda_excecoes"
    ADD CONSTRAINT "agenda_excecoes_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agenda_online_slots"
    ADD CONSTRAINT "agenda_online_slots_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agenda_online_slots"
    ADD CONSTRAINT "agenda_online_slots_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agenda_regras_semanais"
    ADD CONSTRAINT "agenda_regras_semanais_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agenda_slots_bloqueados_semanais"
    ADD CONSTRAINT "agenda_slots_bloqueados_semanais_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agenda_slots_regras"
    ADD CONSTRAINT "agenda_slots_regras_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agendador_configuracoes"
    ADD CONSTRAINT "agendador_configuracoes_owner_fk" FOREIGN KEY ("owner_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agendador_configuracoes"
    ADD CONSTRAINT "agendador_configuracoes_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agendador_solicitacoes"
    ADD CONSTRAINT "agendador_sol_owner_fk" FOREIGN KEY ("owner_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."agendador_solicitacoes"
    ADD CONSTRAINT "agendador_sol_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."commitment_time_logs"
    ADD CONSTRAINT "commitment_time_logs_calendar_event_id_fkey" FOREIGN KEY ("calendar_event_id") REFERENCES "public"."agenda_eventos"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."commitment_time_logs"
    ADD CONSTRAINT "commitment_time_logs_commitment_id_fkey" FOREIGN KEY ("commitment_id") REFERENCES "public"."determined_commitments"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."commitment_time_logs"
    ADD CONSTRAINT "commitment_time_logs_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."determined_commitment_fields"
    ADD CONSTRAINT "determined_commitment_fields_commitment_id_fkey" FOREIGN KEY ("commitment_id") REFERENCES "public"."determined_commitments"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."determined_commitment_fields"
    ADD CONSTRAINT "determined_commitment_fields_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."determined_commitments"
    ADD CONSTRAINT "determined_commitments_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."feriados"
    ADD CONSTRAINT "feriados_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "auth"."users"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."feriados"
    ADD CONSTRAINT "feriados_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."module_features"
    ADD CONSTRAINT "module_features_feature_id_fkey" FOREIGN KEY ("feature_id") REFERENCES "public"."features"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."module_features"
    ADD CONSTRAINT "module_features_module_id_fkey" FOREIGN KEY ("module_id") REFERENCES "public"."modules"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_group_patient"
    ADD CONSTRAINT "patient_group_patient_patient_id_fkey" FOREIGN KEY ("patient_id") REFERENCES "public"."patients"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_group_patient"
    ADD CONSTRAINT "patient_group_patient_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_groups"
    ADD CONSTRAINT "patient_groups_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_intake_requests"
    ADD CONSTRAINT "patient_intake_requests_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_invites"
    ADD CONSTRAINT "patient_invites_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_patient_tag"
    ADD CONSTRAINT "patient_patient_tag_tag_id_fkey" FOREIGN KEY ("tag_id") REFERENCES "public"."patient_tags"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_patient_tag"
    ADD CONSTRAINT "patient_patient_tag_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_tags"
    ADD CONSTRAINT "patient_tags_tenant_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patients"
    ADD CONSTRAINT "patients_responsible_member_id_fkey" FOREIGN KEY ("responsible_member_id") REFERENCES "public"."tenant_members"("id") ON DELETE RESTRICT;



ALTER TABLE ONLY "public"."patients"
    ADD CONSTRAINT "patients_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patients"
    ADD CONSTRAINT "patients_therapist_member_id_fkey" FOREIGN KEY ("therapist_member_id") REFERENCES "public"."tenant_members"("id");



ALTER TABLE ONLY "public"."patients"
    ADD CONSTRAINT "patients_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."plan_features"
    ADD CONSTRAINT "plan_features_feature_id_fkey" FOREIGN KEY ("feature_id") REFERENCES "public"."features"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."plan_features"
    ADD CONSTRAINT "plan_features_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "public"."plans"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."plan_prices"
    ADD CONSTRAINT "plan_prices_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "public"."plans"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."plan_public_bullets"
    ADD CONSTRAINT "plan_public_bullets_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "public"."plans"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."plan_public"
    ADD CONSTRAINT "plan_public_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "public"."plans"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_patient_tag"
    ADD CONSTRAINT "ppt_patient_fk" FOREIGN KEY ("patient_id") REFERENCES "public"."patients"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."patient_patient_tag"
    ADD CONSTRAINT "ppt_tag_fk" FOREIGN KEY ("tag_id") REFERENCES "public"."patient_tags"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."profiles"
    ADD CONSTRAINT "profiles_id_fkey" FOREIGN KEY ("id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."recurrence_exceptions"
    ADD CONSTRAINT "recurrence_exceptions_agenda_evento_id_fkey" FOREIGN KEY ("agenda_evento_id") REFERENCES "public"."agenda_eventos"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."recurrence_exceptions"
    ADD CONSTRAINT "recurrence_exceptions_recurrence_id_fkey" FOREIGN KEY ("recurrence_id") REFERENCES "public"."recurrence_rules"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."saas_admins"
    ADD CONSTRAINT "saas_admins_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."saas_doc_votos"
    ADD CONSTRAINT "saas_doc_votos_doc_id_fkey" FOREIGN KEY ("doc_id") REFERENCES "public"."saas_docs"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."saas_doc_votos"
    ADD CONSTRAINT "saas_doc_votos_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."saas_faq_itens"
    ADD CONSTRAINT "saas_faq_itens_doc_id_fkey" FOREIGN KEY ("doc_id") REFERENCES "public"."saas_docs"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."subscription_intents_personal"
    ADD CONSTRAINT "sint_personal_subscription_id_fkey" FOREIGN KEY ("subscription_id") REFERENCES "public"."subscriptions"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."subscription_intents_tenant"
    ADD CONSTRAINT "sint_tenant_subscription_id_fkey" FOREIGN KEY ("subscription_id") REFERENCES "public"."subscriptions"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."subscription_events"
    ADD CONSTRAINT "subscription_events_subscription_id_fkey" FOREIGN KEY ("subscription_id") REFERENCES "public"."subscriptions"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."subscription_intents_personal"
    ADD CONSTRAINT "subscription_intents_personal_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "public"."plans"("id") ON DELETE RESTRICT;



ALTER TABLE ONLY "public"."subscription_intents_tenant"
    ADD CONSTRAINT "subscription_intents_tenant_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "public"."plans"("id") ON DELETE RESTRICT;



ALTER TABLE ONLY "public"."subscription_intents_legacy"
    ADD CONSTRAINT "subscription_intents_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."subscriptions"
    ADD CONSTRAINT "subscriptions_owner_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."subscriptions"
    ADD CONSTRAINT "subscriptions_plan_id_fkey" FOREIGN KEY ("plan_id") REFERENCES "public"."plans"("id") ON DELETE RESTRICT;



ALTER TABLE ONLY "public"."tenant_features"
    ADD CONSTRAINT "tenant_features_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."tenant_invites"
    ADD CONSTRAINT "tenant_invites_accepted_by_fkey" FOREIGN KEY ("accepted_by") REFERENCES "auth"."users"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."tenant_invites"
    ADD CONSTRAINT "tenant_invites_invited_by_fkey" FOREIGN KEY ("invited_by") REFERENCES "auth"."users"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."tenant_invites"
    ADD CONSTRAINT "tenant_invites_revoked_by_fkey" FOREIGN KEY ("revoked_by") REFERENCES "auth"."users"("id") ON DELETE SET NULL;



ALTER TABLE ONLY "public"."tenant_invites"
    ADD CONSTRAINT "tenant_invites_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."tenant_members"
    ADD CONSTRAINT "tenant_members_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."tenant_members"
    ADD CONSTRAINT "tenant_members_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."tenant_modules"
    ADD CONSTRAINT "tenant_modules_module_id_fkey" FOREIGN KEY ("module_id") REFERENCES "public"."modules"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."tenant_modules"
    ADD CONSTRAINT "tenant_modules_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE ONLY "public"."user_settings"
    ADD CONSTRAINT "user_settings_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE CASCADE;



ALTER TABLE "public"."agenda_bloqueios" ENABLE ROW LEVEL SECURITY;


ALTER TABLE "public"."agenda_configuracoes" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "agenda_configuracoes_clinic_read" ON "public"."agenda_configuracoes" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.view'::"text")));



CREATE POLICY "agenda_configuracoes_clinic_write" ON "public"."agenda_configuracoes" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text")));



CREATE POLICY "agenda_configuracoes_owner" ON "public"."agenda_configuracoes" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



ALTER TABLE "public"."agenda_eventos" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "agenda_eventos_delete" ON "public"."agenda_eventos" FOR DELETE USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.delete'::"text")));



CREATE POLICY "agenda_eventos_insert" ON "public"."agenda_eventos" FOR INSERT WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.create'::"text")));



CREATE POLICY "agenda_eventos_owner_all" ON "public"."agenda_eventos" TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "agenda_eventos_select" ON "public"."agenda_eventos" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.view'::"text")));



CREATE POLICY "agenda_eventos_update" ON "public"."agenda_eventos" FOR UPDATE USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text")));



ALTER TABLE "public"."agenda_excecoes" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "agenda_excecoes_owner" ON "public"."agenda_excecoes" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "agenda_excecoes_select" ON "public"."agenda_excecoes" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.view'::"text")));



CREATE POLICY "agenda_excecoes_write" ON "public"."agenda_excecoes" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text")));



ALTER TABLE "public"."agenda_online_slots" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "agenda_online_slots_owner" ON "public"."agenda_online_slots" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "agenda_online_slots_select" ON "public"."agenda_online_slots" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.view'::"text")));



CREATE POLICY "agenda_online_slots_write" ON "public"."agenda_online_slots" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text")));



ALTER TABLE "public"."agenda_regras_semanais" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "agenda_regras_semanais_owner" ON "public"."agenda_regras_semanais" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "agenda_regras_semanais_select" ON "public"."agenda_regras_semanais" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.view'::"text")));



CREATE POLICY "agenda_regras_semanais_write" ON "public"."agenda_regras_semanais" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text")));



ALTER TABLE "public"."agenda_slots_bloqueados_semanais" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "agenda_slots_bloqueados_semanais_select" ON "public"."agenda_slots_bloqueados_semanais" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.view'::"text")));



CREATE POLICY "agenda_slots_bloqueados_semanais_write" ON "public"."agenda_slots_bloqueados_semanais" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text")));



ALTER TABLE "public"."agenda_slots_regras" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "agenda_slots_regras_select" ON "public"."agenda_slots_regras" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.view'::"text")));



CREATE POLICY "agenda_slots_regras_write" ON "public"."agenda_slots_regras" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text")));



CREATE POLICY "agendador_cfg_public_read" ON "public"."agendador_configuracoes" FOR SELECT TO "anon" USING ((("ativo" = true) AND ("link_slug" IS NOT NULL)));



CREATE POLICY "agendador_cfg_select" ON "public"."agendador_configuracoes" FOR SELECT USING (("auth"."uid"() = "owner_id"));



CREATE POLICY "agendador_cfg_write" ON "public"."agendador_configuracoes" USING (("auth"."uid"() = "owner_id")) WITH CHECK (("auth"."uid"() = "owner_id"));



ALTER TABLE "public"."agendador_configuracoes" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "agendador_sol_owner_select" ON "public"."agendador_solicitacoes" FOR SELECT USING (("auth"."uid"() = "owner_id"));



CREATE POLICY "agendador_sol_owner_write" ON "public"."agendador_solicitacoes" USING (("auth"."uid"() = "owner_id")) WITH CHECK (("auth"."uid"() = "owner_id"));



CREATE POLICY "agendador_sol_patient_read" ON "public"."agendador_solicitacoes" FOR SELECT TO "authenticated" USING ((("auth"."uid"() = "user_id") OR ("auth"."uid"() = "owner_id")));



CREATE POLICY "agendador_sol_public_insert" ON "public"."agendador_solicitacoes" FOR INSERT TO "anon" WITH CHECK (true);



ALTER TABLE "public"."agendador_solicitacoes" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "bloqueios_delete" ON "public"."agenda_bloqueios" FOR DELETE TO "authenticated" USING (("owner_id" = "auth"."uid"()));



CREATE POLICY "bloqueios_insert" ON "public"."agenda_bloqueios" FOR INSERT TO "authenticated" WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "bloqueios_select_clinic" ON "public"."agenda_bloqueios" FOR SELECT TO "authenticated" USING (("tenant_id" IN ( SELECT "tenant_members"."tenant_id"
   FROM "public"."tenant_members"
  WHERE (("tenant_members"."user_id" = "auth"."uid"()) AND ("tenant_members"."role" = ANY (ARRAY['admin'::"text", 'clinic_admin'::"text", 'tenant_admin'::"text", 'secretary'::"text"]))))));



CREATE POLICY "bloqueios_select_own" ON "public"."agenda_bloqueios" FOR SELECT TO "authenticated" USING (("owner_id" = "auth"."uid"()));



CREATE POLICY "bloqueios_update" ON "public"."agenda_bloqueios" FOR UPDATE TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



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" = ANY (ARRAY['clinic_admin'::"text", 'tenant_admin'::"text"])))))));



ALTER TABLE "public"."commitment_time_logs" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "ctl_delete_for_active_member" ON "public"."commitment_time_logs" FOR DELETE TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "commitment_time_logs"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "ctl_insert_for_active_member" ON "public"."commitment_time_logs" FOR INSERT TO "authenticated" WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "commitment_time_logs"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "ctl_select_for_active_member" ON "public"."commitment_time_logs" FOR SELECT TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "commitment_time_logs"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "ctl_update_for_active_member" ON "public"."commitment_time_logs" FOR UPDATE TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "commitment_time_logs"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text"))))) WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "commitment_time_logs"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "dc_delete_custom_for_active_member" ON "public"."determined_commitments" FOR DELETE TO "authenticated" USING ((("is_native" = false) AND (EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitments"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text"))))));



CREATE POLICY "dc_insert_for_active_member" ON "public"."determined_commitments" FOR INSERT TO "authenticated" WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitments"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "dc_select_for_active_member" ON "public"."determined_commitments" FOR SELECT TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitments"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "dc_update_for_active_member" ON "public"."determined_commitments" FOR UPDATE TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitments"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text"))))) WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitments"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "dcf_delete_for_active_member" ON "public"."determined_commitment_fields" FOR DELETE TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitment_fields"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "dcf_insert_for_active_member" ON "public"."determined_commitment_fields" FOR INSERT TO "authenticated" WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitment_fields"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "dcf_select_for_active_member" ON "public"."determined_commitment_fields" FOR SELECT TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitment_fields"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "dcf_update_for_active_member" ON "public"."determined_commitment_fields" FOR UPDATE TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitment_fields"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text"))))) WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "determined_commitment_fields"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text")))));



CREATE POLICY "delete own" ON "public"."agenda_bloqueios" FOR DELETE USING (("owner_id" = "auth"."uid"()));



ALTER TABLE "public"."determined_commitment_fields" ENABLE ROW LEVEL SECURITY;


ALTER TABLE "public"."determined_commitments" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "dev_creds_select_saas_admin" ON "public"."dev_user_credentials" FOR SELECT TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."profiles" "p"
  WHERE (("p"."id" = "auth"."uid"()) AND ("p"."role" = 'saas_admin'::"text")))));



CREATE POLICY "dev_creds_write_saas_admin" ON "public"."dev_user_credentials" TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."profiles" "p"
  WHERE (("p"."id" = "auth"."uid"()) AND ("p"."role" = 'saas_admin'::"text"))))) WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."profiles" "p"
  WHERE (("p"."id" = "auth"."uid"()) AND ("p"."role" = 'saas_admin'::"text")))));



ALTER TABLE "public"."dev_user_credentials" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "ent_inv_select_own" ON "public"."entitlements_invalidation" FOR SELECT USING ((("owner_id" = "auth"."uid"()) OR "public"."is_saas_admin"()));



CREATE POLICY "ent_inv_update_saas" ON "public"."entitlements_invalidation" FOR UPDATE USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



CREATE POLICY "ent_inv_write_saas" ON "public"."entitlements_invalidation" FOR INSERT WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."entitlements_invalidation" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "faq_admin_write" ON "public"."saas_faq" TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."profiles"
  WHERE (("profiles"."id" = "auth"."uid"()) AND ("profiles"."role" = ANY (ARRAY['saas_admin'::"text", 'tenant_admin'::"text", 'clinic_admin'::"text"]))))));



CREATE POLICY "faq_auth_read" ON "public"."saas_faq" FOR SELECT TO "authenticated" USING (("ativo" = true));



CREATE POLICY "faq_itens_admin_write" ON "public"."saas_faq_itens" TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."profiles"
  WHERE (("profiles"."id" = "auth"."uid"()) AND ("profiles"."role" = ANY (ARRAY['saas_admin'::"text", 'tenant_admin'::"text", 'clinic_admin'::"text"]))))));



CREATE POLICY "faq_itens_auth_read" ON "public"."saas_faq_itens" FOR SELECT TO "authenticated" USING ((("ativo" = true) AND (EXISTS ( SELECT 1
   FROM "public"."saas_docs" "d"
  WHERE (("d"."id" = "saas_faq_itens"."doc_id") AND ("d"."ativo" = true))))));



CREATE POLICY "faq_public_read" ON "public"."saas_faq" FOR SELECT USING ((("publico" = true) AND ("ativo" = true)));



ALTER TABLE "public"."features" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "features_read_authenticated" ON "public"."features" FOR SELECT TO "authenticated" USING (true);



CREATE POLICY "features_write_saas_admin" ON "public"."features" TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."feriados" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "feriados_delete" ON "public"."feriados" FOR DELETE USING (("owner_id" = "auth"."uid"()));



CREATE POLICY "feriados_global_select" ON "public"."feriados" FOR SELECT USING (("tenant_id" IS NULL));



CREATE POLICY "feriados_insert" ON "public"."feriados" FOR INSERT WITH CHECK (("tenant_id" IN ( SELECT "tenant_members"."tenant_id"
   FROM "public"."tenant_members"
  WHERE ("tenant_members"."user_id" = "auth"."uid"()))));



CREATE POLICY "feriados_saas_delete" ON "public"."feriados" FOR DELETE USING ((EXISTS ( SELECT 1
   FROM "public"."saas_admins"
  WHERE ("saas_admins"."user_id" = "auth"."uid"()))));



CREATE POLICY "feriados_saas_insert" ON "public"."feriados" FOR INSERT WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."saas_admins"
  WHERE ("saas_admins"."user_id" = "auth"."uid"()))));



CREATE POLICY "feriados_saas_select" ON "public"."feriados" FOR SELECT USING ((EXISTS ( SELECT 1
   FROM "public"."saas_admins"
  WHERE ("saas_admins"."user_id" = "auth"."uid"()))));



CREATE POLICY "feriados_select" ON "public"."feriados" FOR SELECT USING (("tenant_id" IN ( SELECT "tenant_members"."tenant_id"
   FROM "public"."tenant_members"
  WHERE ("tenant_members"."user_id" = "auth"."uid"()))));



CREATE POLICY "insert own" ON "public"."agenda_bloqueios" FOR INSERT WITH CHECK (("owner_id" = "auth"."uid"()));



ALTER TABLE "public"."module_features" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "module_features_read_authenticated" ON "public"."module_features" FOR SELECT TO "authenticated" USING (true);



CREATE POLICY "module_features_write_saas_admin" ON "public"."module_features" TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."modules" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "modules_read_authenticated" ON "public"."modules" FOR SELECT TO "authenticated" USING (true);



CREATE POLICY "modules_write_saas_admin" ON "public"."modules" TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."owner_users" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "owner_users: user can read own links" ON "public"."owner_users" FOR SELECT TO "authenticated" USING (("user_id" = "auth"."uid"()));



ALTER TABLE "public"."patient_group_patient" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "patient_group_patient_owner_all" ON "public"."patient_group_patient" 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"())))));



CREATE POLICY "patient_group_patient_select" ON "public"."patient_group_patient" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.view'::"text")));



CREATE POLICY "patient_group_patient_write" ON "public"."patient_group_patient" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text")));



ALTER TABLE "public"."patient_groups" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "patient_groups_owner_all" ON "public"."patient_groups" TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "patient_groups_select" ON "public"."patient_groups" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.view'::"text")));



CREATE POLICY "patient_groups_write" ON "public"."patient_groups" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text")));



ALTER TABLE "public"."patient_intake_requests" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "patient_intake_requests_owner_all" ON "public"."patient_intake_requests" TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "patient_intake_requests_select" ON "public"."patient_intake_requests" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.view'::"text")));



CREATE POLICY "patient_intake_requests_write" ON "public"."patient_intake_requests" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text")));



ALTER TABLE "public"."patient_invites" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "patient_invites_owner_all" ON "public"."patient_invites" TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "patient_invites_select" ON "public"."patient_invites" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.view'::"text")));



CREATE POLICY "patient_invites_write" ON "public"."patient_invites" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text")));



ALTER TABLE "public"."patient_patient_tag" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "patient_patient_tag_owner_all" ON "public"."patient_patient_tag" TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "patient_patient_tag_select" ON "public"."patient_patient_tag" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.view'::"text")));



CREATE POLICY "patient_patient_tag_write" ON "public"."patient_patient_tag" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text")));



ALTER TABLE "public"."patient_tags" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "patient_tags_owner_all" ON "public"."patient_tags" TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "patient_tags_select" ON "public"."patient_tags" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.view'::"text")));



CREATE POLICY "patient_tags_write" ON "public"."patient_tags" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text")));



ALTER TABLE "public"."patients" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "patients_delete" ON "public"."patients" FOR DELETE USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.delete'::"text")));



CREATE POLICY "patients_insert" ON "public"."patients" FOR INSERT WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.create'::"text")));



CREATE POLICY "patients_owner_all" ON "public"."patients" TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "patients_select" ON "public"."patients" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.view'::"text")));



CREATE POLICY "patients_update" ON "public"."patients" FOR UPDATE USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'patients.edit'::"text")));



ALTER TABLE "public"."plan_features" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "plan_features_read_authenticated" ON "public"."plan_features" FOR SELECT TO "authenticated" USING (true);



CREATE POLICY "plan_features_write_saas_admin" ON "public"."plan_features" TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."plans" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "plans_read_authenticated" ON "public"."plans" FOR SELECT TO "authenticated" USING (true);



CREATE POLICY "plans_write_saas_admin" ON "public"."plans" TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."profiles" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "profiles_insert_own" ON "public"."profiles" FOR INSERT WITH CHECK (("id" = "auth"."uid"()));



CREATE POLICY "profiles_read_saas_admin" ON "public"."profiles" FOR SELECT USING ("public"."is_saas_admin"());



CREATE POLICY "profiles_select_own" ON "public"."profiles" FOR SELECT USING (("id" = "auth"."uid"()));



CREATE POLICY "profiles_update_own" ON "public"."profiles" FOR UPDATE USING (("id" = "auth"."uid"())) WITH CHECK (("id" = "auth"."uid"()));



CREATE POLICY "read features (auth)" ON "public"."features" FOR SELECT TO "authenticated" USING (true);



CREATE POLICY "read plan_features (auth)" ON "public"."plan_features" FOR SELECT TO "authenticated" USING (true);



CREATE POLICY "read plans (auth)" ON "public"."plans" FOR SELECT TO "authenticated" USING (true);



ALTER TABLE "public"."recurrence_exceptions" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "recurrence_exceptions_tenant" ON "public"."recurrence_exceptions" TO "authenticated" USING (("tenant_id" IN ( SELECT "tenant_members"."tenant_id"
   FROM "public"."tenant_members"
  WHERE ("tenant_members"."user_id" = "auth"."uid"())))) WITH CHECK (("tenant_id" IN ( SELECT "tenant_members"."tenant_id"
   FROM "public"."tenant_members"
  WHERE ("tenant_members"."user_id" = "auth"."uid"()))));



ALTER TABLE "public"."recurrence_rules" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "recurrence_rules_clinic_read" ON "public"."recurrence_rules" FOR SELECT USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.view'::"text")));



CREATE POLICY "recurrence_rules_clinic_write" ON "public"."recurrence_rules" USING (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text"))) WITH CHECK (("public"."is_clinic_tenant"("tenant_id") AND "public"."is_tenant_member"("tenant_id") AND "public"."tenant_has_feature"("tenant_id", 'agenda.edit'::"text")));



CREATE POLICY "recurrence_rules_owner" ON "public"."recurrence_rules" TO "authenticated" USING (("owner_id" = "auth"."uid"())) WITH CHECK (("owner_id" = "auth"."uid"()));



CREATE POLICY "saas_admin can read subscription_intents" ON "public"."subscription_intents_legacy" FOR SELECT TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."saas_admins" "a"
  WHERE ("a"."user_id" = "auth"."uid"()))));



CREATE POLICY "saas_admin can update subscription_intents" ON "public"."subscription_intents_legacy" FOR UPDATE TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."saas_admins" "a"
  WHERE ("a"."user_id" = "auth"."uid"())))) WITH CHECK ((EXISTS ( SELECT 1
   FROM "public"."saas_admins" "a"
  WHERE ("a"."user_id" = "auth"."uid"()))));



CREATE POLICY "saas_admin_full_access" ON "public"."saas_docs" 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"()))));



ALTER TABLE "public"."saas_admins" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "saas_admins_select_self" ON "public"."saas_admins" FOR SELECT TO "authenticated" USING (("user_id" = "auth"."uid"()));



ALTER TABLE "public"."saas_doc_votos" ENABLE ROW LEVEL SECURITY;


ALTER TABLE "public"."saas_docs" ENABLE ROW LEVEL SECURITY;


ALTER TABLE "public"."saas_faq" ENABLE ROW LEVEL SECURITY;


ALTER TABLE "public"."saas_faq_itens" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "select own" ON "public"."agenda_bloqueios" FOR SELECT USING (("owner_id" = "auth"."uid"()));



ALTER TABLE "public"."subscription_events" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "subscription_events_read_saas" ON "public"."subscription_events" FOR SELECT USING ("public"."is_saas_admin"());



CREATE POLICY "subscription_events_write_saas" ON "public"."subscription_events" FOR INSERT WITH CHECK ("public"."is_saas_admin"());



CREATE POLICY "subscription_intents_insert_own" ON "public"."subscription_intents_legacy" FOR INSERT TO "authenticated" WITH CHECK (("user_id" = "auth"."uid"()));



ALTER TABLE "public"."subscription_intents_legacy" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "subscription_intents_select_own" ON "public"."subscription_intents_legacy" FOR SELECT TO "authenticated" USING (("user_id" = "auth"."uid"()));



ALTER TABLE "public"."subscriptions" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "subscriptions read own" ON "public"."subscriptions" FOR SELECT TO "authenticated" USING (("user_id" = "auth"."uid"()));



CREATE POLICY "subscriptions: read if linked owner_users" ON "public"."subscriptions" FOR SELECT TO "authenticated" USING ((EXISTS ( SELECT 1
   FROM "public"."owner_users" "ou"
  WHERE (("ou"."owner_id" = "subscriptions"."user_id") AND ("ou"."user_id" = "auth"."uid"())))));



CREATE POLICY "subscriptions_insert_own_personal" ON "public"."subscriptions" FOR INSERT TO "authenticated" WITH CHECK ((("user_id" = "auth"."uid"()) AND ("tenant_id" IS NULL)));



CREATE POLICY "subscriptions_no_direct_update" ON "public"."subscriptions" FOR UPDATE TO "authenticated" USING (false) WITH CHECK (false);



CREATE POLICY "subscriptions_read_own" ON "public"."subscriptions" FOR SELECT TO "authenticated" USING ((("user_id" = "auth"."uid"()) OR "public"."is_saas_admin"()));



CREATE POLICY "subscriptions_select_for_tenant_members" ON "public"."subscriptions" FOR SELECT TO "authenticated" USING ((("tenant_id" IS NOT NULL) AND (EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "subscriptions"."tenant_id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text"))))));



CREATE POLICY "subscriptions_select_own_personal" ON "public"."subscriptions" FOR SELECT TO "authenticated" USING ((("user_id" = "auth"."uid"()) AND ("tenant_id" IS NULL)));



CREATE POLICY "subscriptions_update_only_saas_admin" ON "public"."subscriptions" FOR UPDATE TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."tenant_members" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "tenant_members_write_saas" ON "public"."tenant_members" TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."tenant_modules" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "tenant_modules_read_own" ON "public"."tenant_modules" FOR SELECT TO "authenticated" USING ((("owner_id" = "auth"."uid"()) OR "public"."is_saas_admin"()));



CREATE POLICY "tenant_modules_write_saas" ON "public"."tenant_modules" TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



ALTER TABLE "public"."tenants" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "tenants_read_members" ON "public"."tenants" FOR SELECT TO "authenticated" USING (("public"."is_saas_admin"() OR (EXISTS ( SELECT 1
   FROM "public"."tenant_members" "tm"
  WHERE (("tm"."tenant_id" = "tenants"."id") AND ("tm"."user_id" = "auth"."uid"()) AND ("tm"."status" = 'active'::"text"))))));



CREATE POLICY "tenants_write_saas" ON "public"."tenants" TO "authenticated" USING ("public"."is_saas_admin"()) WITH CHECK ("public"."is_saas_admin"());



CREATE POLICY "tm_select_admin_all_members" ON "public"."tenant_members" FOR SELECT TO "authenticated" USING ("public"."is_tenant_admin"("tenant_id"));



CREATE POLICY "tm_select_own_membership" ON "public"."tenant_members" FOR SELECT TO "authenticated" USING (("user_id" = "auth"."uid"()));



CREATE POLICY "update own" ON "public"."agenda_bloqueios" FOR UPDATE USING (("owner_id" = "auth"."uid"()));



ALTER TABLE "public"."user_settings" ENABLE ROW LEVEL SECURITY;


CREATE POLICY "user_settings_insert_own" ON "public"."user_settings" FOR INSERT WITH CHECK (("user_id" = "auth"."uid"()));



CREATE POLICY "user_settings_select_own" ON "public"."user_settings" FOR SELECT USING (("user_id" = "auth"."uid"()));



CREATE POLICY "user_settings_update_own" ON "public"."user_settings" FOR UPDATE USING (("user_id" = "auth"."uid"())) WITH CHECK (("user_id" = "auth"."uid"()));



CREATE POLICY "users_read_usuario_docs" ON "public"."saas_docs" FOR SELECT TO "authenticated" USING ((("ativo" = true) AND ("tipo_acesso" = 'usuario'::"text")));



CREATE POLICY "votos_select_own" ON "public"."saas_doc_votos" FOR SELECT TO "authenticated" USING (("user_id" = "auth"."uid"()));



CREATE POLICY "votos_upsert_own" ON "public"."saas_doc_votos" TO "authenticated" USING (("user_id" = "auth"."uid"())) WITH CHECK (("user_id" = "auth"."uid"()));





ALTER PUBLICATION "supabase_realtime" OWNER TO "postgres";





GRANT USAGE ON SCHEMA "public" TO "postgres";
GRANT USAGE ON SCHEMA "public" TO "anon";
GRANT USAGE ON SCHEMA "public" TO "authenticated";
GRANT USAGE ON SCHEMA "public" TO "service_role";



GRANT ALL ON FUNCTION "public"."citextin"("cstring") TO "postgres";
GRANT ALL ON FUNCTION "public"."citextin"("cstring") TO "anon";
GRANT ALL ON FUNCTION "public"."citextin"("cstring") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citextin"("cstring") TO "service_role";



GRANT ALL ON FUNCTION "public"."citextout"("public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citextout"("public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citextout"("public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citextout"("public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citextrecv"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."citextrecv"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."citextrecv"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citextrecv"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."citextsend"("public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citextsend"("public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citextsend"("public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citextsend"("public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey16_in"("cstring") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey16_in"("cstring") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey16_in"("cstring") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey16_in"("cstring") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey16_out"("public"."gbtreekey16") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey16_out"("public"."gbtreekey16") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey16_out"("public"."gbtreekey16") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey16_out"("public"."gbtreekey16") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey2_in"("cstring") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey2_in"("cstring") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey2_in"("cstring") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey2_in"("cstring") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey2_out"("public"."gbtreekey2") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey2_out"("public"."gbtreekey2") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey2_out"("public"."gbtreekey2") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey2_out"("public"."gbtreekey2") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey32_in"("cstring") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey32_in"("cstring") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey32_in"("cstring") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey32_in"("cstring") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey32_out"("public"."gbtreekey32") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey32_out"("public"."gbtreekey32") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey32_out"("public"."gbtreekey32") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey32_out"("public"."gbtreekey32") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey4_in"("cstring") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey4_in"("cstring") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey4_in"("cstring") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey4_in"("cstring") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey4_out"("public"."gbtreekey4") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey4_out"("public"."gbtreekey4") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey4_out"("public"."gbtreekey4") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey4_out"("public"."gbtreekey4") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey8_in"("cstring") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey8_in"("cstring") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey8_in"("cstring") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey8_in"("cstring") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey8_out"("public"."gbtreekey8") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey8_out"("public"."gbtreekey8") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey8_out"("public"."gbtreekey8") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey8_out"("public"."gbtreekey8") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey_var_in"("cstring") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey_var_in"("cstring") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey_var_in"("cstring") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey_var_in"("cstring") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbtreekey_var_out"("public"."gbtreekey_var") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbtreekey_var_out"("public"."gbtreekey_var") TO "anon";
GRANT ALL ON FUNCTION "public"."gbtreekey_var_out"("public"."gbtreekey_var") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbtreekey_var_out"("public"."gbtreekey_var") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_in"("cstring") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_in"("cstring") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_in"("cstring") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_in"("cstring") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_out"("public"."gtrgm") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_out"("public"."gtrgm") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_out"("public"."gtrgm") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_out"("public"."gtrgm") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext"(boolean) TO "postgres";
GRANT ALL ON FUNCTION "public"."citext"(boolean) TO "anon";
GRANT ALL ON FUNCTION "public"."citext"(boolean) TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext"(boolean) TO "service_role";



GRANT ALL ON FUNCTION "public"."citext"(character) TO "postgres";
GRANT ALL ON FUNCTION "public"."citext"(character) TO "anon";
GRANT ALL ON FUNCTION "public"."citext"(character) TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext"(character) TO "service_role";



GRANT ALL ON FUNCTION "public"."citext"("inet") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext"("inet") TO "anon";
GRANT ALL ON FUNCTION "public"."citext"("inet") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext"("inet") TO "service_role";































































































































































GRANT ALL ON FUNCTION "public"."__rls_ping"() TO "postgres";
GRANT ALL ON FUNCTION "public"."__rls_ping"() TO "anon";
GRANT ALL ON FUNCTION "public"."__rls_ping"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."__rls_ping"() TO "service_role";



GRANT ALL ON TABLE "public"."subscriptions" TO "postgres";
GRANT ALL ON TABLE "public"."subscriptions" TO "anon";
GRANT ALL ON TABLE "public"."subscriptions" TO "authenticated";
GRANT ALL ON TABLE "public"."subscriptions" TO "service_role";



GRANT ALL ON FUNCTION "public"."activate_subscription_from_intent"("p_intent_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."activate_subscription_from_intent"("p_intent_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."activate_subscription_from_intent"("p_intent_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."activate_subscription_from_intent"("p_intent_id" "uuid") TO "service_role";



REVOKE ALL ON FUNCTION "public"."admin_fix_plan_target"("p_plan_key" "text", "p_new_target" "text") FROM PUBLIC;
GRANT ALL ON FUNCTION "public"."admin_fix_plan_target"("p_plan_key" "text", "p_new_target" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."admin_fix_plan_target"("p_plan_key" "text", "p_new_target" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."admin_fix_plan_target"("p_plan_key" "text", "p_new_target" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."admin_fix_plan_target"("p_plan_key" "text", "p_new_target" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."agenda_cfg_sync"() TO "postgres";
GRANT ALL ON FUNCTION "public"."agenda_cfg_sync"() TO "anon";
GRANT ALL ON FUNCTION "public"."agenda_cfg_sync"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."agenda_cfg_sync"() TO "service_role";



GRANT ALL ON FUNCTION "public"."agendador_dias_disponiveis"("p_slug" "text", "p_ano" integer, "p_mes" integer) TO "postgres";
GRANT ALL ON FUNCTION "public"."agendador_dias_disponiveis"("p_slug" "text", "p_ano" integer, "p_mes" integer) TO "anon";
GRANT ALL ON FUNCTION "public"."agendador_dias_disponiveis"("p_slug" "text", "p_ano" integer, "p_mes" integer) TO "authenticated";
GRANT ALL ON FUNCTION "public"."agendador_dias_disponiveis"("p_slug" "text", "p_ano" integer, "p_mes" integer) TO "service_role";



GRANT ALL ON FUNCTION "public"."agendador_gerar_slug"() TO "postgres";
GRANT ALL ON FUNCTION "public"."agendador_gerar_slug"() TO "anon";
GRANT ALL ON FUNCTION "public"."agendador_gerar_slug"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."agendador_gerar_slug"() TO "service_role";



GRANT ALL ON FUNCTION "public"."agendador_slots_disponiveis"("p_slug" "text", "p_data" "date") TO "postgres";
GRANT ALL ON FUNCTION "public"."agendador_slots_disponiveis"("p_slug" "text", "p_data" "date") TO "anon";
GRANT ALL ON FUNCTION "public"."agendador_slots_disponiveis"("p_slug" "text", "p_data" "date") TO "authenticated";
GRANT ALL ON FUNCTION "public"."agendador_slots_disponiveis"("p_slug" "text", "p_data" "date") TO "service_role";



GRANT ALL ON FUNCTION "public"."cancel_recurrence_from"("p_recurrence_id" "uuid", "p_from_date" "date") TO "postgres";
GRANT ALL ON FUNCTION "public"."cancel_recurrence_from"("p_recurrence_id" "uuid", "p_from_date" "date") TO "anon";
GRANT ALL ON FUNCTION "public"."cancel_recurrence_from"("p_recurrence_id" "uuid", "p_from_date" "date") TO "authenticated";
GRANT ALL ON FUNCTION "public"."cancel_recurrence_from"("p_recurrence_id" "uuid", "p_from_date" "date") TO "service_role";



GRANT ALL ON FUNCTION "public"."cancel_subscription"("p_subscription_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."cancel_subscription"("p_subscription_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."cancel_subscription"("p_subscription_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."cancel_subscription"("p_subscription_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."cancelar_eventos_serie"("p_serie_id" "uuid", "p_a_partir_de" timestamp with time zone) TO "postgres";
GRANT ALL ON FUNCTION "public"."cancelar_eventos_serie"("p_serie_id" "uuid", "p_a_partir_de" timestamp with time zone) TO "anon";
GRANT ALL ON FUNCTION "public"."cancelar_eventos_serie"("p_serie_id" "uuid", "p_a_partir_de" timestamp with time zone) TO "authenticated";
GRANT ALL ON FUNCTION "public"."cancelar_eventos_serie"("p_serie_id" "uuid", "p_a_partir_de" timestamp with time zone) TO "service_role";



GRANT ALL ON FUNCTION "public"."cash_dist"("money", "money") TO "postgres";
GRANT ALL ON FUNCTION "public"."cash_dist"("money", "money") TO "anon";
GRANT ALL ON FUNCTION "public"."cash_dist"("money", "money") TO "authenticated";
GRANT ALL ON FUNCTION "public"."cash_dist"("money", "money") TO "service_role";



GRANT ALL ON FUNCTION "public"."change_subscription_plan"("p_subscription_id" "uuid", "p_new_plan_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."change_subscription_plan"("p_subscription_id" "uuid", "p_new_plan_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."change_subscription_plan"("p_subscription_id" "uuid", "p_new_plan_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."change_subscription_plan"("p_subscription_id" "uuid", "p_new_plan_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_cmp"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_cmp"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_cmp"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_cmp"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_eq"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_eq"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_eq"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_eq"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_ge"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_ge"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_ge"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_ge"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_gt"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_gt"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_gt"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_gt"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_hash"("public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_hash"("public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_hash"("public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_hash"("public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_hash_extended"("public"."citext", bigint) TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_hash_extended"("public"."citext", bigint) TO "anon";
GRANT ALL ON FUNCTION "public"."citext_hash_extended"("public"."citext", bigint) TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_hash_extended"("public"."citext", bigint) TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_larger"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_larger"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_larger"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_larger"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_le"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_le"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_le"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_le"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_lt"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_lt"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_lt"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_lt"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_ne"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_ne"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_ne"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_ne"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_pattern_cmp"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_pattern_cmp"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_pattern_cmp"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_pattern_cmp"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_pattern_ge"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_pattern_ge"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_pattern_ge"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_pattern_ge"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_pattern_gt"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_pattern_gt"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_pattern_gt"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_pattern_gt"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_pattern_le"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_pattern_le"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_pattern_le"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_pattern_le"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_pattern_lt"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_pattern_lt"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_pattern_lt"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_pattern_lt"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."citext_smaller"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."citext_smaller"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."citext_smaller"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."citext_smaller"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."create_clinic_tenant"("p_name" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."create_clinic_tenant"("p_name" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."create_clinic_tenant"("p_name" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."create_clinic_tenant"("p_name" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."create_patient_intake_request"("p_token" "text", "p_name" "text", "p_email" "text", "p_phone" "text", "p_notes" "text", "p_consent" boolean) TO "postgres";
GRANT ALL ON FUNCTION "public"."create_patient_intake_request"("p_token" "text", "p_name" "text", "p_email" "text", "p_phone" "text", "p_notes" "text", "p_consent" boolean) TO "anon";
GRANT ALL ON FUNCTION "public"."create_patient_intake_request"("p_token" "text", "p_name" "text", "p_email" "text", "p_phone" "text", "p_notes" "text", "p_consent" boolean) TO "authenticated";
GRANT ALL ON FUNCTION "public"."create_patient_intake_request"("p_token" "text", "p_name" "text", "p_email" "text", "p_phone" "text", "p_notes" "text", "p_consent" boolean) TO "service_role";



REVOKE ALL ON FUNCTION "public"."create_patient_intake_request_v2"("p_token" "text", "p_payload" "jsonb") FROM PUBLIC;
GRANT ALL ON FUNCTION "public"."create_patient_intake_request_v2"("p_token" "text", "p_payload" "jsonb") TO "postgres";
GRANT ALL ON FUNCTION "public"."create_patient_intake_request_v2"("p_token" "text", "p_payload" "jsonb") TO "anon";
GRANT ALL ON FUNCTION "public"."create_patient_intake_request_v2"("p_token" "text", "p_payload" "jsonb") TO "authenticated";
GRANT ALL ON FUNCTION "public"."create_patient_intake_request_v2"("p_token" "text", "p_payload" "jsonb") TO "service_role";



GRANT ALL ON FUNCTION "public"."current_member_id"("p_tenant_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."current_member_id"("p_tenant_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."current_member_id"("p_tenant_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."current_member_id"("p_tenant_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."current_member_role"("p_tenant_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."current_member_role"("p_tenant_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."current_member_role"("p_tenant_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."current_member_role"("p_tenant_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."date_dist"("date", "date") TO "postgres";
GRANT ALL ON FUNCTION "public"."date_dist"("date", "date") TO "anon";
GRANT ALL ON FUNCTION "public"."date_dist"("date", "date") TO "authenticated";
GRANT ALL ON FUNCTION "public"."date_dist"("date", "date") TO "service_role";



GRANT ALL ON FUNCTION "public"."delete_commitment_full"("p_tenant_id" "uuid", "p_commitment_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."delete_commitment_full"("p_tenant_id" "uuid", "p_commitment_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."delete_commitment_full"("p_tenant_id" "uuid", "p_commitment_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."delete_determined_commitment"("p_tenant_id" "uuid", "p_commitment_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."delete_determined_commitment"("p_tenant_id" "uuid", "p_commitment_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."delete_determined_commitment"("p_tenant_id" "uuid", "p_commitment_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."delete_determined_commitment"("p_tenant_id" "uuid", "p_commitment_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."dev_list_auth_users"("p_limit" integer) TO "postgres";
GRANT ALL ON FUNCTION "public"."dev_list_auth_users"("p_limit" integer) TO "anon";
GRANT ALL ON FUNCTION "public"."dev_list_auth_users"("p_limit" integer) TO "authenticated";
GRANT ALL ON FUNCTION "public"."dev_list_auth_users"("p_limit" integer) TO "service_role";



REVOKE ALL ON FUNCTION "public"."dev_list_custom_users"() FROM PUBLIC;
GRANT ALL ON FUNCTION "public"."dev_list_custom_users"() TO "postgres";
GRANT ALL ON FUNCTION "public"."dev_list_custom_users"() TO "anon";
GRANT ALL ON FUNCTION "public"."dev_list_custom_users"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."dev_list_custom_users"() TO "service_role";



REVOKE ALL ON FUNCTION "public"."dev_list_intent_leads"() FROM PUBLIC;
GRANT ALL ON FUNCTION "public"."dev_list_intent_leads"() TO "postgres";
GRANT ALL ON FUNCTION "public"."dev_list_intent_leads"() TO "anon";
GRANT ALL ON FUNCTION "public"."dev_list_intent_leads"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."dev_list_intent_leads"() TO "service_role";



GRANT ALL ON FUNCTION "public"."dev_public_debug_snapshot"() TO "postgres";
GRANT ALL ON FUNCTION "public"."dev_public_debug_snapshot"() TO "anon";
GRANT ALL ON FUNCTION "public"."dev_public_debug_snapshot"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."dev_public_debug_snapshot"() TO "service_role";



GRANT ALL ON FUNCTION "public"."ensure_personal_tenant"() TO "postgres";
GRANT ALL ON FUNCTION "public"."ensure_personal_tenant"() TO "anon";
GRANT ALL ON FUNCTION "public"."ensure_personal_tenant"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."ensure_personal_tenant"() TO "service_role";



GRANT ALL ON FUNCTION "public"."ensure_personal_tenant_for_user"("p_user_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."ensure_personal_tenant_for_user"("p_user_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."ensure_personal_tenant_for_user"("p_user_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."ensure_personal_tenant_for_user"("p_user_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."faq_votar"("faq_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."faq_votar"("faq_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."faq_votar"("faq_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."faq_votar"("faq_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."fix_all_subscription_mismatches"() TO "postgres";
GRANT ALL ON FUNCTION "public"."fix_all_subscription_mismatches"() TO "anon";
GRANT ALL ON FUNCTION "public"."fix_all_subscription_mismatches"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."fix_all_subscription_mismatches"() TO "service_role";



GRANT ALL ON FUNCTION "public"."float4_dist"(real, real) TO "postgres";
GRANT ALL ON FUNCTION "public"."float4_dist"(real, real) TO "anon";
GRANT ALL ON FUNCTION "public"."float4_dist"(real, real) TO "authenticated";
GRANT ALL ON FUNCTION "public"."float4_dist"(real, real) TO "service_role";



GRANT ALL ON FUNCTION "public"."float8_dist"(double precision, double precision) TO "postgres";
GRANT ALL ON FUNCTION "public"."float8_dist"(double precision, double precision) TO "anon";
GRANT ALL ON FUNCTION "public"."float8_dist"(double precision, double precision) TO "authenticated";
GRANT ALL ON FUNCTION "public"."float8_dist"(double precision, double precision) TO "service_role";



GRANT ALL ON FUNCTION "public"."fn_agenda_regras_semanais_no_overlap"() TO "postgres";
GRANT ALL ON FUNCTION "public"."fn_agenda_regras_semanais_no_overlap"() TO "anon";
GRANT ALL ON FUNCTION "public"."fn_agenda_regras_semanais_no_overlap"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."fn_agenda_regras_semanais_no_overlap"() TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bit_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bit_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bit_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bit_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bit_consistent"("internal", bit, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bit_consistent"("internal", bit, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bit_consistent"("internal", bit, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bit_consistent"("internal", bit, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bit_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bit_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bit_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bit_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bit_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bit_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bit_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bit_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bit_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bit_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bit_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bit_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bit_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bit_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bit_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bit_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bool_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bool_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bool_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bool_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bool_consistent"("internal", boolean, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bool_consistent"("internal", boolean, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bool_consistent"("internal", boolean, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bool_consistent"("internal", boolean, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bool_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bool_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bool_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bool_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bool_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bool_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bool_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bool_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bool_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bool_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bool_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bool_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bool_same"("public"."gbtreekey2", "public"."gbtreekey2", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bool_same"("public"."gbtreekey2", "public"."gbtreekey2", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bool_same"("public"."gbtreekey2", "public"."gbtreekey2", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bool_same"("public"."gbtreekey2", "public"."gbtreekey2", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bool_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bool_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bool_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bool_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bpchar_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bpchar_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bpchar_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bpchar_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bpchar_consistent"("internal", character, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bpchar_consistent"("internal", character, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bpchar_consistent"("internal", character, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bpchar_consistent"("internal", character, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bytea_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bytea_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bytea_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bytea_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bytea_consistent"("internal", "bytea", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bytea_consistent"("internal", "bytea", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bytea_consistent"("internal", "bytea", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bytea_consistent"("internal", "bytea", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bytea_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bytea_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bytea_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bytea_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bytea_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bytea_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bytea_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bytea_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bytea_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bytea_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bytea_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bytea_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_bytea_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_bytea_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_bytea_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_bytea_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_cash_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_cash_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_cash_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_cash_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_cash_consistent"("internal", "money", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_cash_consistent"("internal", "money", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_cash_consistent"("internal", "money", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_cash_consistent"("internal", "money", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_cash_distance"("internal", "money", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_cash_distance"("internal", "money", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_cash_distance"("internal", "money", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_cash_distance"("internal", "money", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_cash_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_cash_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_cash_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_cash_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_cash_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_cash_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_cash_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_cash_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_cash_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_cash_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_cash_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_cash_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_cash_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_cash_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_cash_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_cash_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_cash_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_cash_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_cash_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_cash_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_date_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_date_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_date_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_date_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_date_consistent"("internal", "date", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_date_consistent"("internal", "date", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_date_consistent"("internal", "date", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_date_consistent"("internal", "date", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_date_distance"("internal", "date", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_date_distance"("internal", "date", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_date_distance"("internal", "date", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_date_distance"("internal", "date", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_date_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_date_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_date_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_date_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_date_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_date_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_date_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_date_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_date_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_date_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_date_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_date_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_date_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_date_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_date_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_date_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_date_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_date_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_date_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_date_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_decompress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_decompress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_decompress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_decompress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_enum_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_enum_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_enum_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_enum_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_enum_consistent"("internal", "anyenum", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_enum_consistent"("internal", "anyenum", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_enum_consistent"("internal", "anyenum", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_enum_consistent"("internal", "anyenum", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_enum_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_enum_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_enum_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_enum_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_enum_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_enum_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_enum_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_enum_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_enum_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_enum_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_enum_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_enum_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_enum_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_enum_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_enum_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_enum_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_enum_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_enum_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_enum_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_enum_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float4_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float4_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float4_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float4_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float4_consistent"("internal", real, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float4_consistent"("internal", real, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float4_consistent"("internal", real, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float4_consistent"("internal", real, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float4_distance"("internal", real, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float4_distance"("internal", real, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float4_distance"("internal", real, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float4_distance"("internal", real, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float4_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float4_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float4_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float4_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float4_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float4_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float4_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float4_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float4_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float4_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float4_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float4_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float4_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float4_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float4_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float4_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float4_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float4_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float4_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float4_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float8_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float8_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float8_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float8_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float8_consistent"("internal", double precision, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float8_consistent"("internal", double precision, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float8_consistent"("internal", double precision, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float8_consistent"("internal", double precision, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float8_distance"("internal", double precision, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float8_distance"("internal", double precision, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float8_distance"("internal", double precision, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float8_distance"("internal", double precision, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float8_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float8_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float8_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float8_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float8_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float8_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float8_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float8_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float8_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float8_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float8_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float8_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_float8_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_float8_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_float8_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_float8_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_inet_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_inet_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_inet_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_inet_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_inet_consistent"("internal", "inet", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_inet_consistent"("internal", "inet", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_inet_consistent"("internal", "inet", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_inet_consistent"("internal", "inet", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_inet_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_inet_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_inet_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_inet_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_inet_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_inet_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_inet_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_inet_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_inet_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_inet_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_inet_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_inet_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_inet_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_inet_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_inet_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_inet_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int2_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int2_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int2_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int2_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int2_consistent"("internal", smallint, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int2_consistent"("internal", smallint, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int2_consistent"("internal", smallint, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int2_consistent"("internal", smallint, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int2_distance"("internal", smallint, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int2_distance"("internal", smallint, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int2_distance"("internal", smallint, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int2_distance"("internal", smallint, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int2_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int2_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int2_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int2_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int2_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int2_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int2_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int2_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int2_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int2_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int2_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int2_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int2_same"("public"."gbtreekey4", "public"."gbtreekey4", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int2_same"("public"."gbtreekey4", "public"."gbtreekey4", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int2_same"("public"."gbtreekey4", "public"."gbtreekey4", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int2_same"("public"."gbtreekey4", "public"."gbtreekey4", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int2_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int2_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int2_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int2_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int4_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int4_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int4_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int4_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int4_consistent"("internal", integer, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int4_consistent"("internal", integer, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int4_consistent"("internal", integer, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int4_consistent"("internal", integer, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int4_distance"("internal", integer, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int4_distance"("internal", integer, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int4_distance"("internal", integer, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int4_distance"("internal", integer, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int4_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int4_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int4_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int4_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int4_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int4_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int4_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int4_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int4_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int4_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int4_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int4_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int4_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int4_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int4_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int4_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int4_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int4_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int4_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int4_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int8_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int8_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int8_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int8_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int8_consistent"("internal", bigint, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int8_consistent"("internal", bigint, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int8_consistent"("internal", bigint, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int8_consistent"("internal", bigint, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int8_distance"("internal", bigint, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int8_distance"("internal", bigint, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int8_distance"("internal", bigint, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int8_distance"("internal", bigint, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int8_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int8_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int8_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int8_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int8_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int8_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int8_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int8_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int8_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int8_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int8_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int8_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_int8_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_int8_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_int8_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_int8_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_consistent"("internal", interval, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_consistent"("internal", interval, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_consistent"("internal", interval, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_consistent"("internal", interval, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_decompress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_decompress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_decompress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_decompress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_distance"("internal", interval, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_distance"("internal", interval, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_distance"("internal", interval, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_distance"("internal", interval, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_same"("public"."gbtreekey32", "public"."gbtreekey32", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_same"("public"."gbtreekey32", "public"."gbtreekey32", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_same"("public"."gbtreekey32", "public"."gbtreekey32", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_same"("public"."gbtreekey32", "public"."gbtreekey32", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_intv_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_intv_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_intv_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_intv_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad8_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad8_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad8_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad8_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad8_consistent"("internal", "macaddr8", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad8_consistent"("internal", "macaddr8", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad8_consistent"("internal", "macaddr8", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad8_consistent"("internal", "macaddr8", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad8_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad8_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad8_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad8_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad8_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad8_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad8_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad8_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad8_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad8_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad8_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad8_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad8_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad8_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad8_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad8_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad8_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad_consistent"("internal", "macaddr", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad_consistent"("internal", "macaddr", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad_consistent"("internal", "macaddr", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad_consistent"("internal", "macaddr", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_macad_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_macad_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_macad_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_macad_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_numeric_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_numeric_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_numeric_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_numeric_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_numeric_consistent"("internal", numeric, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_numeric_consistent"("internal", numeric, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_numeric_consistent"("internal", numeric, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_numeric_consistent"("internal", numeric, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_numeric_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_numeric_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_numeric_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_numeric_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_numeric_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_numeric_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_numeric_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_numeric_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_numeric_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_numeric_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_numeric_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_numeric_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_numeric_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_numeric_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_numeric_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_numeric_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_oid_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_oid_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_oid_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_oid_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_oid_consistent"("internal", "oid", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_oid_consistent"("internal", "oid", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_oid_consistent"("internal", "oid", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_oid_consistent"("internal", "oid", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_oid_distance"("internal", "oid", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_oid_distance"("internal", "oid", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_oid_distance"("internal", "oid", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_oid_distance"("internal", "oid", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_oid_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_oid_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_oid_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_oid_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_oid_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_oid_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_oid_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_oid_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_oid_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_oid_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_oid_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_oid_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_oid_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_oid_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_oid_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_oid_same"("public"."gbtreekey8", "public"."gbtreekey8", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_oid_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_oid_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_oid_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_oid_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_text_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_text_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_text_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_text_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_text_consistent"("internal", "text", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_text_consistent"("internal", "text", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_text_consistent"("internal", "text", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_text_consistent"("internal", "text", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_text_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_text_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_text_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_text_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_text_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_text_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_text_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_text_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_text_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_text_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_text_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_text_same"("public"."gbtreekey_var", "public"."gbtreekey_var", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_text_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_text_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_text_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_text_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_time_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_time_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_time_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_time_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_time_consistent"("internal", time without time zone, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_time_consistent"("internal", time without time zone, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_time_consistent"("internal", time without time zone, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_time_consistent"("internal", time without time zone, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_time_distance"("internal", time without time zone, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_time_distance"("internal", time without time zone, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_time_distance"("internal", time without time zone, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_time_distance"("internal", time without time zone, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_time_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_time_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_time_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_time_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_time_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_time_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_time_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_time_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_time_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_time_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_time_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_time_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_time_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_time_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_time_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_time_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_time_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_time_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_time_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_time_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_timetz_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_timetz_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_timetz_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_timetz_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_timetz_consistent"("internal", time with time zone, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_timetz_consistent"("internal", time with time zone, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_timetz_consistent"("internal", time with time zone, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_timetz_consistent"("internal", time with time zone, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_ts_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_ts_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_ts_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_ts_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_ts_consistent"("internal", timestamp without time zone, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_ts_consistent"("internal", timestamp without time zone, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_ts_consistent"("internal", timestamp without time zone, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_ts_consistent"("internal", timestamp without time zone, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_ts_distance"("internal", timestamp without time zone, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_ts_distance"("internal", timestamp without time zone, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_ts_distance"("internal", timestamp without time zone, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_ts_distance"("internal", timestamp without time zone, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_ts_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_ts_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_ts_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_ts_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_ts_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_ts_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_ts_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_ts_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_ts_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_ts_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_ts_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_ts_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_ts_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_ts_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_ts_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_ts_same"("public"."gbtreekey16", "public"."gbtreekey16", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_ts_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_ts_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_ts_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_ts_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_tstz_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_tstz_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_tstz_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_tstz_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_tstz_consistent"("internal", timestamp with time zone, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_tstz_consistent"("internal", timestamp with time zone, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_tstz_consistent"("internal", timestamp with time zone, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_tstz_consistent"("internal", timestamp with time zone, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_tstz_distance"("internal", timestamp with time zone, smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_tstz_distance"("internal", timestamp with time zone, smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_tstz_distance"("internal", timestamp with time zone, smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_tstz_distance"("internal", timestamp with time zone, smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_uuid_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_uuid_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_uuid_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_uuid_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_uuid_consistent"("internal", "uuid", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_uuid_consistent"("internal", "uuid", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_uuid_consistent"("internal", "uuid", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_uuid_consistent"("internal", "uuid", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_uuid_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_uuid_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_uuid_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_uuid_fetch"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_uuid_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_uuid_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_uuid_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_uuid_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_uuid_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_uuid_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_uuid_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_uuid_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_uuid_same"("public"."gbtreekey32", "public"."gbtreekey32", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_uuid_same"("public"."gbtreekey32", "public"."gbtreekey32", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_uuid_same"("public"."gbtreekey32", "public"."gbtreekey32", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_uuid_same"("public"."gbtreekey32", "public"."gbtreekey32", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_uuid_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_uuid_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_uuid_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_uuid_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_var_decompress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_var_decompress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_var_decompress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_var_decompress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gbt_var_fetch"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gbt_var_fetch"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gbt_var_fetch"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gbt_var_fetch"("internal") TO "service_role";



REVOKE ALL ON FUNCTION "public"."get_my_email"() FROM PUBLIC;
GRANT ALL ON FUNCTION "public"."get_my_email"() TO "postgres";
GRANT ALL ON FUNCTION "public"."get_my_email"() TO "anon";
GRANT ALL ON FUNCTION "public"."get_my_email"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."get_my_email"() TO "service_role";



GRANT ALL ON FUNCTION "public"."gin_extract_query_trgm"("text", "internal", smallint, "internal", "internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gin_extract_query_trgm"("text", "internal", smallint, "internal", "internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gin_extract_query_trgm"("text", "internal", smallint, "internal", "internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gin_extract_query_trgm"("text", "internal", smallint, "internal", "internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gin_extract_value_trgm"("text", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gin_extract_value_trgm"("text", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gin_extract_value_trgm"("text", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gin_extract_value_trgm"("text", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gin_trgm_consistent"("internal", smallint, "text", integer, "internal", "internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gin_trgm_consistent"("internal", smallint, "text", integer, "internal", "internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gin_trgm_consistent"("internal", smallint, "text", integer, "internal", "internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gin_trgm_consistent"("internal", smallint, "text", integer, "internal", "internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gin_trgm_triconsistent"("internal", smallint, "text", integer, "internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gin_trgm_triconsistent"("internal", smallint, "text", integer, "internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gin_trgm_triconsistent"("internal", smallint, "text", integer, "internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gin_trgm_triconsistent"("internal", smallint, "text", integer, "internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_compress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_compress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_compress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_compress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_consistent"("internal", "text", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_consistent"("internal", "text", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_consistent"("internal", "text", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_consistent"("internal", "text", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_decompress"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_decompress"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_decompress"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_decompress"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_distance"("internal", "text", smallint, "oid", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_distance"("internal", "text", smallint, "oid", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_distance"("internal", "text", smallint, "oid", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_distance"("internal", "text", smallint, "oid", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_options"("internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_options"("internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_options"("internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_options"("internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_penalty"("internal", "internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_penalty"("internal", "internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_penalty"("internal", "internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_penalty"("internal", "internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_picksplit"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_picksplit"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_picksplit"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_picksplit"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_same"("public"."gtrgm", "public"."gtrgm", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_same"("public"."gtrgm", "public"."gtrgm", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_same"("public"."gtrgm", "public"."gtrgm", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_same"("public"."gtrgm", "public"."gtrgm", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."gtrgm_union"("internal", "internal") TO "postgres";
GRANT ALL ON FUNCTION "public"."gtrgm_union"("internal", "internal") TO "anon";
GRANT ALL ON FUNCTION "public"."gtrgm_union"("internal", "internal") TO "authenticated";
GRANT ALL ON FUNCTION "public"."gtrgm_union"("internal", "internal") TO "service_role";



GRANT ALL ON FUNCTION "public"."guard_account_type_immutable"() TO "postgres";
GRANT ALL ON FUNCTION "public"."guard_account_type_immutable"() TO "anon";
GRANT ALL ON FUNCTION "public"."guard_account_type_immutable"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."guard_account_type_immutable"() TO "service_role";



GRANT ALL ON FUNCTION "public"."guard_locked_commitment"() TO "postgres";
GRANT ALL ON FUNCTION "public"."guard_locked_commitment"() TO "anon";
GRANT ALL ON FUNCTION "public"."guard_locked_commitment"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."guard_locked_commitment"() TO "service_role";



GRANT ALL ON FUNCTION "public"."guard_no_change_core_plan_key"() TO "postgres";
GRANT ALL ON FUNCTION "public"."guard_no_change_core_plan_key"() TO "anon";
GRANT ALL ON FUNCTION "public"."guard_no_change_core_plan_key"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."guard_no_change_core_plan_key"() TO "service_role";



GRANT ALL ON FUNCTION "public"."guard_no_change_plan_target"() TO "postgres";
GRANT ALL ON FUNCTION "public"."guard_no_change_plan_target"() TO "anon";
GRANT ALL ON FUNCTION "public"."guard_no_change_plan_target"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."guard_no_change_plan_target"() TO "service_role";



GRANT ALL ON FUNCTION "public"."guard_no_delete_core_plans"() TO "postgres";
GRANT ALL ON FUNCTION "public"."guard_no_delete_core_plans"() TO "anon";
GRANT ALL ON FUNCTION "public"."guard_no_delete_core_plans"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."guard_no_delete_core_plans"() TO "service_role";



GRANT ALL ON FUNCTION "public"."guard_patient_cannot_own_tenant"() TO "postgres";
GRANT ALL ON FUNCTION "public"."guard_patient_cannot_own_tenant"() TO "anon";
GRANT ALL ON FUNCTION "public"."guard_patient_cannot_own_tenant"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."guard_patient_cannot_own_tenant"() TO "service_role";



GRANT ALL ON FUNCTION "public"."guard_tenant_kind_immutable"() TO "postgres";
GRANT ALL ON FUNCTION "public"."guard_tenant_kind_immutable"() TO "anon";
GRANT ALL ON FUNCTION "public"."guard_tenant_kind_immutable"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."guard_tenant_kind_immutable"() TO "service_role";



GRANT ALL ON FUNCTION "public"."handle_new_user"() TO "postgres";
GRANT ALL ON FUNCTION "public"."handle_new_user"() TO "anon";
GRANT ALL ON FUNCTION "public"."handle_new_user"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."handle_new_user"() TO "service_role";



GRANT ALL ON FUNCTION "public"."handle_new_user_create_personal_tenant"() TO "postgres";
GRANT ALL ON FUNCTION "public"."handle_new_user_create_personal_tenant"() TO "anon";
GRANT ALL ON FUNCTION "public"."handle_new_user_create_personal_tenant"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."handle_new_user_create_personal_tenant"() TO "service_role";



GRANT ALL ON FUNCTION "public"."has_feature"("p_owner_id" "uuid", "p_feature_key" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."has_feature"("p_owner_id" "uuid", "p_feature_key" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."has_feature"("p_owner_id" "uuid", "p_feature_key" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."has_feature"("p_owner_id" "uuid", "p_feature_key" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."int2_dist"(smallint, smallint) TO "postgres";
GRANT ALL ON FUNCTION "public"."int2_dist"(smallint, smallint) TO "anon";
GRANT ALL ON FUNCTION "public"."int2_dist"(smallint, smallint) TO "authenticated";
GRANT ALL ON FUNCTION "public"."int2_dist"(smallint, smallint) TO "service_role";



GRANT ALL ON FUNCTION "public"."int4_dist"(integer, integer) TO "postgres";
GRANT ALL ON FUNCTION "public"."int4_dist"(integer, integer) TO "anon";
GRANT ALL ON FUNCTION "public"."int4_dist"(integer, integer) TO "authenticated";
GRANT ALL ON FUNCTION "public"."int4_dist"(integer, integer) TO "service_role";



GRANT ALL ON FUNCTION "public"."int8_dist"(bigint, bigint) TO "postgres";
GRANT ALL ON FUNCTION "public"."int8_dist"(bigint, bigint) TO "anon";
GRANT ALL ON FUNCTION "public"."int8_dist"(bigint, bigint) TO "authenticated";
GRANT ALL ON FUNCTION "public"."int8_dist"(bigint, bigint) TO "service_role";



GRANT ALL ON FUNCTION "public"."interval_dist"(interval, interval) TO "postgres";
GRANT ALL ON FUNCTION "public"."interval_dist"(interval, interval) TO "anon";
GRANT ALL ON FUNCTION "public"."interval_dist"(interval, interval) TO "authenticated";
GRANT ALL ON FUNCTION "public"."interval_dist"(interval, interval) TO "service_role";



GRANT ALL ON FUNCTION "public"."is_clinic_tenant"("_tenant_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."is_clinic_tenant"("_tenant_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."is_clinic_tenant"("_tenant_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."is_clinic_tenant"("_tenant_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."is_saas_admin"() TO "postgres";
GRANT ALL ON FUNCTION "public"."is_saas_admin"() TO "anon";
GRANT ALL ON FUNCTION "public"."is_saas_admin"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."is_saas_admin"() TO "service_role";



GRANT ALL ON FUNCTION "public"."is_tenant_admin"("p_tenant_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."is_tenant_admin"("p_tenant_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."is_tenant_admin"("p_tenant_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."is_tenant_admin"("p_tenant_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."is_tenant_member"("_tenant_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."is_tenant_member"("_tenant_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."is_tenant_member"("_tenant_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."is_tenant_member"("_tenant_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."is_therapist_tenant"("_tenant_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."is_therapist_tenant"("_tenant_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."is_therapist_tenant"("_tenant_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."is_therapist_tenant"("_tenant_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."jwt_email"() TO "postgres";
GRANT ALL ON FUNCTION "public"."jwt_email"() TO "anon";
GRANT ALL ON FUNCTION "public"."jwt_email"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."jwt_email"() TO "service_role";



GRANT ALL ON FUNCTION "public"."my_tenants"() TO "postgres";
GRANT ALL ON FUNCTION "public"."my_tenants"() TO "anon";
GRANT ALL ON FUNCTION "public"."my_tenants"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."my_tenants"() TO "service_role";



GRANT ALL ON FUNCTION "public"."oid_dist"("oid", "oid") TO "postgres";
GRANT ALL ON FUNCTION "public"."oid_dist"("oid", "oid") TO "anon";
GRANT ALL ON FUNCTION "public"."oid_dist"("oid", "oid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."oid_dist"("oid", "oid") TO "service_role";



GRANT ALL ON FUNCTION "public"."on_new_user_seed_patient_groups"() TO "postgres";
GRANT ALL ON FUNCTION "public"."on_new_user_seed_patient_groups"() TO "anon";
GRANT ALL ON FUNCTION "public"."on_new_user_seed_patient_groups"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."on_new_user_seed_patient_groups"() TO "service_role";



GRANT ALL ON FUNCTION "public"."patients_validate_member_consistency"() TO "postgres";
GRANT ALL ON FUNCTION "public"."patients_validate_member_consistency"() TO "anon";
GRANT ALL ON FUNCTION "public"."patients_validate_member_consistency"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."patients_validate_member_consistency"() TO "service_role";



GRANT ALL ON FUNCTION "public"."patients_validate_responsible_member_tenant"() TO "postgres";
GRANT ALL ON FUNCTION "public"."patients_validate_responsible_member_tenant"() TO "anon";
GRANT ALL ON FUNCTION "public"."patients_validate_responsible_member_tenant"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."patients_validate_responsible_member_tenant"() TO "service_role";



GRANT ALL ON FUNCTION "public"."prevent_promoting_to_system"() TO "postgres";
GRANT ALL ON FUNCTION "public"."prevent_promoting_to_system"() TO "anon";
GRANT ALL ON FUNCTION "public"."prevent_promoting_to_system"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."prevent_promoting_to_system"() TO "service_role";



GRANT ALL ON FUNCTION "public"."prevent_saas_membership"() TO "postgres";
GRANT ALL ON FUNCTION "public"."prevent_saas_membership"() TO "anon";
GRANT ALL ON FUNCTION "public"."prevent_saas_membership"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."prevent_saas_membership"() TO "service_role";



GRANT ALL ON FUNCTION "public"."prevent_system_group_changes"() TO "postgres";
GRANT ALL ON FUNCTION "public"."prevent_system_group_changes"() TO "anon";
GRANT ALL ON FUNCTION "public"."prevent_system_group_changes"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."prevent_system_group_changes"() TO "service_role";



GRANT ALL ON FUNCTION "public"."provision_account_tenant"("p_user_id" "uuid", "p_kind" "text", "p_name" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."provision_account_tenant"("p_user_id" "uuid", "p_kind" "text", "p_name" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."provision_account_tenant"("p_user_id" "uuid", "p_kind" "text", "p_name" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."provision_account_tenant"("p_user_id" "uuid", "p_kind" "text", "p_name" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."reactivate_subscription"("p_subscription_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."reactivate_subscription"("p_subscription_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."reactivate_subscription"("p_subscription_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."reactivate_subscription"("p_subscription_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."rebuild_owner_entitlements"("p_owner_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."rebuild_owner_entitlements"("p_owner_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."rebuild_owner_entitlements"("p_owner_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."rebuild_owner_entitlements"("p_owner_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_match"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_match"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_match"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_match"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_match"("public"."citext", "public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_match"("public"."citext", "public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_match"("public"."citext", "public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_match"("public"."citext", "public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_matches"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_matches"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_matches"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_matches"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_matches"("public"."citext", "public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_matches"("public"."citext", "public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_matches"("public"."citext", "public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_matches"("public"."citext", "public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_replace"("public"."citext", "public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_replace"("public"."citext", "public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_replace"("public"."citext", "public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_replace"("public"."citext", "public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_replace"("public"."citext", "public"."citext", "text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_replace"("public"."citext", "public"."citext", "text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_replace"("public"."citext", "public"."citext", "text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_replace"("public"."citext", "public"."citext", "text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_split_to_array"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_split_to_array"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_split_to_array"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_split_to_array"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_split_to_array"("public"."citext", "public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_split_to_array"("public"."citext", "public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_split_to_array"("public"."citext", "public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_split_to_array"("public"."citext", "public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_split_to_table"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_split_to_table"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_split_to_table"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_split_to_table"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."regexp_split_to_table"("public"."citext", "public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."regexp_split_to_table"("public"."citext", "public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."regexp_split_to_table"("public"."citext", "public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."regexp_split_to_table"("public"."citext", "public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."replace"("public"."citext", "public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."replace"("public"."citext", "public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."replace"("public"."citext", "public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."replace"("public"."citext", "public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."rotate_patient_invite_token"("p_new_token" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."rotate_patient_invite_token"("p_new_token" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."rotate_patient_invite_token"("p_new_token" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."rotate_patient_invite_token"("p_new_token" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."saas_votar_doc"("p_doc_id" "uuid", "p_util" boolean) TO "postgres";
GRANT ALL ON FUNCTION "public"."saas_votar_doc"("p_doc_id" "uuid", "p_util" boolean) TO "anon";
GRANT ALL ON FUNCTION "public"."saas_votar_doc"("p_doc_id" "uuid", "p_util" boolean) TO "authenticated";
GRANT ALL ON FUNCTION "public"."saas_votar_doc"("p_doc_id" "uuid", "p_util" boolean) TO "service_role";



GRANT ALL ON FUNCTION "public"."seed_determined_commitments"("p_tenant_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."seed_determined_commitments"("p_tenant_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."seed_determined_commitments"("p_tenant_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."seed_determined_commitments"("p_tenant_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."set_limit"(real) TO "postgres";
GRANT ALL ON FUNCTION "public"."set_limit"(real) TO "anon";
GRANT ALL ON FUNCTION "public"."set_limit"(real) TO "authenticated";
GRANT ALL ON FUNCTION "public"."set_limit"(real) TO "service_role";



GRANT ALL ON FUNCTION "public"."set_owner_id"() TO "postgres";
GRANT ALL ON FUNCTION "public"."set_owner_id"() TO "anon";
GRANT ALL ON FUNCTION "public"."set_owner_id"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."set_owner_id"() TO "service_role";



GRANT ALL ON FUNCTION "public"."set_tenant_feature_exception"("p_tenant_id" "uuid", "p_feature_key" "text", "p_enabled" boolean, "p_reason" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."set_tenant_feature_exception"("p_tenant_id" "uuid", "p_feature_key" "text", "p_enabled" boolean, "p_reason" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."set_tenant_feature_exception"("p_tenant_id" "uuid", "p_feature_key" "text", "p_enabled" boolean, "p_reason" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."set_tenant_feature_exception"("p_tenant_id" "uuid", "p_feature_key" "text", "p_enabled" boolean, "p_reason" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."set_updated_at"() TO "postgres";
GRANT ALL ON FUNCTION "public"."set_updated_at"() TO "anon";
GRANT ALL ON FUNCTION "public"."set_updated_at"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."set_updated_at"() TO "service_role";



GRANT ALL ON FUNCTION "public"."set_updated_at_recurrence"() TO "postgres";
GRANT ALL ON FUNCTION "public"."set_updated_at_recurrence"() TO "anon";
GRANT ALL ON FUNCTION "public"."set_updated_at_recurrence"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."set_updated_at_recurrence"() TO "service_role";



GRANT ALL ON FUNCTION "public"."show_limit"() TO "postgres";
GRANT ALL ON FUNCTION "public"."show_limit"() TO "anon";
GRANT ALL ON FUNCTION "public"."show_limit"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."show_limit"() TO "service_role";



GRANT ALL ON FUNCTION "public"."show_trgm"("text") TO "postgres";
GRANT ALL ON FUNCTION "public"."show_trgm"("text") TO "anon";
GRANT ALL ON FUNCTION "public"."show_trgm"("text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."show_trgm"("text") TO "service_role";



GRANT ALL ON FUNCTION "public"."similarity"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."similarity"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."similarity"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."similarity"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."similarity_dist"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."similarity_dist"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."similarity_dist"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."similarity_dist"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."similarity_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."similarity_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."similarity_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."similarity_op"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."split_part"("public"."citext", "public"."citext", integer) TO "postgres";
GRANT ALL ON FUNCTION "public"."split_part"("public"."citext", "public"."citext", integer) TO "anon";
GRANT ALL ON FUNCTION "public"."split_part"("public"."citext", "public"."citext", integer) TO "authenticated";
GRANT ALL ON FUNCTION "public"."split_part"("public"."citext", "public"."citext", integer) TO "service_role";



GRANT ALL ON FUNCTION "public"."split_recurrence_at"("p_recurrence_id" "uuid", "p_from_date" "date") TO "postgres";
GRANT ALL ON FUNCTION "public"."split_recurrence_at"("p_recurrence_id" "uuid", "p_from_date" "date") TO "anon";
GRANT ALL ON FUNCTION "public"."split_recurrence_at"("p_recurrence_id" "uuid", "p_from_date" "date") TO "authenticated";
GRANT ALL ON FUNCTION "public"."split_recurrence_at"("p_recurrence_id" "uuid", "p_from_date" "date") TO "service_role";



GRANT ALL ON FUNCTION "public"."strict_word_similarity"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."strict_word_similarity"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."strict_word_similarity"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."strict_word_similarity"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."strict_word_similarity_commutator_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_commutator_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_commutator_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_commutator_op"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."strict_word_similarity_dist_commutator_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_dist_commutator_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_dist_commutator_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_dist_commutator_op"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."strict_word_similarity_dist_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_dist_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_dist_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_dist_op"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."strict_word_similarity_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."strict_word_similarity_op"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."strpos"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."strpos"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."strpos"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."strpos"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."subscription_intents_view_insert"() TO "postgres";
GRANT ALL ON FUNCTION "public"."subscription_intents_view_insert"() TO "anon";
GRANT ALL ON FUNCTION "public"."subscription_intents_view_insert"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."subscription_intents_view_insert"() TO "service_role";



GRANT ALL ON FUNCTION "public"."subscriptions_validate_scope"() TO "postgres";
GRANT ALL ON FUNCTION "public"."subscriptions_validate_scope"() TO "anon";
GRANT ALL ON FUNCTION "public"."subscriptions_validate_scope"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."subscriptions_validate_scope"() TO "service_role";



GRANT ALL ON FUNCTION "public"."sync_busy_mirror_agenda_eventos"() TO "postgres";
GRANT ALL ON FUNCTION "public"."sync_busy_mirror_agenda_eventos"() TO "anon";
GRANT ALL ON FUNCTION "public"."sync_busy_mirror_agenda_eventos"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."sync_busy_mirror_agenda_eventos"() TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_accept_invite"("p_token" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_accept_invite"("p_token" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_accept_invite"("p_token" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_accept_invite"("p_token" "uuid") TO "service_role";



GRANT ALL ON TABLE "public"."tenant_members" TO "postgres";
GRANT SELECT,REFERENCES,TRIGGER,TRUNCATE,MAINTAIN ON TABLE "public"."tenant_members" TO "authenticated";
GRANT ALL ON TABLE "public"."tenant_members" TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_add_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_add_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_add_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_add_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_feature_allowed"("p_tenant_id" "uuid", "p_feature_key" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_feature_allowed"("p_tenant_id" "uuid", "p_feature_key" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_feature_allowed"("p_tenant_id" "uuid", "p_feature_key" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_feature_allowed"("p_tenant_id" "uuid", "p_feature_key" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_feature_enabled"("p_tenant_id" "uuid", "p_feature_key" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_feature_enabled"("p_tenant_id" "uuid", "p_feature_key" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_feature_enabled"("p_tenant_id" "uuid", "p_feature_key" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_feature_enabled"("p_tenant_id" "uuid", "p_feature_key" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_features_guard_with_plan"() TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_features_guard_with_plan"() TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_features_guard_with_plan"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_features_guard_with_plan"() TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_has_feature"("_tenant_id" "uuid", "_feature" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_has_feature"("_tenant_id" "uuid", "_feature" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_has_feature"("_tenant_id" "uuid", "_feature" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_has_feature"("_tenant_id" "uuid", "_feature" "text") TO "service_role";



REVOKE ALL ON FUNCTION "public"."tenant_invite_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") FROM PUBLIC;
GRANT ALL ON FUNCTION "public"."tenant_invite_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_invite_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_invite_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_invite_member_by_email"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_reactivate_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_reactivate_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_reactivate_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_reactivate_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_remove_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_remove_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_remove_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_remove_member"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_remove_member_soft"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_remove_member_soft"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_remove_member_soft"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_remove_member_soft"("p_tenant_id" "uuid", "p_member_user_id" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_revoke_invite"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_revoke_invite"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_revoke_invite"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_revoke_invite"("p_tenant_id" "uuid", "p_email" "text", "p_role" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_set_member_status"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_status" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_set_member_status"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_status" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_set_member_status"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_status" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_set_member_status"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_status" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."tenant_update_member_role"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_role" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."tenant_update_member_role"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_role" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."tenant_update_member_role"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_role" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."tenant_update_member_role"("p_tenant_id" "uuid", "p_member_user_id" "uuid", "p_new_role" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."texticlike"("public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."texticlike"("public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."texticlike"("public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."texticlike"("public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."texticlike"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."texticlike"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."texticlike"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."texticlike"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."texticnlike"("public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."texticnlike"("public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."texticnlike"("public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."texticnlike"("public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."texticnlike"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."texticnlike"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."texticnlike"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."texticnlike"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."texticregexeq"("public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."texticregexeq"("public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."texticregexeq"("public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."texticregexeq"("public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."texticregexeq"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."texticregexeq"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."texticregexeq"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."texticregexeq"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."texticregexne"("public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."texticregexne"("public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."texticregexne"("public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."texticregexne"("public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."texticregexne"("public"."citext", "public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."texticregexne"("public"."citext", "public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."texticregexne"("public"."citext", "public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."texticregexne"("public"."citext", "public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."time_dist"(time without time zone, time without time zone) TO "postgres";
GRANT ALL ON FUNCTION "public"."time_dist"(time without time zone, time without time zone) TO "anon";
GRANT ALL ON FUNCTION "public"."time_dist"(time without time zone, time without time zone) TO "authenticated";
GRANT ALL ON FUNCTION "public"."time_dist"(time without time zone, time without time zone) TO "service_role";



GRANT ALL ON FUNCTION "public"."toggle_plan"("owner" "uuid") TO "postgres";
GRANT ALL ON FUNCTION "public"."toggle_plan"("owner" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."toggle_plan"("owner" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."toggle_plan"("owner" "uuid") TO "service_role";



GRANT ALL ON FUNCTION "public"."transition_subscription"("p_subscription_id" "uuid", "p_to_status" "text", "p_reason" "text", "p_metadata" "jsonb") TO "postgres";
GRANT ALL ON FUNCTION "public"."transition_subscription"("p_subscription_id" "uuid", "p_to_status" "text", "p_reason" "text", "p_metadata" "jsonb") TO "anon";
GRANT ALL ON FUNCTION "public"."transition_subscription"("p_subscription_id" "uuid", "p_to_status" "text", "p_reason" "text", "p_metadata" "jsonb") TO "authenticated";
GRANT ALL ON FUNCTION "public"."transition_subscription"("p_subscription_id" "uuid", "p_to_status" "text", "p_reason" "text", "p_metadata" "jsonb") TO "service_role";



GRANT ALL ON FUNCTION "public"."translate"("public"."citext", "public"."citext", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."translate"("public"."citext", "public"."citext", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."translate"("public"."citext", "public"."citext", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."translate"("public"."citext", "public"."citext", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."ts_dist"(timestamp without time zone, timestamp without time zone) TO "postgres";
GRANT ALL ON FUNCTION "public"."ts_dist"(timestamp without time zone, timestamp without time zone) TO "anon";
GRANT ALL ON FUNCTION "public"."ts_dist"(timestamp without time zone, timestamp without time zone) TO "authenticated";
GRANT ALL ON FUNCTION "public"."ts_dist"(timestamp without time zone, timestamp without time zone) TO "service_role";



GRANT ALL ON FUNCTION "public"."tstz_dist"(timestamp with time zone, timestamp with time zone) TO "postgres";
GRANT ALL ON FUNCTION "public"."tstz_dist"(timestamp with time zone, timestamp with time zone) TO "anon";
GRANT ALL ON FUNCTION "public"."tstz_dist"(timestamp with time zone, timestamp with time zone) TO "authenticated";
GRANT ALL ON FUNCTION "public"."tstz_dist"(timestamp with time zone, timestamp with time zone) TO "service_role";



GRANT ALL ON FUNCTION "public"."user_has_feature"("_user_id" "uuid", "_feature" "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."user_has_feature"("_user_id" "uuid", "_feature" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."user_has_feature"("_user_id" "uuid", "_feature" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."user_has_feature"("_user_id" "uuid", "_feature" "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."whoami"() TO "postgres";
GRANT ALL ON FUNCTION "public"."whoami"() TO "anon";
GRANT ALL ON FUNCTION "public"."whoami"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."whoami"() TO "service_role";



GRANT ALL ON FUNCTION "public"."word_similarity"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."word_similarity"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."word_similarity"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."word_similarity"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."word_similarity_commutator_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."word_similarity_commutator_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."word_similarity_commutator_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."word_similarity_commutator_op"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."word_similarity_dist_commutator_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."word_similarity_dist_commutator_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."word_similarity_dist_commutator_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."word_similarity_dist_commutator_op"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."word_similarity_dist_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."word_similarity_dist_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."word_similarity_dist_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."word_similarity_dist_op"("text", "text") TO "service_role";



GRANT ALL ON FUNCTION "public"."word_similarity_op"("text", "text") TO "postgres";
GRANT ALL ON FUNCTION "public"."word_similarity_op"("text", "text") TO "anon";
GRANT ALL ON FUNCTION "public"."word_similarity_op"("text", "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."word_similarity_op"("text", "text") TO "service_role";












GRANT ALL ON FUNCTION "public"."max"("public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."max"("public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."max"("public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."max"("public"."citext") TO "service_role";



GRANT ALL ON FUNCTION "public"."min"("public"."citext") TO "postgres";
GRANT ALL ON FUNCTION "public"."min"("public"."citext") TO "anon";
GRANT ALL ON FUNCTION "public"."min"("public"."citext") TO "authenticated";
GRANT ALL ON FUNCTION "public"."min"("public"."citext") TO "service_role";









GRANT ALL ON TABLE "public"."agenda_bloqueios" TO "postgres";
GRANT ALL ON TABLE "public"."agenda_bloqueios" TO "anon";
GRANT ALL ON TABLE "public"."agenda_bloqueios" TO "authenticated";
GRANT ALL ON TABLE "public"."agenda_bloqueios" TO "service_role";



GRANT ALL ON TABLE "public"."agenda_configuracoes" TO "postgres";
GRANT ALL ON TABLE "public"."agenda_configuracoes" TO "anon";
GRANT ALL ON TABLE "public"."agenda_configuracoes" TO "authenticated";
GRANT ALL ON TABLE "public"."agenda_configuracoes" TO "service_role";



GRANT ALL ON TABLE "public"."agenda_eventos" TO "postgres";
GRANT ALL ON TABLE "public"."agenda_eventos" TO "anon";
GRANT ALL ON TABLE "public"."agenda_eventos" TO "authenticated";
GRANT ALL ON TABLE "public"."agenda_eventos" TO "service_role";



GRANT ALL ON TABLE "public"."agenda_excecoes" TO "postgres";
GRANT ALL ON TABLE "public"."agenda_excecoes" TO "anon";
GRANT ALL ON TABLE "public"."agenda_excecoes" TO "authenticated";
GRANT ALL ON TABLE "public"."agenda_excecoes" TO "service_role";



GRANT ALL ON TABLE "public"."agenda_online_slots" TO "postgres";
GRANT ALL ON TABLE "public"."agenda_online_slots" TO "anon";
GRANT ALL ON TABLE "public"."agenda_online_slots" TO "authenticated";
GRANT ALL ON TABLE "public"."agenda_online_slots" TO "service_role";



GRANT ALL ON SEQUENCE "public"."agenda_online_slots_id_seq" TO "postgres";
GRANT ALL ON SEQUENCE "public"."agenda_online_slots_id_seq" TO "anon";
GRANT ALL ON SEQUENCE "public"."agenda_online_slots_id_seq" TO "authenticated";
GRANT ALL ON SEQUENCE "public"."agenda_online_slots_id_seq" TO "service_role";



GRANT ALL ON TABLE "public"."agenda_regras_semanais" TO "postgres";
GRANT ALL ON TABLE "public"."agenda_regras_semanais" TO "anon";
GRANT ALL ON TABLE "public"."agenda_regras_semanais" TO "authenticated";
GRANT ALL ON TABLE "public"."agenda_regras_semanais" TO "service_role";



GRANT ALL ON TABLE "public"."agenda_slots_bloqueados_semanais" TO "postgres";
GRANT ALL ON TABLE "public"."agenda_slots_bloqueados_semanais" TO "anon";
GRANT ALL ON TABLE "public"."agenda_slots_bloqueados_semanais" TO "authenticated";
GRANT ALL ON TABLE "public"."agenda_slots_bloqueados_semanais" TO "service_role";



GRANT ALL ON TABLE "public"."agenda_slots_regras" TO "postgres";
GRANT ALL ON TABLE "public"."agenda_slots_regras" TO "anon";
GRANT ALL ON TABLE "public"."agenda_slots_regras" TO "authenticated";
GRANT ALL ON TABLE "public"."agenda_slots_regras" TO "service_role";



GRANT ALL ON TABLE "public"."agendador_configuracoes" TO "postgres";
GRANT ALL ON TABLE "public"."agendador_configuracoes" TO "anon";
GRANT ALL ON TABLE "public"."agendador_configuracoes" TO "authenticated";
GRANT ALL ON TABLE "public"."agendador_configuracoes" TO "service_role";



GRANT ALL ON TABLE "public"."agendador_solicitacoes" TO "postgres";
GRANT ALL ON TABLE "public"."agendador_solicitacoes" TO "anon";
GRANT ALL ON TABLE "public"."agendador_solicitacoes" TO "authenticated";
GRANT ALL ON TABLE "public"."agendador_solicitacoes" TO "service_role";



GRANT ALL ON TABLE "public"."commitment_time_logs" TO "postgres";
GRANT ALL ON TABLE "public"."commitment_time_logs" TO "anon";
GRANT ALL ON TABLE "public"."commitment_time_logs" TO "authenticated";
GRANT ALL ON TABLE "public"."commitment_time_logs" TO "service_role";



GRANT ALL ON TABLE "public"."current_tenant_id" TO "postgres";
GRANT ALL ON TABLE "public"."current_tenant_id" TO "anon";
GRANT ALL ON TABLE "public"."current_tenant_id" TO "authenticated";
GRANT ALL ON TABLE "public"."current_tenant_id" TO "service_role";



GRANT ALL ON TABLE "public"."determined_commitment_fields" TO "postgres";
GRANT ALL ON TABLE "public"."determined_commitment_fields" TO "anon";
GRANT ALL ON TABLE "public"."determined_commitment_fields" TO "authenticated";
GRANT ALL ON TABLE "public"."determined_commitment_fields" TO "service_role";



GRANT ALL ON TABLE "public"."determined_commitments" TO "postgres";
GRANT ALL ON TABLE "public"."determined_commitments" TO "anon";
GRANT ALL ON TABLE "public"."determined_commitments" TO "authenticated";
GRANT ALL ON TABLE "public"."determined_commitments" TO "service_role";



GRANT ALL ON TABLE "public"."dev_user_credentials" TO "postgres";
GRANT ALL ON TABLE "public"."dev_user_credentials" TO "anon";
GRANT ALL ON TABLE "public"."dev_user_credentials" TO "authenticated";
GRANT ALL ON TABLE "public"."dev_user_credentials" TO "service_role";



GRANT ALL ON TABLE "public"."entitlements_invalidation" TO "postgres";
GRANT ALL ON TABLE "public"."entitlements_invalidation" TO "anon";
GRANT ALL ON TABLE "public"."entitlements_invalidation" TO "authenticated";
GRANT ALL ON TABLE "public"."entitlements_invalidation" TO "service_role";



GRANT ALL ON TABLE "public"."features" TO "postgres";
GRANT ALL ON TABLE "public"."features" TO "anon";
GRANT ALL ON TABLE "public"."features" TO "authenticated";
GRANT ALL ON TABLE "public"."features" TO "service_role";



GRANT ALL ON TABLE "public"."feriados" TO "postgres";
GRANT ALL ON TABLE "public"."feriados" TO "anon";
GRANT ALL ON TABLE "public"."feriados" TO "authenticated";
GRANT ALL ON TABLE "public"."feriados" TO "service_role";



GRANT ALL ON TABLE "public"."module_features" TO "postgres";
GRANT ALL ON TABLE "public"."module_features" TO "anon";
GRANT ALL ON TABLE "public"."module_features" TO "authenticated";
GRANT ALL ON TABLE "public"."module_features" TO "service_role";



GRANT ALL ON TABLE "public"."modules" TO "postgres";
GRANT ALL ON TABLE "public"."modules" TO "anon";
GRANT ALL ON TABLE "public"."modules" TO "authenticated";
GRANT ALL ON TABLE "public"."modules" TO "service_role";



GRANT ALL ON TABLE "public"."plan_features" TO "postgres";
GRANT ALL ON TABLE "public"."plan_features" TO "anon";
GRANT ALL ON TABLE "public"."plan_features" TO "authenticated";
GRANT ALL ON TABLE "public"."plan_features" TO "service_role";



GRANT ALL ON TABLE "public"."tenant_modules" TO "postgres";
GRANT ALL ON TABLE "public"."tenant_modules" TO "anon";
GRANT ALL ON TABLE "public"."tenant_modules" TO "authenticated";
GRANT ALL ON TABLE "public"."tenant_modules" TO "service_role";



GRANT ALL ON TABLE "public"."owner_feature_entitlements" TO "postgres";
GRANT ALL ON TABLE "public"."owner_feature_entitlements" TO "anon";
GRANT ALL ON TABLE "public"."owner_feature_entitlements" TO "authenticated";
GRANT ALL ON TABLE "public"."owner_feature_entitlements" TO "service_role";



GRANT ALL ON TABLE "public"."owner_users" TO "postgres";
GRANT ALL ON TABLE "public"."owner_users" TO "anon";
GRANT ALL ON TABLE "public"."owner_users" TO "authenticated";
GRANT ALL ON TABLE "public"."owner_users" TO "service_role";



GRANT ALL ON TABLE "public"."patient_group_patient" TO "postgres";
GRANT ALL ON TABLE "public"."patient_group_patient" TO "anon";
GRANT ALL ON TABLE "public"."patient_group_patient" TO "authenticated";
GRANT ALL ON TABLE "public"."patient_group_patient" TO "service_role";



GRANT ALL ON TABLE "public"."patient_groups" TO "postgres";
GRANT ALL ON TABLE "public"."patient_groups" TO "anon";
GRANT ALL ON TABLE "public"."patient_groups" TO "authenticated";
GRANT ALL ON TABLE "public"."patient_groups" TO "service_role";



GRANT ALL ON TABLE "public"."patient_intake_requests" TO "postgres";
GRANT ALL ON TABLE "public"."patient_intake_requests" TO "authenticated";
GRANT ALL ON TABLE "public"."patient_intake_requests" TO "service_role";



GRANT ALL ON TABLE "public"."patient_invites" TO "postgres";
GRANT ALL ON TABLE "public"."patient_invites" TO "authenticated";
GRANT ALL ON TABLE "public"."patient_invites" TO "service_role";



GRANT ALL ON TABLE "public"."patient_patient_tag" TO "postgres";
GRANT ALL ON TABLE "public"."patient_patient_tag" TO "anon";
GRANT ALL ON TABLE "public"."patient_patient_tag" TO "authenticated";
GRANT ALL ON TABLE "public"."patient_patient_tag" TO "service_role";



GRANT ALL ON TABLE "public"."patient_tags" TO "postgres";
GRANT ALL ON TABLE "public"."patient_tags" TO "anon";
GRANT ALL ON TABLE "public"."patient_tags" TO "authenticated";
GRANT ALL ON TABLE "public"."patient_tags" TO "service_role";



GRANT ALL ON TABLE "public"."patients" TO "postgres";
GRANT ALL ON TABLE "public"."patients" TO "anon";
GRANT ALL ON TABLE "public"."patients" TO "authenticated";
GRANT ALL ON TABLE "public"."patients" TO "service_role";



GRANT ALL ON TABLE "public"."plan_prices" TO "postgres";
GRANT ALL ON TABLE "public"."plan_prices" TO "anon";
GRANT ALL ON TABLE "public"."plan_prices" TO "authenticated";
GRANT ALL ON TABLE "public"."plan_prices" TO "service_role";



GRANT ALL ON TABLE "public"."plan_public" TO "postgres";
GRANT ALL ON TABLE "public"."plan_public" TO "anon";
GRANT ALL ON TABLE "public"."plan_public" TO "authenticated";
GRANT ALL ON TABLE "public"."plan_public" TO "service_role";



GRANT ALL ON TABLE "public"."plan_public_bullets" TO "postgres";
GRANT ALL ON TABLE "public"."plan_public_bullets" TO "anon";
GRANT ALL ON TABLE "public"."plan_public_bullets" TO "authenticated";
GRANT ALL ON TABLE "public"."plan_public_bullets" TO "service_role";



GRANT ALL ON TABLE "public"."plans" TO "postgres";
GRANT ALL ON TABLE "public"."plans" TO "anon";
GRANT ALL ON TABLE "public"."plans" TO "authenticated";
GRANT ALL ON TABLE "public"."plans" TO "service_role";



GRANT ALL ON TABLE "public"."profiles" TO "postgres";
GRANT ALL ON TABLE "public"."profiles" TO "anon";
GRANT ALL ON TABLE "public"."profiles" TO "authenticated";
GRANT ALL ON TABLE "public"."profiles" TO "service_role";



GRANT ALL ON TABLE "public"."recurrence_exceptions" TO "postgres";
GRANT ALL ON TABLE "public"."recurrence_exceptions" TO "anon";
GRANT ALL ON TABLE "public"."recurrence_exceptions" TO "authenticated";
GRANT ALL ON TABLE "public"."recurrence_exceptions" TO "service_role";



GRANT ALL ON TABLE "public"."recurrence_rules" TO "postgres";
GRANT ALL ON TABLE "public"."recurrence_rules" TO "anon";
GRANT ALL ON TABLE "public"."recurrence_rules" TO "authenticated";
GRANT ALL ON TABLE "public"."recurrence_rules" TO "service_role";



GRANT ALL ON TABLE "public"."saas_admins" TO "postgres";
GRANT ALL ON TABLE "public"."saas_admins" TO "anon";
GRANT ALL ON TABLE "public"."saas_admins" TO "authenticated";
GRANT ALL ON TABLE "public"."saas_admins" TO "service_role";



GRANT ALL ON TABLE "public"."saas_doc_votos" TO "postgres";
GRANT ALL ON TABLE "public"."saas_doc_votos" TO "anon";
GRANT ALL ON TABLE "public"."saas_doc_votos" TO "authenticated";
GRANT ALL ON TABLE "public"."saas_doc_votos" TO "service_role";



GRANT ALL ON TABLE "public"."saas_docs" TO "postgres";
GRANT ALL ON TABLE "public"."saas_docs" TO "anon";
GRANT ALL ON TABLE "public"."saas_docs" TO "authenticated";
GRANT ALL ON TABLE "public"."saas_docs" TO "service_role";



GRANT ALL ON TABLE "public"."saas_faq" TO "postgres";
GRANT ALL ON TABLE "public"."saas_faq" TO "anon";
GRANT ALL ON TABLE "public"."saas_faq" TO "authenticated";
GRANT ALL ON TABLE "public"."saas_faq" TO "service_role";



GRANT ALL ON TABLE "public"."saas_faq_itens" TO "postgres";
GRANT ALL ON TABLE "public"."saas_faq_itens" TO "anon";
GRANT ALL ON TABLE "public"."saas_faq_itens" TO "authenticated";
GRANT ALL ON TABLE "public"."saas_faq_itens" TO "service_role";



GRANT ALL ON TABLE "public"."subscription_events" TO "postgres";
GRANT ALL ON TABLE "public"."subscription_events" TO "anon";
GRANT ALL ON TABLE "public"."subscription_events" TO "authenticated";
GRANT ALL ON TABLE "public"."subscription_events" TO "service_role";



GRANT ALL ON TABLE "public"."subscription_intents_personal" TO "postgres";
GRANT ALL ON TABLE "public"."subscription_intents_personal" TO "anon";
GRANT ALL ON TABLE "public"."subscription_intents_personal" TO "authenticated";
GRANT ALL ON TABLE "public"."subscription_intents_personal" TO "service_role";



GRANT ALL ON TABLE "public"."subscription_intents_tenant" TO "postgres";
GRANT ALL ON TABLE "public"."subscription_intents_tenant" TO "anon";
GRANT ALL ON TABLE "public"."subscription_intents_tenant" TO "authenticated";
GRANT ALL ON TABLE "public"."subscription_intents_tenant" TO "service_role";



GRANT ALL ON TABLE "public"."subscription_intents" TO "postgres";
GRANT ALL ON TABLE "public"."subscription_intents" TO "anon";
GRANT ALL ON TABLE "public"."subscription_intents" TO "authenticated";
GRANT ALL ON TABLE "public"."subscription_intents" TO "service_role";



GRANT ALL ON TABLE "public"."subscription_intents_legacy" TO "postgres";
GRANT ALL ON TABLE "public"."subscription_intents_legacy" TO "anon";
GRANT ALL ON TABLE "public"."subscription_intents_legacy" TO "authenticated";
GRANT ALL ON TABLE "public"."subscription_intents_legacy" TO "service_role";



GRANT ALL ON TABLE "public"."tenant_feature_exceptions_log" TO "postgres";
GRANT ALL ON TABLE "public"."tenant_feature_exceptions_log" TO "anon";
GRANT ALL ON TABLE "public"."tenant_feature_exceptions_log" TO "authenticated";
GRANT ALL ON TABLE "public"."tenant_feature_exceptions_log" TO "service_role";



GRANT ALL ON TABLE "public"."tenant_features" TO "postgres";
GRANT ALL ON TABLE "public"."tenant_features" TO "anon";
GRANT ALL ON TABLE "public"."tenant_features" TO "authenticated";
GRANT ALL ON TABLE "public"."tenant_features" TO "service_role";



GRANT ALL ON TABLE "public"."tenant_invites" TO "postgres";
GRANT ALL ON TABLE "public"."tenant_invites" TO "authenticated";
GRANT ALL ON TABLE "public"."tenant_invites" TO "service_role";



GRANT ALL ON TABLE "public"."tenants" TO "postgres";
GRANT ALL ON TABLE "public"."tenants" TO "anon";
GRANT ALL ON TABLE "public"."tenants" TO "authenticated";
GRANT ALL ON TABLE "public"."tenants" TO "service_role";



GRANT ALL ON TABLE "public"."user_settings" TO "postgres";
GRANT ALL ON TABLE "public"."user_settings" TO "anon";
GRANT ALL ON TABLE "public"."user_settings" TO "authenticated";
GRANT ALL ON TABLE "public"."user_settings" TO "service_role";



GRANT ALL ON TABLE "public"."v_auth_users_public" TO "postgres";
GRANT ALL ON TABLE "public"."v_auth_users_public" TO "anon";
GRANT ALL ON TABLE "public"."v_auth_users_public" TO "authenticated";
GRANT ALL ON TABLE "public"."v_auth_users_public" TO "service_role";



GRANT ALL ON TABLE "public"."v_commitment_totals" TO "postgres";
GRANT ALL ON TABLE "public"."v_commitment_totals" TO "anon";
GRANT ALL ON TABLE "public"."v_commitment_totals" TO "authenticated";
GRANT ALL ON TABLE "public"."v_commitment_totals" TO "service_role";



GRANT ALL ON TABLE "public"."v_patient_groups_with_counts" TO "postgres";
GRANT ALL ON TABLE "public"."v_patient_groups_with_counts" TO "anon";
GRANT ALL ON TABLE "public"."v_patient_groups_with_counts" TO "authenticated";
GRANT ALL ON TABLE "public"."v_patient_groups_with_counts" TO "service_role";



GRANT ALL ON TABLE "public"."v_plan_active_prices" TO "postgres";
GRANT ALL ON TABLE "public"."v_plan_active_prices" TO "anon";
GRANT ALL ON TABLE "public"."v_plan_active_prices" TO "authenticated";
GRANT ALL ON TABLE "public"."v_plan_active_prices" TO "service_role";



GRANT ALL ON TABLE "public"."v_public_pricing" TO "postgres";
GRANT ALL ON TABLE "public"."v_public_pricing" TO "anon";
GRANT ALL ON TABLE "public"."v_public_pricing" TO "authenticated";
GRANT ALL ON TABLE "public"."v_public_pricing" TO "service_role";



GRANT ALL ON TABLE "public"."v_subscription_feature_mismatch" TO "postgres";
GRANT ALL ON TABLE "public"."v_subscription_feature_mismatch" TO "anon";
GRANT ALL ON TABLE "public"."v_subscription_feature_mismatch" TO "authenticated";
GRANT ALL ON TABLE "public"."v_subscription_feature_mismatch" TO "service_role";



GRANT ALL ON TABLE "public"."v_subscription_health" TO "postgres";
GRANT ALL ON TABLE "public"."v_subscription_health" TO "anon";
GRANT ALL ON TABLE "public"."v_subscription_health" TO "authenticated";
GRANT ALL ON TABLE "public"."v_subscription_health" TO "service_role";



GRANT ALL ON TABLE "public"."v_subscription_health_v2" TO "postgres";
GRANT ALL ON TABLE "public"."v_subscription_health_v2" TO "anon";
GRANT ALL ON TABLE "public"."v_subscription_health_v2" TO "authenticated";
GRANT ALL ON TABLE "public"."v_subscription_health_v2" TO "service_role";



GRANT ALL ON TABLE "public"."v_tag_patient_counts" TO "postgres";
GRANT ALL ON TABLE "public"."v_tag_patient_counts" TO "anon";
GRANT ALL ON TABLE "public"."v_tag_patient_counts" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tag_patient_counts" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_active_subscription" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_active_subscription" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_active_subscription" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_active_subscription" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_entitlements" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_entitlements" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_entitlements" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_entitlements" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_entitlements_full" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_entitlements_full" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_entitlements_full" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_entitlements_full" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_entitlements_json" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_entitlements_json" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_entitlements_json" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_entitlements_json" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_feature_exceptions" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_feature_exceptions" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_feature_exceptions" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_feature_exceptions" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_feature_mismatch" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_feature_mismatch" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_feature_mismatch" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_feature_mismatch" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_members_with_profiles" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_members_with_profiles" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_members_with_profiles" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_members_with_profiles" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_people" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_people" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_people" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_people" TO "service_role";



GRANT ALL ON TABLE "public"."v_tenant_staff" TO "postgres";
GRANT ALL ON TABLE "public"."v_tenant_staff" TO "anon";
GRANT ALL ON TABLE "public"."v_tenant_staff" TO "authenticated";
GRANT ALL ON TABLE "public"."v_tenant_staff" TO "service_role";



GRANT ALL ON TABLE "public"."v_user_active_subscription" TO "postgres";
GRANT ALL ON TABLE "public"."v_user_active_subscription" TO "anon";
GRANT ALL ON TABLE "public"."v_user_active_subscription" TO "authenticated";
GRANT ALL ON TABLE "public"."v_user_active_subscription" TO "service_role";



GRANT ALL ON TABLE "public"."v_user_entitlements" TO "postgres";
GRANT ALL ON TABLE "public"."v_user_entitlements" TO "anon";
GRANT ALL ON TABLE "public"."v_user_entitlements" TO "authenticated";
GRANT ALL ON TABLE "public"."v_user_entitlements" TO "service_role";









ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "service_role";






ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "service_role";






ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "service_role";































