20659 lines
700 KiB
PL/PgSQL
20659 lines
700 KiB
PL/PgSQL
--
|
|
-- PostgreSQL database dump
|
|
--
|
|
|
|
\restrict bF1wUs8GdUoGkTriiI6ANM1G5CWmXBDmeY0qMLRMwq4O6xbnSjM03LBj5DO29ct
|
|
|
|
-- Dumped from database version 17.6
|
|
-- Dumped by pg_dump version 17.6
|
|
|
|
SET statement_timeout = 0;
|
|
SET lock_timeout = 0;
|
|
SET idle_in_transaction_session_timeout = 0;
|
|
SET transaction_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;
|
|
|
|
--
|
|
-- Name: _realtime; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA _realtime;
|
|
|
|
|
|
--
|
|
-- Name: auth; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA auth;
|
|
|
|
|
|
--
|
|
-- Name: pg_cron; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pg_cron WITH SCHEMA pg_catalog;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION pg_cron; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION pg_cron IS 'Job scheduler for PostgreSQL';
|
|
|
|
|
|
--
|
|
-- Name: extensions; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA extensions;
|
|
|
|
|
|
--
|
|
-- Name: graphql; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA graphql;
|
|
|
|
|
|
--
|
|
-- Name: graphql_public; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA graphql_public;
|
|
|
|
|
|
--
|
|
-- Name: pg_net; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pg_net WITH SCHEMA extensions;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION pg_net; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION pg_net IS 'Async HTTP';
|
|
|
|
|
|
--
|
|
-- Name: pgbouncer; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA pgbouncer;
|
|
|
|
|
|
--
|
|
-- Name: realtime; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA realtime;
|
|
|
|
|
|
--
|
|
-- Name: storage; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA storage;
|
|
|
|
|
|
--
|
|
-- Name: supabase_functions; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA supabase_functions;
|
|
|
|
|
|
--
|
|
-- Name: vault; Type: SCHEMA; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE SCHEMA vault;
|
|
|
|
|
|
--
|
|
-- Name: btree_gist; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS btree_gist WITH SCHEMA public;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION btree_gist; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION btree_gist IS 'support for indexing common datatypes in GiST';
|
|
|
|
|
|
--
|
|
-- Name: citext; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS citext WITH SCHEMA public;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION citext; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION citext IS 'data type for case-insensitive character strings';
|
|
|
|
|
|
--
|
|
-- Name: pg_graphql; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pg_graphql WITH SCHEMA graphql;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION pg_graphql; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION pg_graphql IS 'pg_graphql: GraphQL support';
|
|
|
|
|
|
--
|
|
-- Name: pg_stat_statements; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA extensions;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION pg_stat_statements; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION pg_stat_statements IS 'track planning and execution statistics of all SQL statements executed';
|
|
|
|
|
|
--
|
|
-- Name: pg_trgm; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION pg_trgm; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams';
|
|
|
|
|
|
--
|
|
-- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA extensions;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION pgcrypto; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions';
|
|
|
|
|
|
--
|
|
-- Name: supabase_vault; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS supabase_vault WITH SCHEMA vault;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION supabase_vault; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION supabase_vault IS 'Supabase Vault Extension';
|
|
|
|
|
|
--
|
|
-- Name: uuid-ossp; Type: EXTENSION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA extensions;
|
|
|
|
|
|
--
|
|
-- Name: EXTENSION "uuid-ossp"; Type: COMMENT; Schema: -; Owner: -
|
|
--
|
|
|
|
COMMENT ON EXTENSION "uuid-ossp" IS 'generate universally unique identifiers (UUIDs)';
|
|
|
|
|
|
--
|
|
-- Name: aal_level; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.aal_level AS ENUM (
|
|
'aal1',
|
|
'aal2',
|
|
'aal3'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: code_challenge_method; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.code_challenge_method AS ENUM (
|
|
's256',
|
|
'plain'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: factor_status; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.factor_status AS ENUM (
|
|
'unverified',
|
|
'verified'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: factor_type; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.factor_type AS ENUM (
|
|
'totp',
|
|
'webauthn',
|
|
'phone'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: oauth_authorization_status; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.oauth_authorization_status AS ENUM (
|
|
'pending',
|
|
'approved',
|
|
'denied',
|
|
'expired'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: oauth_client_type; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.oauth_client_type AS ENUM (
|
|
'public',
|
|
'confidential'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: oauth_registration_type; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.oauth_registration_type AS ENUM (
|
|
'dynamic',
|
|
'manual'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: oauth_response_type; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.oauth_response_type AS ENUM (
|
|
'code'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: one_time_token_type; Type: TYPE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TYPE auth.one_time_token_type AS ENUM (
|
|
'confirmation_token',
|
|
'reauthentication_token',
|
|
'recovery_token',
|
|
'email_change_token_new',
|
|
'email_change_token_current',
|
|
'phone_change_token'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: commitment_log_source; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.commitment_log_source AS ENUM (
|
|
'manual',
|
|
'auto'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: determined_field_type; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.determined_field_type AS ENUM (
|
|
'text',
|
|
'textarea',
|
|
'number',
|
|
'date',
|
|
'select',
|
|
'boolean'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: financial_record_type; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.financial_record_type AS ENUM (
|
|
'receita',
|
|
'despesa'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exception_type; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.recurrence_exception_type AS ENUM (
|
|
'cancel_session',
|
|
'reschedule_session',
|
|
'patient_missed',
|
|
'therapist_canceled',
|
|
'holiday_block'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_type; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.recurrence_type AS ENUM (
|
|
'weekly',
|
|
'biweekly',
|
|
'monthly',
|
|
'yearly',
|
|
'custom_weekdays'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: status_agenda_serie; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.status_agenda_serie AS ENUM (
|
|
'ativo',
|
|
'pausado',
|
|
'cancelado'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: status_evento_agenda; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.status_evento_agenda AS ENUM (
|
|
'agendado',
|
|
'realizado',
|
|
'faltou',
|
|
'cancelado',
|
|
'remarcar'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: status_excecao_agenda; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.status_excecao_agenda AS ENUM (
|
|
'pendente',
|
|
'ativo',
|
|
'arquivado'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tipo_evento_agenda; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.tipo_evento_agenda AS ENUM (
|
|
'sessao',
|
|
'bloqueio'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tipo_excecao_agenda; Type: TYPE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TYPE public.tipo_excecao_agenda AS ENUM (
|
|
'bloqueio',
|
|
'horario_extra'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: action; Type: TYPE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TYPE realtime.action AS ENUM (
|
|
'INSERT',
|
|
'UPDATE',
|
|
'DELETE',
|
|
'TRUNCATE',
|
|
'ERROR'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: equality_op; Type: TYPE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TYPE realtime.equality_op AS ENUM (
|
|
'eq',
|
|
'neq',
|
|
'lt',
|
|
'lte',
|
|
'gt',
|
|
'gte',
|
|
'in'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: user_defined_filter; Type: TYPE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TYPE realtime.user_defined_filter AS (
|
|
column_name text,
|
|
op realtime.equality_op,
|
|
value text
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: wal_column; Type: TYPE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TYPE realtime.wal_column AS (
|
|
name text,
|
|
type_name text,
|
|
type_oid oid,
|
|
value jsonb,
|
|
is_pkey boolean,
|
|
is_selectable boolean
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: wal_rls; Type: TYPE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TYPE realtime.wal_rls AS (
|
|
wal jsonb,
|
|
is_rls_enabled boolean,
|
|
subscription_ids uuid[],
|
|
errors text[]
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: buckettype; Type: TYPE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TYPE storage.buckettype AS ENUM (
|
|
'STANDARD',
|
|
'ANALYTICS',
|
|
'VECTOR'
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: email(); Type: FUNCTION; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION auth.email() RETURNS text
|
|
LANGUAGE sql STABLE
|
|
AS $$
|
|
select
|
|
coalesce(
|
|
nullif(current_setting('request.jwt.claim.email', true), ''),
|
|
(nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'email')
|
|
)::text
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION email(); Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION auth.email() IS 'Deprecated. Use auth.jwt() -> ''email'' instead.';
|
|
|
|
|
|
--
|
|
-- Name: jwt(); Type: FUNCTION; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION auth.jwt() RETURNS jsonb
|
|
LANGUAGE sql STABLE
|
|
AS $$
|
|
select
|
|
coalesce(
|
|
nullif(current_setting('request.jwt.claim', true), ''),
|
|
nullif(current_setting('request.jwt.claims', true), '')
|
|
)::jsonb
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: role(); Type: FUNCTION; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION auth.role() RETURNS text
|
|
LANGUAGE sql STABLE
|
|
AS $$
|
|
select
|
|
coalesce(
|
|
nullif(current_setting('request.jwt.claim.role', true), ''),
|
|
(nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'role')
|
|
)::text
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION role(); Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION auth.role() IS 'Deprecated. Use auth.jwt() -> ''role'' instead.';
|
|
|
|
|
|
--
|
|
-- Name: uid(); Type: FUNCTION; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION auth.uid() RETURNS uuid
|
|
LANGUAGE sql STABLE
|
|
AS $$
|
|
select
|
|
coalesce(
|
|
nullif(current_setting('request.jwt.claim.sub', true), ''),
|
|
(nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub')
|
|
)::uuid
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION uid(); Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION auth.uid() IS 'Deprecated. Use auth.jwt() -> ''sub'' instead.';
|
|
|
|
|
|
--
|
|
-- Name: grant_pg_cron_access(); Type: FUNCTION; Schema: extensions; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION extensions.grant_pg_cron_access() RETURNS event_trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
IF EXISTS (
|
|
SELECT
|
|
FROM pg_event_trigger_ddl_commands() AS ev
|
|
JOIN pg_extension AS ext
|
|
ON ev.objid = ext.oid
|
|
WHERE ext.extname = 'pg_cron'
|
|
)
|
|
THEN
|
|
grant usage on schema cron to postgres with grant option;
|
|
|
|
alter default privileges in schema cron grant all on tables to postgres with grant option;
|
|
alter default privileges in schema cron grant all on functions to postgres with grant option;
|
|
alter default privileges in schema cron grant all on sequences to postgres with grant option;
|
|
|
|
alter default privileges for user supabase_admin in schema cron grant all
|
|
on sequences to postgres with grant option;
|
|
alter default privileges for user supabase_admin in schema cron grant all
|
|
on tables to postgres with grant option;
|
|
alter default privileges for user supabase_admin in schema cron grant all
|
|
on functions to postgres with grant option;
|
|
|
|
grant all privileges on all tables in schema cron to postgres with grant option;
|
|
revoke all on table cron.job from postgres;
|
|
grant select on table cron.job to postgres with grant option;
|
|
END IF;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION grant_pg_cron_access(); Type: COMMENT; Schema: extensions; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION extensions.grant_pg_cron_access() IS 'Grants access to pg_cron';
|
|
|
|
|
|
--
|
|
-- Name: grant_pg_graphql_access(); Type: FUNCTION; Schema: extensions; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION extensions.grant_pg_graphql_access() RETURNS event_trigger
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
DECLARE
|
|
func_is_graphql_resolve bool;
|
|
BEGIN
|
|
func_is_graphql_resolve = (
|
|
SELECT n.proname = 'resolve'
|
|
FROM pg_event_trigger_ddl_commands() AS ev
|
|
LEFT JOIN pg_catalog.pg_proc AS n
|
|
ON ev.objid = n.oid
|
|
);
|
|
|
|
IF func_is_graphql_resolve
|
|
THEN
|
|
-- Update public wrapper to pass all arguments through to the pg_graphql resolve func
|
|
DROP FUNCTION IF EXISTS graphql_public.graphql;
|
|
create or replace function graphql_public.graphql(
|
|
"operationName" text default null,
|
|
query text default null,
|
|
variables jsonb default null,
|
|
extensions jsonb default null
|
|
)
|
|
returns jsonb
|
|
language sql
|
|
as $$
|
|
select graphql.resolve(
|
|
query := query,
|
|
variables := coalesce(variables, '{}'),
|
|
"operationName" := "operationName",
|
|
extensions := extensions
|
|
);
|
|
$$;
|
|
|
|
-- This hook executes when `graphql.resolve` is created. That is not necessarily the last
|
|
-- function in the extension so we need to grant permissions on existing entities AND
|
|
-- update default permissions to any others that are created after `graphql.resolve`
|
|
grant usage on schema graphql to postgres, anon, authenticated, service_role;
|
|
grant select on all tables in schema graphql to postgres, anon, authenticated, service_role;
|
|
grant execute on all functions in schema graphql to postgres, anon, authenticated, service_role;
|
|
grant all on all sequences in schema graphql to postgres, anon, authenticated, service_role;
|
|
alter default privileges in schema graphql grant all on tables to postgres, anon, authenticated, service_role;
|
|
alter default privileges in schema graphql grant all on functions to postgres, anon, authenticated, service_role;
|
|
alter default privileges in schema graphql grant all on sequences to postgres, anon, authenticated, service_role;
|
|
|
|
-- Allow postgres role to allow granting usage on graphql and graphql_public schemas to custom roles
|
|
grant usage on schema graphql_public to postgres with grant option;
|
|
grant usage on schema graphql to postgres with grant option;
|
|
END IF;
|
|
|
|
END;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION grant_pg_graphql_access(); Type: COMMENT; Schema: extensions; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION extensions.grant_pg_graphql_access() IS 'Grants access to pg_graphql';
|
|
|
|
|
|
--
|
|
-- Name: grant_pg_net_access(); Type: FUNCTION; Schema: extensions; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION extensions.grant_pg_net_access() RETURNS event_trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
IF EXISTS (
|
|
SELECT 1
|
|
FROM pg_event_trigger_ddl_commands() AS ev
|
|
JOIN pg_extension AS ext
|
|
ON ev.objid = ext.oid
|
|
WHERE ext.extname = 'pg_net'
|
|
)
|
|
THEN
|
|
GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role;
|
|
|
|
ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
|
|
ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
|
|
|
|
ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
|
|
ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
|
|
|
|
REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
|
|
REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
|
|
|
|
GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
|
|
GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
|
|
END IF;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION grant_pg_net_access(); Type: COMMENT; Schema: extensions; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION extensions.grant_pg_net_access() IS 'Grants access to pg_net';
|
|
|
|
|
|
--
|
|
-- Name: pgrst_ddl_watch(); Type: FUNCTION; Schema: extensions; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION extensions.pgrst_ddl_watch() RETURNS event_trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
cmd record;
|
|
BEGIN
|
|
FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands()
|
|
LOOP
|
|
IF cmd.command_tag IN (
|
|
'CREATE SCHEMA', 'ALTER SCHEMA'
|
|
, 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE'
|
|
, 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE'
|
|
, 'CREATE VIEW', 'ALTER VIEW'
|
|
, 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW'
|
|
, 'CREATE FUNCTION', 'ALTER FUNCTION'
|
|
, 'CREATE TRIGGER'
|
|
, 'CREATE TYPE', 'ALTER TYPE'
|
|
, 'CREATE RULE'
|
|
, 'COMMENT'
|
|
)
|
|
-- don't notify in case of CREATE TEMP table or other objects created on pg_temp
|
|
AND cmd.schema_name is distinct from 'pg_temp'
|
|
THEN
|
|
NOTIFY pgrst, 'reload schema';
|
|
END IF;
|
|
END LOOP;
|
|
END; $$;
|
|
|
|
|
|
--
|
|
-- Name: pgrst_drop_watch(); Type: FUNCTION; Schema: extensions; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION extensions.pgrst_drop_watch() RETURNS event_trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
obj record;
|
|
BEGIN
|
|
FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
|
|
LOOP
|
|
IF obj.object_type IN (
|
|
'schema'
|
|
, 'table'
|
|
, 'foreign table'
|
|
, 'view'
|
|
, 'materialized view'
|
|
, 'function'
|
|
, 'trigger'
|
|
, 'type'
|
|
, 'rule'
|
|
)
|
|
AND obj.is_temporary IS false -- no pg_temp objects
|
|
THEN
|
|
NOTIFY pgrst, 'reload schema';
|
|
END IF;
|
|
END LOOP;
|
|
END; $$;
|
|
|
|
|
|
--
|
|
-- Name: set_graphql_placeholder(); Type: FUNCTION; Schema: extensions; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION extensions.set_graphql_placeholder() RETURNS event_trigger
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
DECLARE
|
|
graphql_is_dropped bool;
|
|
BEGIN
|
|
graphql_is_dropped = (
|
|
SELECT ev.schema_name = 'graphql_public'
|
|
FROM pg_event_trigger_dropped_objects() AS ev
|
|
WHERE ev.schema_name = 'graphql_public'
|
|
);
|
|
|
|
IF graphql_is_dropped
|
|
THEN
|
|
create or replace function graphql_public.graphql(
|
|
"operationName" text default null,
|
|
query text default null,
|
|
variables jsonb default null,
|
|
extensions jsonb default null
|
|
)
|
|
returns jsonb
|
|
language plpgsql
|
|
as $$
|
|
DECLARE
|
|
server_version float;
|
|
BEGIN
|
|
server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float);
|
|
|
|
IF server_version >= 14 THEN
|
|
RETURN jsonb_build_object(
|
|
'errors', jsonb_build_array(
|
|
jsonb_build_object(
|
|
'message', 'pg_graphql extension is not enabled.'
|
|
)
|
|
)
|
|
);
|
|
ELSE
|
|
RETURN jsonb_build_object(
|
|
'errors', jsonb_build_array(
|
|
jsonb_build_object(
|
|
'message', 'pg_graphql is only available on projects running Postgres 14 onwards.'
|
|
)
|
|
)
|
|
);
|
|
END IF;
|
|
END;
|
|
$$;
|
|
END IF;
|
|
|
|
END;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION set_graphql_placeholder(); Type: COMMENT; Schema: extensions; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION extensions.set_graphql_placeholder() IS 'Reintroduces placeholder function for graphql_public.graphql';
|
|
|
|
|
|
--
|
|
-- Name: get_auth(text); Type: FUNCTION; Schema: pgbouncer; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION pgbouncer.get_auth(p_usename text) RETURNS TABLE(username text, password text)
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO ''
|
|
AS $_$
|
|
begin
|
|
raise debug 'PgBouncer auth request: %', p_usename;
|
|
|
|
return query
|
|
select
|
|
rolname::text,
|
|
case when rolvaliduntil < now()
|
|
then null
|
|
else rolpassword::text
|
|
end
|
|
from pg_authid
|
|
where rolname=$1 and rolcanlogin;
|
|
end;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: __rls_ping(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.__rls_ping() RETURNS text
|
|
LANGUAGE sql STABLE
|
|
AS $$
|
|
select 'ok'::text;
|
|
$$;
|
|
|
|
|
|
SET default_tablespace = '';
|
|
|
|
SET default_table_access_method = heap;
|
|
|
|
--
|
|
-- Name: subscriptions; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: activate_subscription_from_intent(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: admin_credit_addon(uuid, text, integer, uuid, text, text, integer); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.admin_credit_addon(p_tenant_id uuid, p_addon_type text, p_amount integer, p_product_id uuid DEFAULT NULL::uuid, p_description text DEFAULT 'Cr??dito manual'::text, p_payment_method text DEFAULT 'manual'::text, p_price_cents integer DEFAULT 0) RETURNS jsonb
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_credit addon_credits%ROWTYPE;
|
|
v_balance_before INTEGER;
|
|
v_balance_after INTEGER;
|
|
v_tx_id UUID;
|
|
BEGIN
|
|
-- Upsert addon_credits
|
|
INSERT INTO addon_credits (tenant_id, addon_type, balance, total_purchased)
|
|
VALUES (p_tenant_id, p_addon_type, 0, 0)
|
|
ON CONFLICT (tenant_id, addon_type) DO NOTHING;
|
|
|
|
-- Lock e leitura
|
|
SELECT * INTO v_credit
|
|
FROM addon_credits
|
|
WHERE tenant_id = p_tenant_id AND addon_type = p_addon_type
|
|
FOR UPDATE;
|
|
|
|
v_balance_before := v_credit.balance;
|
|
v_balance_after := v_credit.balance + p_amount;
|
|
|
|
-- Atualiza saldo
|
|
UPDATE addon_credits
|
|
SET balance = v_balance_after,
|
|
total_purchased = total_purchased + p_amount,
|
|
low_balance_notified = CASE WHEN v_balance_after > COALESCE(low_balance_threshold, 10) THEN false ELSE low_balance_notified END,
|
|
updated_at = now()
|
|
WHERE id = v_credit.id;
|
|
|
|
-- Registra transa????o
|
|
INSERT INTO addon_transactions (
|
|
tenant_id, addon_type, type, amount,
|
|
balance_before, balance_after,
|
|
product_id, description,
|
|
admin_user_id, payment_method, price_cents
|
|
) VALUES (
|
|
p_tenant_id, p_addon_type, 'purchase', p_amount,
|
|
v_balance_before, v_balance_after,
|
|
p_product_id, p_description,
|
|
auth.uid(), p_payment_method, p_price_cents
|
|
)
|
|
RETURNING id INTO v_tx_id;
|
|
|
|
RETURN jsonb_build_object(
|
|
'success', true,
|
|
'transaction_id', v_tx_id,
|
|
'balance_before', v_balance_before,
|
|
'balance_after', v_balance_after
|
|
);
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION admin_credit_addon(p_tenant_id uuid, p_addon_type text, p_amount integer, p_product_id uuid, p_description text, p_payment_method text, p_price_cents integer); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION public.admin_credit_addon(p_tenant_id uuid, p_addon_type text, p_amount integer, p_product_id uuid, p_description text, p_payment_method text, p_price_cents integer) IS 'Admin adiciona cr??ditos de add-on a um tenant. Cria registro se n??o existir.';
|
|
|
|
|
|
--
|
|
-- Name: admin_delete_email_template_global(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.admin_delete_email_template_global(p_id uuid) RETURNS boolean
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
BEGIN
|
|
DELETE FROM public.email_templates_global WHERE id = p_id;
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'Template com id % n??o encontrado', p_id;
|
|
END IF;
|
|
RETURN true;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: admin_fix_plan_target(text, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: admin_upsert_email_template_global(uuid, text, text, text, text, text, text, boolean, jsonb); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.admin_upsert_email_template_global(p_id uuid DEFAULT NULL::uuid, p_key text DEFAULT NULL::text, p_domain text DEFAULT NULL::text, p_channel text DEFAULT 'email'::text, p_subject text DEFAULT NULL::text, p_body_html text DEFAULT NULL::text, p_body_text text DEFAULT NULL::text, p_is_active boolean DEFAULT true, p_variables jsonb DEFAULT '{}'::jsonb) RETURNS jsonb
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_result jsonb;
|
|
v_id uuid;
|
|
BEGIN
|
|
-- UPDATE existente
|
|
IF p_id IS NOT NULL THEN
|
|
UPDATE public.email_templates_global
|
|
SET
|
|
subject = COALESCE(p_subject, subject),
|
|
body_html = COALESCE(p_body_html, body_html),
|
|
body_text = p_body_text,
|
|
is_active = p_is_active,
|
|
variables = COALESCE(p_variables, variables),
|
|
version = version + 1
|
|
WHERE id = p_id
|
|
RETURNING to_jsonb(email_templates_global.*) INTO v_result;
|
|
|
|
IF v_result IS NULL THEN
|
|
RAISE EXCEPTION 'Template com id % n??o encontrado', p_id;
|
|
END IF;
|
|
|
|
RETURN v_result;
|
|
END IF;
|
|
|
|
-- INSERT novo
|
|
IF p_key IS NULL OR p_domain IS NULL OR p_subject IS NULL OR p_body_html IS NULL THEN
|
|
RAISE EXCEPTION 'key, domain, subject e body_html s??o obrigat??rios para novo template';
|
|
END IF;
|
|
|
|
INSERT INTO public.email_templates_global (key, domain, channel, subject, body_html, body_text, is_active, variables)
|
|
VALUES (p_key, p_domain, p_channel, p_subject, p_body_html, p_body_text, p_is_active, p_variables)
|
|
RETURNING to_jsonb(email_templates_global.*) INTO v_result;
|
|
|
|
RETURN v_result;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: agenda_cfg_sync(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: agendador_dias_disponiveis(text, integer, integer); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
v_bloqueado 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;
|
|
|
|
-- ?????? Dia inteiro bloqueado? (agenda_bloqueios) ???????????????????????????????????????????????????????????????????????????
|
|
SELECT EXISTS (
|
|
SELECT 1 FROM public.agenda_bloqueios b
|
|
WHERE b.owner_id = v_owner_id
|
|
AND b.data_inicio <= v_data
|
|
AND COALESCE(b.data_fim, v_data) >= v_data
|
|
AND b.hora_inicio IS NULL -- bloqueio de dia inteiro
|
|
AND (
|
|
(NOT b.recorrente)
|
|
OR (b.recorrente AND b.dia_semana = v_db_dow)
|
|
)
|
|
) INTO v_bloqueado;
|
|
|
|
IF v_bloqueado THEN
|
|
v_data := v_data + 1;
|
|
CONTINUE;
|
|
END IF;
|
|
|
|
-- ?????? Tem slots dispon??veis no dia? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????
|
|
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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: agendador_gerar_slug(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: agendador_slots_disponiveis(text, date); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
-- ?????? Dia inteiro bloqueado? (agenda_bloqueios sem hora) ?????????????????????????????????????????????????????????
|
|
-- Se sim, n??o h?? nenhum slot dispon??vel ??? retorna vazio.
|
|
IF EXISTS (
|
|
SELECT 1 FROM public.agenda_bloqueios b
|
|
WHERE b.owner_id = v_owner_id
|
|
AND b.data_inicio <= p_data
|
|
AND COALESCE(b.data_fim, p_data) >= p_data
|
|
AND b.hora_inicio IS NULL -- bloqueio de dia inteiro
|
|
AND (
|
|
(NOT b.recorrente)
|
|
OR (b.recorrente AND b.dia_semana = v_db_dow)
|
|
)
|
|
) THEN
|
|
RETURN;
|
|
END IF;
|
|
|
|
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;
|
|
|
|
-- ?????? Bloqueio de hor??rio espec??fico (agenda_bloqueios com hora) ?????????????????????????????????
|
|
IF NOT v_ocupado THEN
|
|
SELECT EXISTS (
|
|
SELECT 1 FROM public.agenda_bloqueios b
|
|
WHERE b.owner_id = v_owner_id
|
|
AND b.data_inicio <= p_data
|
|
AND COALESCE(b.data_fim, p_data) >= p_data
|
|
AND b.hora_inicio IS NOT NULL
|
|
AND b.hora_inicio < v_slot_fim
|
|
AND b.hora_fim > v_slot
|
|
AND (
|
|
(NOT b.recorrente)
|
|
OR (b.recorrente AND b.dia_semana = v_db_dow)
|
|
)
|
|
) INTO v_ocupado;
|
|
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) ?????????????????????????????????????????????????????????????????????????????????????????????
|
|
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
|
|
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;
|
|
|
|
IF v_day_diff >= 0 AND v_day_diff % (7 * v_rule.interval) = 0 THEN
|
|
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;
|
|
|
|
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;
|
|
END IF;
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
-- ?????? Recorr??ncias remarcadas para este dia ????????????????????????????????????????????????????????????????????????????????????????????????
|
|
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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: auto_create_financial_record_from_session(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.auto_create_financial_record_from_session() RETURNS trigger
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_price NUMERIC(10,2);
|
|
v_services_total NUMERIC(10,2);
|
|
v_already_billed BOOLEAN;
|
|
BEGIN
|
|
-- ?????? Guards de sa??da r??pida ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
|
|
|
|
-- S?? processa quando o status muda PARA 'realizado'
|
|
IF NEW.status::TEXT <> 'realizado' THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
-- S?? processa quando houve mudan??a real de status
|
|
IF OLD.status IS NOT DISTINCT FROM NEW.status THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
-- S?? sess??es (n??o bloqueios, feriados, etc.)
|
|
IF NEW.tipo::TEXT <> 'sessao' THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
-- Paciente obrigat??rio para vincular a cobran??a
|
|
IF NEW.patient_id IS NULL THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
-- Sess??es de pacote t??m cobran??a gerenciada por billing_contract
|
|
IF NEW.billing_contract_id IS NOT NULL THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
-- Idempot??ncia: j?? existe financial_record para este evento?
|
|
SELECT billed INTO v_already_billed
|
|
FROM public.agenda_eventos
|
|
WHERE id = NEW.id;
|
|
|
|
IF v_already_billed = TRUE THEN
|
|
-- Confirma no financial_records tamb??m (dupla verifica????o)
|
|
IF EXISTS (
|
|
SELECT 1 FROM public.financial_records
|
|
WHERE agenda_evento_id = NEW.id AND deleted_at IS NULL
|
|
) THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
END IF;
|
|
|
|
-- ?????? Busca do pre??o ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
|
|
|
|
v_price := NULL;
|
|
|
|
-- Prioridade 1: soma dos servi??os da regra de recorr??ncia
|
|
IF NEW.recurrence_id IS NOT NULL THEN
|
|
SELECT COALESCE(SUM(rrs.final_price), 0)
|
|
INTO v_services_total
|
|
FROM public.recurrence_rule_services rrs
|
|
WHERE rrs.rule_id = NEW.recurrence_id;
|
|
|
|
IF v_services_total > 0 THEN
|
|
v_price := v_services_total;
|
|
END IF;
|
|
|
|
-- Prioridade 2: price direto da regra (fallback se sem servi??os)
|
|
IF v_price IS NULL OR v_price = 0 THEN
|
|
SELECT price INTO v_price
|
|
FROM public.recurrence_rules
|
|
WHERE id = NEW.recurrence_id;
|
|
END IF;
|
|
END IF;
|
|
|
|
-- Prioridade 3: price do pr??prio evento de agenda
|
|
IF v_price IS NULL OR v_price = 0 THEN
|
|
v_price := NEW.price;
|
|
END IF;
|
|
|
|
-- Sem pre??o ??? n??o criar registro (n??o ?? erro, apenas skip silencioso)
|
|
IF v_price IS NULL OR v_price <= 0 THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
-- ?????? Cria????o do financial_record ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
|
|
|
|
INSERT INTO public.financial_records (
|
|
owner_id,
|
|
tenant_id,
|
|
patient_id,
|
|
agenda_evento_id,
|
|
type,
|
|
amount,
|
|
discount_amount,
|
|
final_amount,
|
|
clinic_fee_pct,
|
|
clinic_fee_amount,
|
|
status,
|
|
due_date
|
|
-- payment_method: NULL at?? o momento do pagamento (mark_as_paid preenche)
|
|
) VALUES (
|
|
NEW.owner_id,
|
|
NEW.tenant_id,
|
|
NEW.patient_id,
|
|
NEW.id,
|
|
'receita',
|
|
v_price,
|
|
0,
|
|
v_price,
|
|
0, -- clinic_fee_pct: sem campo de configura????o global no schema atual.
|
|
0, -- clinic_fee_amount: calculado manualmente ou via update posterior.
|
|
'pending',
|
|
(NEW.inicio_em::DATE + 7) -- vencimento padr??o: 7 dias ap??s a sess??o
|
|
);
|
|
|
|
-- ?????? Marca sess??o como billed ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
|
|
-- UPDATE em billed (n??o em status) ??? n??o re-dispara este trigger
|
|
UPDATE public.agenda_eventos
|
|
SET billed = TRUE
|
|
WHERE id = NEW.id;
|
|
|
|
RETURN NEW;
|
|
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
-- Log silencioso: nunca bloquear a agenda por falha financeira
|
|
RAISE WARNING '[auto_create_financial_record_from_session] evento=% erro=%',
|
|
NEW.id, SQLERRM;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION auto_create_financial_record_from_session(); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION public.auto_create_financial_record_from_session() IS 'Trigger que cria automaticamente um financial_record (receita, pending) quando uma sess??o de agenda ?? marcada como realizada. Prioridade de pre??o: recurrence_rule_services > recurrence_rules.price > agenda_eventos.price. Skip silencioso se sem pre??o, pacote ou registro j?? existente.';
|
|
|
|
|
|
--
|
|
-- Name: can_delete_patient(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.can_delete_patient(p_patient_id uuid) RETURNS boolean
|
|
LANGUAGE sql STABLE SECURITY DEFINER
|
|
AS $$
|
|
SELECT NOT EXISTS (
|
|
SELECT 1 FROM public.agenda_eventos WHERE patient_id = p_patient_id
|
|
UNION ALL
|
|
SELECT 1 FROM public.recurrence_rules WHERE patient_id = p_patient_id
|
|
UNION ALL
|
|
SELECT 1 FROM public.billing_contracts WHERE patient_id = p_patient_id
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: cancel_notifications_on_opt_out(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.cancel_notifications_on_opt_out() RETURNS trigger
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
BEGIN
|
|
-- WhatsApp opt-out
|
|
IF OLD.whatsapp_opt_in = true AND NEW.whatsapp_opt_in = false THEN
|
|
PERFORM public.cancel_patient_pending_notifications(
|
|
NEW.patient_id, 'whatsapp'
|
|
);
|
|
END IF;
|
|
-- Email opt-out
|
|
IF OLD.email_opt_in = true AND NEW.email_opt_in = false THEN
|
|
PERFORM public.cancel_patient_pending_notifications(
|
|
NEW.patient_id, 'email'
|
|
);
|
|
END IF;
|
|
-- SMS opt-out
|
|
IF OLD.sms_opt_in = true AND NEW.sms_opt_in = false THEN
|
|
PERFORM public.cancel_patient_pending_notifications(
|
|
NEW.patient_id, 'sms'
|
|
);
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: cancel_notifications_on_session_cancel(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.cancel_notifications_on_session_cancel() RETURNS trigger
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
BEGIN
|
|
IF NEW.status IN ('cancelado', 'excluido')
|
|
AND OLD.status NOT IN ('cancelado', 'excluido')
|
|
THEN
|
|
PERFORM public.cancel_patient_pending_notifications(
|
|
NEW.patient_id, NULL, NEW.id
|
|
);
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: cancel_patient_pending_notifications(uuid, text, uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.cancel_patient_pending_notifications(p_patient_id uuid, p_channel text DEFAULT NULL::text, p_evento_id uuid DEFAULT NULL::uuid) RETURNS integer
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
v_canceled integer;
|
|
BEGIN
|
|
UPDATE public.notification_queue
|
|
SET status = 'cancelado',
|
|
updated_at = now()
|
|
WHERE patient_id = p_patient_id
|
|
AND status IN ('pendente', 'processando')
|
|
AND (p_channel IS NULL OR channel = p_channel)
|
|
AND (p_evento_id IS NULL OR agenda_evento_id = p_evento_id);
|
|
|
|
GET DIAGNOSTICS v_canceled = ROW_COUNT;
|
|
RETURN v_canceled;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: cancel_recurrence_from(uuid, date); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: cancel_subscription(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: cancelar_eventos_serie(uuid, timestamp with time zone); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION cancelar_eventos_serie(p_serie_id uuid, p_a_partir_de timestamp with time zone); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
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.';
|
|
|
|
|
|
--
|
|
-- Name: change_subscription_plan(uuid, uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: cleanup_notification_queue(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.cleanup_notification_queue() RETURNS integer
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
v_deleted integer;
|
|
BEGIN
|
|
DELETE FROM public.notification_queue
|
|
WHERE status IN ('enviado', 'cancelado', 'ignorado')
|
|
AND created_at < now() - interval '90 days';
|
|
|
|
GET DIAGNOSTICS v_deleted = ROW_COUNT;
|
|
RETURN v_deleted;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: create_clinic_tenant(text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: financial_records; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.financial_records (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid,
|
|
type public.financial_record_type DEFAULT 'receita'::public.financial_record_type NOT NULL,
|
|
amount numeric(10,2) NOT NULL,
|
|
description text,
|
|
category text,
|
|
payment_method text,
|
|
paid_at timestamp with time zone,
|
|
due_date date,
|
|
installments smallint DEFAULT 1,
|
|
installment_number smallint DEFAULT 1,
|
|
installment_group uuid,
|
|
agenda_evento_id uuid,
|
|
patient_id uuid,
|
|
clinic_fee_pct numeric(5,2) DEFAULT 0,
|
|
clinic_fee_amount numeric(10,2) DEFAULT 0,
|
|
net_amount numeric(10,2) GENERATED ALWAYS AS ((amount - clinic_fee_amount)) STORED,
|
|
insurance_plan_id uuid,
|
|
notes text,
|
|
tags text[],
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
deleted_at timestamp with time zone,
|
|
discount_amount numeric(10,2) DEFAULT 0 NOT NULL,
|
|
final_amount numeric(10,2) DEFAULT 0 NOT NULL,
|
|
status text DEFAULT 'pending'::text NOT NULL,
|
|
category_id uuid,
|
|
CONSTRAINT financial_records_amount_check CHECK ((amount >= (0)::numeric)),
|
|
CONSTRAINT financial_records_clinic_fee_amount_check CHECK ((clinic_fee_amount >= (0)::numeric)),
|
|
CONSTRAINT financial_records_clinic_fee_pct_check CHECK (((clinic_fee_pct >= (0)::numeric) AND (clinic_fee_pct <= (100)::numeric))),
|
|
CONSTRAINT financial_records_discount_amount_check CHECK ((discount_amount >= (0)::numeric)),
|
|
CONSTRAINT financial_records_final_amount_check CHECK ((final_amount >= (0)::numeric)),
|
|
CONSTRAINT financial_records_installments_check CHECK ((installments >= 1)),
|
|
CONSTRAINT financial_records_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'paid'::text, 'partial'::text, 'overdue'::text, 'cancelled'::text, 'refunded'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: create_financial_record_for_session(uuid, uuid, uuid, uuid, numeric, date); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.create_financial_record_for_session(p_tenant_id uuid, p_owner_id uuid, p_patient_id uuid, p_agenda_evento_id uuid, p_amount numeric, p_due_date date) RETURNS SETOF public.financial_records
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_existing public.financial_records%ROWTYPE;
|
|
v_new public.financial_records%ROWTYPE;
|
|
BEGIN
|
|
-- Idempot??ncia: retorna o registro existente se j?? foi criado
|
|
SELECT * INTO v_existing
|
|
FROM public.financial_records
|
|
WHERE agenda_evento_id = p_agenda_evento_id
|
|
AND deleted_at IS NULL
|
|
LIMIT 1;
|
|
|
|
IF FOUND THEN
|
|
RETURN NEXT v_existing;
|
|
RETURN;
|
|
END IF;
|
|
|
|
-- Cria o novo registro
|
|
INSERT INTO public.financial_records (
|
|
tenant_id,
|
|
owner_id,
|
|
patient_id,
|
|
agenda_evento_id,
|
|
amount,
|
|
discount_amount,
|
|
final_amount,
|
|
status,
|
|
due_date
|
|
) VALUES (
|
|
p_tenant_id,
|
|
p_owner_id,
|
|
p_patient_id,
|
|
p_agenda_evento_id,
|
|
p_amount,
|
|
0,
|
|
p_amount,
|
|
'pending',
|
|
p_due_date
|
|
)
|
|
RETURNING * INTO v_new;
|
|
|
|
-- Marca o evento da agenda como billed = true
|
|
UPDATE public.agenda_eventos
|
|
SET billed = TRUE
|
|
WHERE id = p_agenda_evento_id;
|
|
|
|
RETURN NEXT v_new;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: create_patient_intake_request(text, text, text, text, text, boolean); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: create_patient_intake_request_v2(text, jsonb); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: create_support_session(uuid, integer); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.create_support_session(p_tenant_id uuid, p_ttl_minutes integer DEFAULT 60) RETURNS json
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_admin_id uuid;
|
|
v_role text;
|
|
v_token text;
|
|
v_expires timestamp with time zone;
|
|
v_session support_sessions;
|
|
BEGIN
|
|
-- Verifica autentica????o
|
|
v_admin_id := auth.uid();
|
|
IF v_admin_id IS NULL THEN
|
|
RAISE EXCEPTION 'N??o autenticado.' USING ERRCODE = 'P0001';
|
|
END IF;
|
|
|
|
-- Verifica role saas_admin
|
|
SELECT role INTO v_role
|
|
FROM public.profiles
|
|
WHERE id = v_admin_id;
|
|
|
|
IF v_role <> 'saas_admin' THEN
|
|
RAISE EXCEPTION 'Acesso negado. Somente saas_admin pode criar sess??es de suporte.'
|
|
USING ERRCODE = 'P0002';
|
|
END IF;
|
|
|
|
-- Valida TTL (1 a 120 minutos)
|
|
IF p_ttl_minutes < 1 OR p_ttl_minutes > 120 THEN
|
|
RAISE EXCEPTION 'TTL inv??lido. Use entre 1 e 120 minutos.'
|
|
USING ERRCODE = 'P0003';
|
|
END IF;
|
|
|
|
-- Valida tenant
|
|
IF NOT EXISTS (SELECT 1 FROM public.tenants WHERE id = p_tenant_id) THEN
|
|
RAISE EXCEPTION 'Tenant n??o encontrado.'
|
|
USING ERRCODE = 'P0004';
|
|
END IF;
|
|
|
|
-- Gera token ??nico (64 chars hex, sem pgcrypto)
|
|
v_token := replace(gen_random_uuid()::text, '-', '') || replace(gen_random_uuid()::text, '-', '');
|
|
v_expires := now() + (p_ttl_minutes || ' minutes')::interval;
|
|
|
|
-- Insere sess??o
|
|
INSERT INTO public.support_sessions (tenant_id, admin_id, token, expires_at)
|
|
VALUES (p_tenant_id, v_admin_id, v_token, v_expires)
|
|
RETURNING * INTO v_session;
|
|
|
|
RETURN json_build_object(
|
|
'token', v_session.token,
|
|
'expires_at', v_session.expires_at,
|
|
'session_id', v_session.id
|
|
);
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: therapist_payouts; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.therapist_payouts (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
period_start date NOT NULL,
|
|
period_end date NOT NULL,
|
|
total_sessions integer DEFAULT 0 NOT NULL,
|
|
gross_amount numeric(10,2) DEFAULT 0 NOT NULL,
|
|
clinic_fee_total numeric(10,2) DEFAULT 0 NOT NULL,
|
|
net_amount numeric(10,2) DEFAULT 0 NOT NULL,
|
|
status text DEFAULT 'pending'::text NOT NULL,
|
|
paid_at timestamp with time zone,
|
|
notes text,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT therapist_payouts_clinic_fee_total_check CHECK ((clinic_fee_total >= (0)::numeric)),
|
|
CONSTRAINT therapist_payouts_gross_amount_check CHECK ((gross_amount >= (0)::numeric)),
|
|
CONSTRAINT therapist_payouts_net_amount_check CHECK ((net_amount >= (0)::numeric)),
|
|
CONSTRAINT therapist_payouts_period_chk CHECK ((period_end >= period_start)),
|
|
CONSTRAINT therapist_payouts_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'paid'::text, 'cancelled'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: create_therapist_payout(uuid, uuid, date, date); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.create_therapist_payout(p_tenant_id uuid, p_therapist_id uuid, p_period_start date, p_period_end date) RETURNS public.therapist_payouts
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_payout public.therapist_payouts%ROWTYPE;
|
|
v_total_sessions INTEGER;
|
|
v_gross NUMERIC(10,2);
|
|
v_clinic_fee NUMERIC(10,2);
|
|
v_net NUMERIC(10,2);
|
|
BEGIN
|
|
-- ?????? Verifica????o de permiss??o ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
|
|
-- Apenas o pr??prio terapeuta ou o tenant_admin pode criar o repasse
|
|
IF auth.uid() <> p_therapist_id AND NOT public.is_tenant_admin(p_tenant_id) THEN
|
|
RAISE EXCEPTION 'Sem permiss??o para criar repasse para este terapeuta.';
|
|
END IF;
|
|
|
|
-- ?????? Verifica se j?? existe repasse para o mesmo per??odo ???????????????????????????????????????????????????
|
|
IF EXISTS (
|
|
SELECT 1 FROM public.therapist_payouts
|
|
WHERE owner_id = p_therapist_id
|
|
AND tenant_id = p_tenant_id
|
|
AND period_start = p_period_start
|
|
AND period_end = p_period_end
|
|
AND status <> 'cancelled'
|
|
) THEN
|
|
RAISE EXCEPTION
|
|
'J?? existe um repasse ativo para o per??odo % a % deste terapeuta.',
|
|
p_period_start, p_period_end;
|
|
END IF;
|
|
|
|
-- ?????? Agrega os financial_records eleg??veis ??????????????????????????????????????????????????????????????????????????????????????????
|
|
-- Eleg??veis: paid, receita, owner=terapeuta, tenant correto, paid_at no per??odo,
|
|
-- n??o soft-deleted, ainda n??o vinculados a nenhum payout.
|
|
SELECT
|
|
COUNT(*) AS total_sessions,
|
|
COALESCE(SUM(amount), 0) AS gross_amount,
|
|
COALESCE(SUM(clinic_fee_amount), 0) AS clinic_fee_total,
|
|
COALESCE(SUM(net_amount), 0) AS net_amount
|
|
INTO
|
|
v_total_sessions, v_gross, v_clinic_fee, v_net
|
|
FROM public.financial_records fr
|
|
WHERE fr.owner_id = p_therapist_id
|
|
AND fr.tenant_id = p_tenant_id
|
|
AND fr.type = 'receita'
|
|
AND fr.status = 'paid'
|
|
AND fr.deleted_at IS NULL
|
|
AND fr.paid_at::DATE BETWEEN p_period_start AND p_period_end
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM public.therapist_payout_records tpr
|
|
WHERE tpr.financial_record_id = fr.id
|
|
);
|
|
|
|
-- Sem registros eleg??veis ??? n??o criar payout vazio
|
|
IF v_total_sessions = 0 THEN
|
|
RAISE EXCEPTION
|
|
'Nenhum registro financeiro eleg??vel encontrado para o per??odo % a %.',
|
|
p_period_start, p_period_end;
|
|
END IF;
|
|
|
|
-- ?????? Cria o repasse ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
|
|
INSERT INTO public.therapist_payouts (
|
|
owner_id,
|
|
tenant_id,
|
|
period_start,
|
|
period_end,
|
|
total_sessions,
|
|
gross_amount,
|
|
clinic_fee_total,
|
|
net_amount,
|
|
status
|
|
) VALUES (
|
|
p_therapist_id,
|
|
p_tenant_id,
|
|
p_period_start,
|
|
p_period_end,
|
|
v_total_sessions,
|
|
v_gross,
|
|
v_clinic_fee,
|
|
v_net,
|
|
'pending'
|
|
)
|
|
RETURNING * INTO v_payout;
|
|
|
|
-- ?????? Vincula os financial_records ao repasse ????????????????????????????????????????????????????????????????????????????????????
|
|
INSERT INTO public.therapist_payout_records (payout_id, financial_record_id)
|
|
SELECT v_payout.id, fr.id
|
|
FROM public.financial_records fr
|
|
WHERE fr.owner_id = p_therapist_id
|
|
AND fr.tenant_id = p_tenant_id
|
|
AND fr.type = 'receita'
|
|
AND fr.status = 'paid'
|
|
AND fr.deleted_at IS NULL
|
|
AND fr.paid_at::DATE BETWEEN p_period_start AND p_period_end
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM public.therapist_payout_records tpr
|
|
WHERE tpr.financial_record_id = fr.id
|
|
);
|
|
|
|
RETURN v_payout;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION create_therapist_payout(p_tenant_id uuid, p_therapist_id uuid, p_period_start date, p_period_end date); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION public.create_therapist_payout(p_tenant_id uuid, p_therapist_id uuid, p_period_start date, p_period_end date) IS 'Cria um repasse para o terapeuta com todos os financial_records paid+receita do per??odo que ainda n??o estejam vinculados a outro repasse. Lan??a exce????o se n??o houver registros eleg??veis ou se j?? houver repasse ativo no per??odo.';
|
|
|
|
|
|
--
|
|
-- Name: current_member_id(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: current_member_role(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: debit_addon_credit(uuid, text, uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.debit_addon_credit(p_tenant_id uuid, p_addon_type text, p_queue_id uuid DEFAULT NULL::uuid, p_description text DEFAULT 'Consumo'::text) RETURNS jsonb
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_credit addon_credits%ROWTYPE;
|
|
v_balance_before INTEGER;
|
|
v_balance_after INTEGER;
|
|
BEGIN
|
|
-- Lock e leitura
|
|
SELECT * INTO v_credit
|
|
FROM addon_credits
|
|
WHERE tenant_id = p_tenant_id AND addon_type = p_addon_type AND is_active = true
|
|
FOR UPDATE;
|
|
|
|
IF NOT FOUND THEN
|
|
RETURN jsonb_build_object('success', false, 'reason', 'no_credits', 'balance', 0);
|
|
END IF;
|
|
|
|
-- Verifica saldo
|
|
IF v_credit.balance <= 0 THEN
|
|
RETURN jsonb_build_object('success', false, 'reason', 'insufficient_balance', 'balance', 0);
|
|
END IF;
|
|
|
|
-- Verifica rate limit di??rio
|
|
IF v_credit.daily_limit IS NOT NULL THEN
|
|
-- Reset se passou do dia
|
|
IF v_credit.daily_reset_at IS NULL OR v_credit.daily_reset_at < date_trunc('day', now()) THEN
|
|
UPDATE addon_credits SET daily_used = 0, daily_reset_at = date_trunc('day', now()) + interval '1 day' WHERE id = v_credit.id;
|
|
v_credit.daily_used := 0;
|
|
END IF;
|
|
|
|
IF v_credit.daily_used >= v_credit.daily_limit THEN
|
|
RETURN jsonb_build_object('success', false, 'reason', 'daily_limit_reached', 'balance', v_credit.balance);
|
|
END IF;
|
|
END IF;
|
|
|
|
-- Verifica rate limit hor??rio
|
|
IF v_credit.hourly_limit IS NOT NULL THEN
|
|
IF v_credit.hourly_reset_at IS NULL OR v_credit.hourly_reset_at < date_trunc('hour', now()) THEN
|
|
UPDATE addon_credits SET hourly_used = 0, hourly_reset_at = date_trunc('hour', now()) + interval '1 hour' WHERE id = v_credit.id;
|
|
v_credit.hourly_used := 0;
|
|
END IF;
|
|
|
|
IF v_credit.hourly_used >= v_credit.hourly_limit THEN
|
|
RETURN jsonb_build_object('success', false, 'reason', 'hourly_limit_reached', 'balance', v_credit.balance);
|
|
END IF;
|
|
END IF;
|
|
|
|
-- Verifica expira????o
|
|
IF v_credit.expires_at IS NOT NULL AND v_credit.expires_at < now() THEN
|
|
RETURN jsonb_build_object('success', false, 'reason', 'credits_expired', 'balance', v_credit.balance);
|
|
END IF;
|
|
|
|
v_balance_before := v_credit.balance;
|
|
v_balance_after := v_credit.balance - 1;
|
|
|
|
-- Debita
|
|
UPDATE addon_credits
|
|
SET balance = v_balance_after,
|
|
total_consumed = total_consumed + 1,
|
|
daily_used = COALESCE(daily_used, 0) + 1,
|
|
hourly_used = COALESCE(hourly_used, 0) + 1,
|
|
updated_at = now()
|
|
WHERE id = v_credit.id;
|
|
|
|
-- Registra transa????o
|
|
INSERT INTO addon_transactions (
|
|
tenant_id, addon_type, type, amount,
|
|
balance_before, balance_after,
|
|
queue_id, description
|
|
) VALUES (
|
|
p_tenant_id, p_addon_type, 'consume', -1,
|
|
v_balance_before, v_balance_after,
|
|
p_queue_id, p_description
|
|
);
|
|
|
|
RETURN jsonb_build_object(
|
|
'success', true,
|
|
'balance_before', v_balance_before,
|
|
'balance_after', v_balance_after
|
|
);
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION debit_addon_credit(p_tenant_id uuid, p_addon_type text, p_queue_id uuid, p_description text); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION public.debit_addon_credit(p_tenant_id uuid, p_addon_type text, p_queue_id uuid, p_description text) IS 'Debita 1 cr??dito de add-on. Verifica saldo, rate limits e expira????o.';
|
|
|
|
|
|
--
|
|
-- Name: delete_commitment_full(uuid, uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: delete_determined_commitment(uuid, uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: dev_list_auth_users(integer); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: dev_list_custom_users(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: dev_list_intent_leads(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: dev_public_debug_snapshot(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: ensure_personal_tenant(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: ensure_personal_tenant_for_user(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: faq_votar(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: fix_all_subscription_mismatches(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: fn_agenda_regras_semanais_no_overlap(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: get_financial_report(uuid, date, date, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.get_financial_report(p_owner_id uuid, p_start_date date, p_end_date date, p_group_by text DEFAULT 'month'::text) RETURNS TABLE(group_key text, group_label text, total_receitas numeric, total_despesas numeric, saldo numeric, total_pendente numeric, total_overdue numeric, count_records bigint)
|
|
LANGUAGE sql STABLE SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
|
|
-- ?????? Valida p_group_by antes de executar ??????????????????????????????????????????????????????????????????????????????????????????????????????
|
|
-- (lan??a erro se valor inv??lido; plpgsql seria necess??rio para isso em SQL puro,
|
|
-- ent??o usamos um CTE de valida????o com CASE WHEN para retornar vazio em vez de erro)
|
|
|
|
WITH base AS (
|
|
SELECT
|
|
fr.type,
|
|
fr.amount,
|
|
fr.final_amount,
|
|
fr.status,
|
|
fr.deleted_at,
|
|
-- Chave de agrupamento calculada conforme p_group_by
|
|
CASE p_group_by
|
|
WHEN 'month' THEN TO_CHAR(
|
|
COALESCE(fr.paid_at::DATE, fr.due_date, fr.created_at::DATE),
|
|
'YYYY-MM'
|
|
)
|
|
WHEN 'week' THEN TO_CHAR(
|
|
COALESCE(fr.paid_at::DATE, fr.due_date, fr.created_at::DATE),
|
|
'IYYY-"W"IW'
|
|
)
|
|
WHEN 'category' THEN COALESCE(fr.category_id::TEXT, fr.category, 'sem_categoria')
|
|
WHEN 'patient' THEN COALESCE(fr.patient_id::TEXT, 'sem_paciente')
|
|
ELSE NULL -- group_by inv??lido ??? group_key NULL ??? retorno vazio
|
|
END AS gkey,
|
|
-- Label leg??vel (enriquecido via JOIN abaixo quando poss??vel)
|
|
CASE p_group_by
|
|
WHEN 'month' THEN TO_CHAR(
|
|
COALESCE(fr.paid_at::DATE, fr.due_date, fr.created_at::DATE),
|
|
'YYYY-MM'
|
|
)
|
|
WHEN 'week' THEN TO_CHAR(
|
|
COALESCE(fr.paid_at::DATE, fr.due_date, fr.created_at::DATE),
|
|
'IYYY-"W"IW'
|
|
)
|
|
WHEN 'category' THEN COALESCE(fc.name, fr.category, 'Sem categoria')
|
|
WHEN 'patient' THEN COALESCE(p.nome_completo, fr.patient_id::TEXT, 'Sem paciente')
|
|
ELSE NULL
|
|
END AS glabel
|
|
FROM public.financial_records fr
|
|
LEFT JOIN public.financial_categories fc
|
|
ON fc.id = fr.category_id
|
|
LEFT JOIN public.patients p
|
|
ON p.id = fr.patient_id
|
|
WHERE fr.owner_id = p_owner_id
|
|
AND fr.deleted_at IS NULL
|
|
AND COALESCE(fr.paid_at::DATE, fr.due_date, fr.created_at::DATE)
|
|
BETWEEN p_start_date AND p_end_date
|
|
)
|
|
|
|
SELECT
|
|
gkey AS group_key,
|
|
glabel AS group_label,
|
|
|
|
COALESCE(SUM(final_amount) FILTER (WHERE type = 'receita' AND status = 'paid'), 0)
|
|
AS total_receitas,
|
|
|
|
COALESCE(SUM(final_amount) FILTER (WHERE type = 'despesa' AND status = 'paid'), 0)
|
|
AS total_despesas,
|
|
|
|
COALESCE(SUM(final_amount) FILTER (WHERE type = 'receita' AND status = 'paid'), 0)
|
|
- COALESCE(SUM(final_amount) FILTER (WHERE type = 'despesa' AND status = 'paid'), 0)
|
|
AS saldo,
|
|
|
|
COALESCE(SUM(final_amount) FILTER (WHERE status = 'pending'), 0) AS total_pendente,
|
|
|
|
COALESCE(SUM(final_amount) FILTER (WHERE status = 'overdue'), 0) AS total_overdue,
|
|
|
|
COUNT(*) AS count_records
|
|
|
|
FROM base
|
|
WHERE gkey IS NOT NULL -- descarta p_group_by inv??lido
|
|
GROUP BY gkey, glabel
|
|
ORDER BY gkey ASC;
|
|
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION get_financial_report(p_owner_id uuid, p_start_date date, p_end_date date, p_group_by text); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION public.get_financial_report(p_owner_id uuid, p_start_date date, p_end_date date, p_group_by text) IS 'Relat??rio financeiro agrupado por m??s, semana ISO, categoria ou paciente. p_group_by aceita: ''month'' | ''week'' | ''category'' | ''patient''. Totais de receita/despesa consideram apenas registros com status=paid. total_pendente e total_overdue incluem todos os tipos (receita + despesa).';
|
|
|
|
|
|
--
|
|
-- Name: get_financial_summary(uuid, integer, integer); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.get_financial_summary(p_owner_id uuid, p_year integer, p_month integer) RETURNS TABLE(total_receitas numeric, total_despesas numeric, total_pendente numeric, saldo_liquido numeric, total_repasse numeric, count_receitas bigint, count_despesas bigint)
|
|
LANGUAGE sql STABLE SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
SELECT
|
|
-- Receitas pagas no per??odo
|
|
COALESCE(SUM(amount) FILTER (
|
|
WHERE type = 'receita' AND status = 'paid'
|
|
), 0) AS total_receitas,
|
|
|
|
-- Despesas pagas no per??odo
|
|
COALESCE(SUM(amount) FILTER (
|
|
WHERE type = 'despesa' AND status = 'paid'
|
|
), 0) AS total_despesas,
|
|
|
|
-- Tudo pendente ou vencido (receitas + despesas)
|
|
COALESCE(SUM(amount) FILTER (
|
|
WHERE status IN ('pending', 'overdue')
|
|
), 0) AS total_pendente,
|
|
|
|
-- Saldo l??quido (receitas pagas ??? despesas pagas)
|
|
COALESCE(SUM(amount) FILTER (
|
|
WHERE type = 'receita' AND status = 'paid'
|
|
), 0)
|
|
- COALESCE(SUM(amount) FILTER (
|
|
WHERE type = 'despesa' AND status = 'paid'
|
|
), 0) AS saldo_liquido,
|
|
|
|
-- Total repassado ?? cl??nica (apenas receitas pagas)
|
|
COALESCE(SUM(clinic_fee_amount) FILTER (
|
|
WHERE type = 'receita' AND status = 'paid'
|
|
), 0) AS total_repasse,
|
|
|
|
-- Contadores (excluindo soft-deleted)
|
|
COUNT(*) FILTER (WHERE type = 'receita' AND deleted_at IS NULL) AS count_receitas,
|
|
COUNT(*) FILTER (WHERE type = 'despesa' AND deleted_at IS NULL) AS count_despesas
|
|
|
|
FROM public.financial_records
|
|
WHERE owner_id = p_owner_id
|
|
AND deleted_at IS NULL
|
|
AND EXTRACT(YEAR FROM COALESCE(paid_at::DATE, due_date, created_at::DATE)) = p_year
|
|
AND EXTRACT(MONTH FROM COALESCE(paid_at::DATE, due_date, created_at::DATE)) = p_month;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: get_my_email(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: guard_account_type_immutable(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: guard_locked_commitment(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: guard_no_change_core_plan_key(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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 $$;
|
|
|
|
|
|
--
|
|
-- Name: guard_no_change_plan_target(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: guard_no_delete_core_plans(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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 $$;
|
|
|
|
|
|
--
|
|
-- Name: guard_patient_cannot_own_tenant(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: guard_tenant_kind_immutable(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: handle_new_user(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: handle_new_user_create_personal_tenant(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: has_feature(uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: is_clinic_tenant(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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')
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: is_saas_admin(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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()
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: is_tenant_admin(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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'
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: is_tenant_member(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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'
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: is_therapist_tenant(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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'
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: jwt_email(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.jwt_email() RETURNS text
|
|
LANGUAGE sql STABLE
|
|
AS $$
|
|
select nullif(lower(current_setting('request.jwt.claim.email', true)), '');
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: list_financial_records(uuid, integer, integer, text, text, uuid, integer, integer); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.list_financial_records(p_owner_id uuid, p_year integer DEFAULT NULL::integer, p_month integer DEFAULT NULL::integer, p_type text DEFAULT NULL::text, p_status text DEFAULT NULL::text, p_patient_id uuid DEFAULT NULL::uuid, p_limit integer DEFAULT 50, p_offset integer DEFAULT 0) RETURNS SETOF public.financial_records
|
|
LANGUAGE sql STABLE SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
SELECT *
|
|
FROM public.financial_records
|
|
WHERE owner_id = p_owner_id
|
|
AND deleted_at IS NULL
|
|
AND (p_type IS NULL OR type::TEXT = p_type)
|
|
AND (p_status IS NULL OR status = p_status)
|
|
AND (p_patient_id IS NULL OR patient_id = p_patient_id)
|
|
AND (p_year IS NULL OR EXTRACT(YEAR FROM COALESCE(paid_at::DATE, due_date, created_at::DATE)) = p_year)
|
|
AND (p_month IS NULL OR EXTRACT(MONTH FROM COALESCE(paid_at::DATE, due_date, created_at::DATE)) = p_month)
|
|
ORDER BY COALESCE(paid_at, due_date::TIMESTAMPTZ, created_at) DESC
|
|
LIMIT p_limit
|
|
OFFSET p_offset;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: mark_as_paid(uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.mark_as_paid(p_financial_record_id uuid, p_payment_method text) RETURNS SETOF public.financial_records
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_record public.financial_records%ROWTYPE;
|
|
BEGIN
|
|
-- Garante que o registro pertence ao usu??rio autenticado (RLS n??o aplica em SECURITY DEFINER)
|
|
SELECT * INTO v_record
|
|
FROM public.financial_records
|
|
WHERE id = p_financial_record_id
|
|
AND owner_id = auth.uid()
|
|
AND deleted_at IS NULL;
|
|
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'Registro financeiro n??o encontrado ou sem permiss??o.';
|
|
END IF;
|
|
|
|
IF v_record.status NOT IN ('pending', 'overdue') THEN
|
|
RAISE EXCEPTION 'Apenas cobran??as pendentes ou vencidas podem ser marcadas como pagas.';
|
|
END IF;
|
|
|
|
UPDATE public.financial_records
|
|
SET status = 'paid',
|
|
paid_at = NOW(),
|
|
payment_method = p_payment_method,
|
|
updated_at = NOW()
|
|
WHERE id = p_financial_record_id
|
|
RETURNING * INTO v_record;
|
|
|
|
RETURN NEXT v_record;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: mark_payout_as_paid(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.mark_payout_as_paid(p_payout_id uuid) RETURNS public.therapist_payouts
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_payout public.therapist_payouts%ROWTYPE;
|
|
BEGIN
|
|
-- Busca o payout
|
|
SELECT * INTO v_payout
|
|
FROM public.therapist_payouts
|
|
WHERE id = p_payout_id;
|
|
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'Repasse n??o encontrado: %', p_payout_id;
|
|
END IF;
|
|
|
|
-- Verifica permiss??o: apenas tenant_admin do tenant do repasse
|
|
IF NOT public.is_tenant_admin(v_payout.tenant_id) THEN
|
|
RAISE EXCEPTION 'Apenas o administrador da cl??nica pode marcar repasses como pagos.';
|
|
END IF;
|
|
|
|
-- Verifica status
|
|
IF v_payout.status <> 'pending' THEN
|
|
RAISE EXCEPTION
|
|
'Repasse j?? est?? com status ''%''. Apenas repasses pendentes podem ser pagos.',
|
|
v_payout.status;
|
|
END IF;
|
|
|
|
-- Atualiza
|
|
UPDATE public.therapist_payouts
|
|
SET
|
|
status = 'paid',
|
|
paid_at = NOW(),
|
|
updated_at = NOW()
|
|
WHERE id = p_payout_id
|
|
RETURNING * INTO v_payout;
|
|
|
|
RETURN v_payout;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION mark_payout_as_paid(p_payout_id uuid); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION public.mark_payout_as_paid(p_payout_id uuid) IS 'Marca um repasse de terapeuta como pago. Apenas o tenant_admin pode chamar. Apenas repasses com status=pending podem ser finalizados.';
|
|
|
|
|
|
--
|
|
-- Name: my_tenants(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: notice_track_click(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.notice_track_click(p_notice_id uuid) RETURNS void
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
begin
|
|
update public.global_notices
|
|
set clicks_count = clicks_count + 1
|
|
where id = p_notice_id;
|
|
end;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: notice_track_view(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.notice_track_view(p_notice_id uuid) RETURNS void
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
begin
|
|
update public.global_notices
|
|
set views_count = views_count + 1
|
|
where id = p_notice_id;
|
|
end;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: notify_on_intake(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.notify_on_intake() RETURNS trigger
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
BEGIN
|
|
IF NEW.status = 'new' THEN
|
|
INSERT INTO public.notifications (
|
|
owner_id,
|
|
tenant_id,
|
|
type,
|
|
ref_id,
|
|
ref_table,
|
|
payload
|
|
)
|
|
VALUES (
|
|
NEW.owner_id,
|
|
NEW.tenant_id,
|
|
'new_patient',
|
|
NEW.id,
|
|
'patient_intake_requests',
|
|
jsonb_build_object(
|
|
'title', 'Novo cadastro externo',
|
|
'detail', COALESCE(NEW.nome_completo, 'Paciente'),
|
|
'deeplink', '/therapist/patients/cadastro/recebidos',
|
|
'avatar_initials', upper(left(COALESCE(NEW.nome_completo, '?'), 2))
|
|
)
|
|
);
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: notify_on_scheduling(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.notify_on_scheduling() RETURNS trigger
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$ BEGIN IF NEW.status = 'pendente' THEN
|
|
INSERT INTO public.notifications ( owner_id, tenant_id, type, ref_id, ref_table, payload ) VALUES (
|
|
NEW.owner_id, NEW.tenant_id,
|
|
'new_scheduling', NEW.id, 'agendador_solicitacoes', jsonb_build_object( 'title', 'Nova solicita????o de agendamento', 'detail', COALESCE(NEW.paciente_nome, 'Paciente') || ' ' || COALESCE(NEW.paciente_sobrenome, '') || ' ??? ' || COALESCE(NEW.tipo, ''), 'deeplink', '/therapist/agendamentos-recebidos', 'avatar_initials', upper(left(COALESCE(NEW.paciente_nome, '?'), 1) || left(COALESCE(NEW.paciente_sobrenome, ''), 1)) ) ); END IF; RETURN NEW; END; $$;
|
|
|
|
|
|
--
|
|
-- Name: notify_on_session_status(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.notify_on_session_status() RETURNS trigger
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
v_nome text;
|
|
BEGIN
|
|
IF NEW.status IN ('faltou', 'cancelado') AND OLD.status IS DISTINCT FROM NEW.status THEN
|
|
|
|
SELECT nome_completo
|
|
INTO v_nome
|
|
FROM public.patients
|
|
WHERE id = NEW.patient_id
|
|
LIMIT 1;
|
|
|
|
INSERT INTO public.notifications (
|
|
owner_id,
|
|
tenant_id,
|
|
type,
|
|
ref_id,
|
|
ref_table,
|
|
payload
|
|
)
|
|
VALUES (
|
|
NEW.owner_id,
|
|
NEW.tenant_id,
|
|
'session_status',
|
|
NEW.id,
|
|
'agenda_eventos',
|
|
jsonb_build_object(
|
|
'title', CASE WHEN NEW.status = 'faltou' THEN 'Paciente faltou' ELSE 'Sess??o cancelada' END,
|
|
'detail', COALESCE(v_nome, 'Paciente') || ' ??? ' || to_char(NEW.inicio_em, 'DD/MM HH24:MI'),
|
|
'deeplink', '/therapist/agenda',
|
|
'avatar_initials', upper(left(COALESCE(v_nome, '?'), 2))
|
|
)
|
|
);
|
|
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: on_new_user_seed_patient_groups(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: patients_validate_member_consistency(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: patients_validate_responsible_member_tenant(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: populate_notification_queue(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.populate_notification_queue() RETURNS void
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
BEGIN
|
|
INSERT INTO public.notification_queue (
|
|
tenant_id, owner_id, agenda_evento_id, patient_id,
|
|
channel, template_key, schedule_key,
|
|
resolved_vars, recipient_address,
|
|
scheduled_at, idempotency_key
|
|
)
|
|
SELECT
|
|
ae.tenant_id,
|
|
ae.owner_id,
|
|
ae.id AS agenda_evento_id,
|
|
ae.patient_id,
|
|
ch.channel,
|
|
'session.' || REPLACE(ns.event_type, '_sessao', '') || '.' || ch.channel,
|
|
ns.schedule_key,
|
|
jsonb_build_object(
|
|
'nome_paciente', COALESCE(p.nome_completo, 'Paciente'),
|
|
'data_sessao', TO_CHAR(ae.inicio_em AT TIME ZONE 'America/Sao_Paulo', 'DD/MM/YYYY'),
|
|
'hora_sessao', TO_CHAR(ae.inicio_em AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI'),
|
|
'nome_terapeuta', COALESCE(prof.full_name, 'Terapeuta'),
|
|
'modalidade', COALESCE(ae.modalidade, 'Presencial'),
|
|
'titulo', COALESCE(ae.titulo, 'Sess??o')
|
|
),
|
|
CASE ch.channel
|
|
WHEN 'whatsapp' THEN COALESCE(p.telefone, '')
|
|
WHEN 'sms' THEN COALESCE(p.telefone, '')
|
|
WHEN 'email' THEN COALESCE(p.email_principal, '')
|
|
END,
|
|
CASE
|
|
WHEN (ae.inicio_em - (ns.offset_minutes || ' minutes')::interval)::time
|
|
< ns.allowed_time_start
|
|
THEN DATE_TRUNC('day', ae.inicio_em - (ns.offset_minutes || ' minutes')::interval)
|
|
+ ns.allowed_time_start
|
|
WHEN (ae.inicio_em - (ns.offset_minutes || ' minutes')::interval)::time
|
|
> ns.allowed_time_end
|
|
THEN DATE_TRUNC('day', ae.inicio_em - (ns.offset_minutes || ' minutes')::interval)
|
|
+ ns.allowed_time_start
|
|
ELSE ae.inicio_em - (ns.offset_minutes || ' minutes')::interval
|
|
END,
|
|
ae.id::text || ':' || ns.schedule_key || ':' || ch.channel || ':'
|
|
|| ae.inicio_em::date::text
|
|
FROM public.agenda_eventos ae
|
|
JOIN public.patients p ON p.id = ae.patient_id
|
|
LEFT JOIN public.profiles prof ON prof.id = ae.owner_id
|
|
JOIN public.notification_schedules ns
|
|
ON ns.owner_id = ae.owner_id
|
|
AND ns.is_active = true
|
|
AND ns.deleted_at IS NULL
|
|
AND ns.trigger_type = 'before_event'
|
|
AND ns.event_type = 'lembrete_sessao'
|
|
JOIN public.notification_channels nc
|
|
ON nc.owner_id = ae.owner_id
|
|
AND nc.is_active = true
|
|
AND nc.deleted_at IS NULL
|
|
CROSS JOIN LATERAL (
|
|
SELECT 'whatsapp' AS channel WHERE ns.whatsapp_enabled AND nc.channel = 'whatsapp'
|
|
UNION ALL
|
|
SELECT 'email' AS channel WHERE ns.email_enabled AND nc.channel = 'email'
|
|
UNION ALL
|
|
SELECT 'sms' AS channel WHERE ns.sms_enabled AND nc.channel = 'sms'
|
|
) ch
|
|
LEFT JOIN public.notification_preferences np
|
|
ON np.patient_id = ae.patient_id
|
|
AND np.owner_id = ae.owner_id
|
|
AND np.deleted_at IS NULL
|
|
WHERE
|
|
ae.inicio_em > now()
|
|
AND ae.inicio_em <= now() + interval '48 hours'
|
|
AND ae.status NOT IN ('cancelado', 'faltou')
|
|
AND CASE ch.channel
|
|
WHEN 'whatsapp' THEN COALESCE(p.telefone, '') != ''
|
|
WHEN 'sms' THEN COALESCE(p.telefone, '') != ''
|
|
WHEN 'email' THEN COALESCE(p.email_principal, '') != ''
|
|
END
|
|
AND CASE ch.channel
|
|
WHEN 'whatsapp' THEN COALESCE(np.whatsapp_opt_in, true)
|
|
WHEN 'email' THEN COALESCE(np.email_opt_in, true)
|
|
WHEN 'sms' THEN COALESCE(np.sms_opt_in, false)
|
|
END
|
|
AND EXISTS (
|
|
SELECT 1 FROM public.profiles tp
|
|
WHERE tp.id = ae.owner_id
|
|
AND COALESCE(tp.notify_reminders, true) = true
|
|
)
|
|
ON CONFLICT (idempotency_key) DO NOTHING;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: prevent_promoting_to_system(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: prevent_saas_membership(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: prevent_system_group_changes(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: provision_account_tenant(uuid, text, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION provision_account_tenant(p_user_id uuid, p_kind text, p_name text); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
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';
|
|
|
|
|
|
--
|
|
-- Name: reactivate_subscription(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: rebuild_owner_entitlements(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: revoke_support_session(text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.revoke_support_session(p_token text) RETURNS boolean
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_admin_id uuid;
|
|
v_role text;
|
|
BEGIN
|
|
v_admin_id := auth.uid();
|
|
IF v_admin_id IS NULL THEN
|
|
RAISE EXCEPTION 'N??o autenticado.' USING ERRCODE = 'P0001';
|
|
END IF;
|
|
|
|
SELECT role INTO v_role FROM public.profiles WHERE id = v_admin_id;
|
|
IF v_role <> 'saas_admin' THEN
|
|
RAISE EXCEPTION 'Acesso negado.' USING ERRCODE = 'P0002';
|
|
END IF;
|
|
|
|
DELETE FROM public.support_sessions
|
|
WHERE token = p_token
|
|
AND admin_id = v_admin_id;
|
|
|
|
RETURN FOUND;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: rotate_patient_invite_token(text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: saas_votar_doc(uuid, boolean); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: safe_delete_patient(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.safe_delete_patient(p_patient_id uuid) RETURNS jsonb
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
BEGIN
|
|
-- Bloqueia se houver hist??rico
|
|
IF NOT public.can_delete_patient(p_patient_id) THEN
|
|
RETURN jsonb_build_object(
|
|
'ok', false,
|
|
'error', 'has_history',
|
|
'message', 'Este paciente possui hist??rico cl??nico ou financeiro e n??o pode ser removido. Voc?? pode desativar ou arquivar o paciente.'
|
|
);
|
|
END IF;
|
|
|
|
-- Verifica ownership via RLS (owner_id ou responsible_member_id)
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM public.patients
|
|
WHERE id = p_patient_id
|
|
AND (
|
|
owner_id = auth.uid()
|
|
OR responsible_member_id IN (
|
|
SELECT id FROM public.tenant_members WHERE user_id = auth.uid()
|
|
)
|
|
)
|
|
) THEN
|
|
RETURN jsonb_build_object(
|
|
'ok', false,
|
|
'error', 'forbidden',
|
|
'message', 'Sem permiss??o para excluir este paciente.'
|
|
);
|
|
END IF;
|
|
|
|
DELETE FROM public.patients WHERE id = p_patient_id;
|
|
|
|
RETURN jsonb_build_object('ok', true);
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: sanitize_phone_br(text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.sanitize_phone_br(raw_phone text) RETURNS text
|
|
LANGUAGE plpgsql IMMUTABLE
|
|
AS $$ DECLARE digits text;
|
|
BEGIN
|
|
digits := regexp_replace(COALESCE(raw_phone, ''), '[^0-9]', '', 'g');
|
|
IF digits = '' THEN RETURN ''; END IF;
|
|
IF length(digits) = 10 OR length(digits) = 11 THEN
|
|
digits := '55' || digits;
|
|
END IF;
|
|
RETURN digits;
|
|
END; $$;
|
|
|
|
|
|
--
|
|
-- Name: seed_default_financial_categories(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.seed_default_financial_categories(p_user_id uuid) RETURNS void
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
BEGIN
|
|
INSERT INTO public.financial_categories (user_id, name, type, color, icon, sort_order)
|
|
VALUES
|
|
(p_user_id, 'Sess??o', 'receita', '#22c55e', 'pi pi-heart', 1),
|
|
(p_user_id, 'Supervis??o', 'receita', '#6366f1', 'pi pi-users', 2),
|
|
(p_user_id, 'Conv??nio', 'receita', '#3b82f6', 'pi pi-building', 3),
|
|
(p_user_id, 'Grupo terap??utico', 'receita', '#f59e0b', 'pi pi-sitemap', 4),
|
|
(p_user_id, 'Outro (receita)', 'receita', '#8b5cf6', 'pi pi-plus-circle', 5),
|
|
(p_user_id, 'Aluguel sala', 'despesa', '#ef4444', 'pi pi-home', 1),
|
|
(p_user_id, 'Plataforma/SaaS', 'despesa', '#f97316', 'pi pi-desktop', 2),
|
|
(p_user_id, 'Repasse cl??nica', 'despesa', '#64748b', 'pi pi-arrow-right-arrow-left', 3),
|
|
(p_user_id, 'Supervis??o (custo)', 'despesa', '#6366f1', 'pi pi-users', 4),
|
|
(p_user_id, 'Outro (despesa)', 'despesa', '#94a3b8', 'pi pi-minus-circle', 5)
|
|
ON CONFLICT DO NOTHING;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: seed_default_patient_groups(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.seed_default_patient_groups(p_tenant_id uuid) RETURNS void
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_owner_id uuid;
|
|
BEGIN
|
|
-- busca o owner (tenant_admin) do tenant
|
|
SELECT user_id INTO v_owner_id
|
|
FROM public.tenant_members
|
|
WHERE tenant_id = p_tenant_id
|
|
AND role = 'tenant_admin'
|
|
AND status = 'active'
|
|
LIMIT 1;
|
|
|
|
IF v_owner_id IS NULL THEN
|
|
RETURN;
|
|
END IF;
|
|
|
|
INSERT INTO public.patient_groups (owner_id, nome, cor, is_system, tenant_id)
|
|
VALUES
|
|
(v_owner_id, 'Crian??as', '#60a5fa', true, p_tenant_id),
|
|
(v_owner_id, 'Adolescentes', '#a78bfa', true, p_tenant_id),
|
|
(v_owner_id, 'Idosos', '#34d399', true, p_tenant_id)
|
|
ON CONFLICT (owner_id, nome) DO NOTHING;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: seed_determined_commitments(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: set_insurance_plans_updated_at(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.set_insurance_plans_updated_at() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN NEW.updated_at = now(); RETURN NEW; END; $$;
|
|
|
|
|
|
--
|
|
-- Name: set_owner_id(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: set_services_updated_at(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.set_services_updated_at() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
NEW.updated_at = now();
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: set_tenant_feature_exception(uuid, text, boolean, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: set_updated_at(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.set_updated_at() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
NEW.updated_at = now();
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: set_updated_at_recurrence(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.set_updated_at_recurrence() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN NEW.updated_at = now(); RETURN NEW; END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: split_recurrence_at(uuid, date); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_view_insert(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_validate_scope(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: sync_busy_mirror_agenda_eventos(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: sync_overdue_financial_records(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.sync_overdue_financial_records() RETURNS integer
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_count integer;
|
|
BEGIN
|
|
UPDATE public.financial_records
|
|
SET
|
|
status = 'overdue',
|
|
updated_at = NOW()
|
|
WHERE status = 'pending'
|
|
AND due_date IS NOT NULL
|
|
AND due_date < CURRENT_DATE
|
|
AND deleted_at IS NULL;
|
|
|
|
GET DIAGNOSTICS v_count = ROW_COUNT;
|
|
RETURN v_count;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: FUNCTION sync_overdue_financial_records(); Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON FUNCTION public.sync_overdue_financial_records() IS 'Marca como overdue todos os financial_records pendentes com due_date vencido. Pode ser chamada manualmente, via pg_cron ou via Supabase Edge Function agendada.';
|
|
|
|
|
|
--
|
|
-- Name: tenant_accept_invite(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_members; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tenant_add_member_by_email(uuid, text, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_feature_allowed(uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_feature_enabled(uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_features_guard_with_plan(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_has_feature(uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_invite_member_by_email(uuid, text, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_reactivate_member(uuid, uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_remove_member(uuid, uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_remove_member_soft(uuid, uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_revoke_invite(uuid, text, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_set_member_status(uuid, uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: tenant_update_member_role(uuid, uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: toggle_plan(uuid); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: transition_subscription(uuid, text, text, jsonb); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: trg_fn_financial_records_auto_overdue(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.trg_fn_financial_records_auto_overdue() RETURNS trigger
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
BEGIN
|
|
IF NEW.status = 'pending'
|
|
AND NEW.due_date IS NOT NULL
|
|
AND NEW.due_date < CURRENT_DATE
|
|
THEN
|
|
NEW.status := 'overdue';
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: unstick_notification_queue(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.unstick_notification_queue() RETURNS integer
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
v_unstuck integer;
|
|
BEGIN
|
|
UPDATE public.notification_queue
|
|
SET status = 'pendente',
|
|
attempts = attempts + 1,
|
|
last_error = 'Timeout: preso em processando por >10min',
|
|
next_retry_at = now() + interval '2 minutes'
|
|
WHERE status = 'processando'
|
|
AND updated_at < now() - interval '10 minutes';
|
|
|
|
GET DIAGNOSTICS v_unstuck = ROW_COUNT;
|
|
RETURN v_unstuck;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: update_payment_settings_updated_at(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.update_payment_settings_updated_at() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
NEW.updated_at = now();
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: update_professional_pricing_updated_at(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.update_professional_pricing_updated_at() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
NEW.updated_at = now();
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: user_has_feature(uuid, text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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
|
|
);
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: validate_support_session(text); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.validate_support_session(p_token text) RETURNS json
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_session support_sessions;
|
|
BEGIN
|
|
IF p_token IS NULL OR length(trim(p_token)) < 32 THEN
|
|
RETURN json_build_object('valid', false, 'tenant_id', null);
|
|
END IF;
|
|
|
|
SELECT * INTO v_session
|
|
FROM public.support_sessions
|
|
WHERE token = p_token
|
|
AND expires_at > now()
|
|
LIMIT 1;
|
|
|
|
IF NOT FOUND THEN
|
|
RETURN json_build_object('valid', false, 'tenant_id', null);
|
|
END IF;
|
|
|
|
RETURN json_build_object(
|
|
'valid', true,
|
|
'tenant_id', v_session.tenant_id
|
|
);
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: whoami(); Type: FUNCTION; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION public.whoami() RETURNS TABLE(uid uuid, role text)
|
|
LANGUAGE sql STABLE
|
|
AS $$
|
|
select auth.uid() as uid, auth.role() as role;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: apply_rls(jsonb, integer); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer DEFAULT (1024 * 1024)) RETURNS SETOF realtime.wal_rls
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
declare
|
|
-- Regclass of the table e.g. public.notes
|
|
entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;
|
|
|
|
-- I, U, D, T: insert, update ...
|
|
action realtime.action = (
|
|
case wal ->> 'action'
|
|
when 'I' then 'INSERT'
|
|
when 'U' then 'UPDATE'
|
|
when 'D' then 'DELETE'
|
|
else 'ERROR'
|
|
end
|
|
);
|
|
|
|
-- Is row level security enabled for the table
|
|
is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;
|
|
|
|
subscriptions realtime.subscription[] = array_agg(subs)
|
|
from
|
|
realtime.subscription subs
|
|
where
|
|
subs.entity = entity_;
|
|
|
|
-- Subscription vars
|
|
roles regrole[] = array_agg(distinct us.claims_role::text)
|
|
from
|
|
unnest(subscriptions) us;
|
|
|
|
working_role regrole;
|
|
claimed_role regrole;
|
|
claims jsonb;
|
|
|
|
subscription_id uuid;
|
|
subscription_has_access bool;
|
|
visible_to_subscription_ids uuid[] = '{}';
|
|
|
|
-- structured info for wal's columns
|
|
columns realtime.wal_column[];
|
|
-- previous identity values for update/delete
|
|
old_columns realtime.wal_column[];
|
|
|
|
error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;
|
|
|
|
-- Primary jsonb output for record
|
|
output jsonb;
|
|
|
|
begin
|
|
perform set_config('role', null, true);
|
|
|
|
columns =
|
|
array_agg(
|
|
(
|
|
x->>'name',
|
|
x->>'type',
|
|
x->>'typeoid',
|
|
realtime.cast(
|
|
(x->'value') #>> '{}',
|
|
coalesce(
|
|
(x->>'typeoid')::regtype, -- null when wal2json version <= 2.4
|
|
(x->>'type')::regtype
|
|
)
|
|
),
|
|
(pks ->> 'name') is not null,
|
|
true
|
|
)::realtime.wal_column
|
|
)
|
|
from
|
|
jsonb_array_elements(wal -> 'columns') x
|
|
left join jsonb_array_elements(wal -> 'pk') pks
|
|
on (x ->> 'name') = (pks ->> 'name');
|
|
|
|
old_columns =
|
|
array_agg(
|
|
(
|
|
x->>'name',
|
|
x->>'type',
|
|
x->>'typeoid',
|
|
realtime.cast(
|
|
(x->'value') #>> '{}',
|
|
coalesce(
|
|
(x->>'typeoid')::regtype, -- null when wal2json version <= 2.4
|
|
(x->>'type')::regtype
|
|
)
|
|
),
|
|
(pks ->> 'name') is not null,
|
|
true
|
|
)::realtime.wal_column
|
|
)
|
|
from
|
|
jsonb_array_elements(wal -> 'identity') x
|
|
left join jsonb_array_elements(wal -> 'pk') pks
|
|
on (x ->> 'name') = (pks ->> 'name');
|
|
|
|
for working_role in select * from unnest(roles) loop
|
|
|
|
-- Update `is_selectable` for columns and old_columns
|
|
columns =
|
|
array_agg(
|
|
(
|
|
c.name,
|
|
c.type_name,
|
|
c.type_oid,
|
|
c.value,
|
|
c.is_pkey,
|
|
pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')
|
|
)::realtime.wal_column
|
|
)
|
|
from
|
|
unnest(columns) c;
|
|
|
|
old_columns =
|
|
array_agg(
|
|
(
|
|
c.name,
|
|
c.type_name,
|
|
c.type_oid,
|
|
c.value,
|
|
c.is_pkey,
|
|
pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')
|
|
)::realtime.wal_column
|
|
)
|
|
from
|
|
unnest(old_columns) c;
|
|
|
|
if action <> 'DELETE' and count(1) = 0 from unnest(columns) c where c.is_pkey then
|
|
return next (
|
|
jsonb_build_object(
|
|
'schema', wal ->> 'schema',
|
|
'table', wal ->> 'table',
|
|
'type', action
|
|
),
|
|
is_rls_enabled,
|
|
-- subscriptions is already filtered by entity
|
|
(select array_agg(s.subscription_id) from unnest(subscriptions) as s where claims_role = working_role),
|
|
array['Error 400: Bad Request, no primary key']
|
|
)::realtime.wal_rls;
|
|
|
|
-- The claims role does not have SELECT permission to the primary key of entity
|
|
elsif action <> 'DELETE' and sum(c.is_selectable::int) <> count(1) from unnest(columns) c where c.is_pkey then
|
|
return next (
|
|
jsonb_build_object(
|
|
'schema', wal ->> 'schema',
|
|
'table', wal ->> 'table',
|
|
'type', action
|
|
),
|
|
is_rls_enabled,
|
|
(select array_agg(s.subscription_id) from unnest(subscriptions) as s where claims_role = working_role),
|
|
array['Error 401: Unauthorized']
|
|
)::realtime.wal_rls;
|
|
|
|
else
|
|
output = jsonb_build_object(
|
|
'schema', wal ->> 'schema',
|
|
'table', wal ->> 'table',
|
|
'type', action,
|
|
'commit_timestamp', to_char(
|
|
((wal ->> 'timestamp')::timestamptz at time zone 'utc'),
|
|
'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'
|
|
),
|
|
'columns', (
|
|
select
|
|
jsonb_agg(
|
|
jsonb_build_object(
|
|
'name', pa.attname,
|
|
'type', pt.typname
|
|
)
|
|
order by pa.attnum asc
|
|
)
|
|
from
|
|
pg_attribute pa
|
|
join pg_type pt
|
|
on pa.atttypid = pt.oid
|
|
where
|
|
attrelid = entity_
|
|
and attnum > 0
|
|
and pg_catalog.has_column_privilege(working_role, entity_, pa.attname, 'SELECT')
|
|
)
|
|
)
|
|
-- Add "record" key for insert and update
|
|
|| case
|
|
when action in ('INSERT', 'UPDATE') then
|
|
jsonb_build_object(
|
|
'record',
|
|
(
|
|
select
|
|
jsonb_object_agg(
|
|
-- if unchanged toast, get column name and value from old record
|
|
coalesce((c).name, (oc).name),
|
|
case
|
|
when (c).name is null then (oc).value
|
|
else (c).value
|
|
end
|
|
)
|
|
from
|
|
unnest(columns) c
|
|
full outer join unnest(old_columns) oc
|
|
on (c).name = (oc).name
|
|
where
|
|
coalesce((c).is_selectable, (oc).is_selectable)
|
|
and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
|
|
)
|
|
)
|
|
else '{}'::jsonb
|
|
end
|
|
-- Add "old_record" key for update and delete
|
|
|| case
|
|
when action = 'UPDATE' then
|
|
jsonb_build_object(
|
|
'old_record',
|
|
(
|
|
select jsonb_object_agg((c).name, (c).value)
|
|
from unnest(old_columns) c
|
|
where
|
|
(c).is_selectable
|
|
and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
|
|
)
|
|
)
|
|
when action = 'DELETE' then
|
|
jsonb_build_object(
|
|
'old_record',
|
|
(
|
|
select jsonb_object_agg((c).name, (c).value)
|
|
from unnest(old_columns) c
|
|
where
|
|
(c).is_selectable
|
|
and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
|
|
and ( not is_rls_enabled or (c).is_pkey ) -- if RLS enabled, we can't secure deletes so filter to pkey
|
|
)
|
|
)
|
|
else '{}'::jsonb
|
|
end;
|
|
|
|
-- Create the prepared statement
|
|
if is_rls_enabled and action <> 'DELETE' then
|
|
if (select 1 from pg_prepared_statements where name = 'walrus_rls_stmt' limit 1) > 0 then
|
|
deallocate walrus_rls_stmt;
|
|
end if;
|
|
execute realtime.build_prepared_statement_sql('walrus_rls_stmt', entity_, columns);
|
|
end if;
|
|
|
|
visible_to_subscription_ids = '{}';
|
|
|
|
for subscription_id, claims in (
|
|
select
|
|
subs.subscription_id,
|
|
subs.claims
|
|
from
|
|
unnest(subscriptions) subs
|
|
where
|
|
subs.entity = entity_
|
|
and subs.claims_role = working_role
|
|
and (
|
|
realtime.is_visible_through_filters(columns, subs.filters)
|
|
or (
|
|
action = 'DELETE'
|
|
and realtime.is_visible_through_filters(old_columns, subs.filters)
|
|
)
|
|
)
|
|
) loop
|
|
|
|
if not is_rls_enabled or action = 'DELETE' then
|
|
visible_to_subscription_ids = visible_to_subscription_ids || subscription_id;
|
|
else
|
|
-- Check if RLS allows the role to see the record
|
|
perform
|
|
-- Trim leading and trailing quotes from working_role because set_config
|
|
-- doesn't recognize the role as valid if they are included
|
|
set_config('role', trim(both '"' from working_role::text), true),
|
|
set_config('request.jwt.claims', claims::text, true);
|
|
|
|
execute 'execute walrus_rls_stmt' into subscription_has_access;
|
|
|
|
if subscription_has_access then
|
|
visible_to_subscription_ids = visible_to_subscription_ids || subscription_id;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
perform set_config('role', null, true);
|
|
|
|
return next (
|
|
output,
|
|
is_rls_enabled,
|
|
visible_to_subscription_ids,
|
|
case
|
|
when error_record_exceeds_max_size then array['Error 413: Payload Too Large']
|
|
else '{}'
|
|
end
|
|
)::realtime.wal_rls;
|
|
|
|
end if;
|
|
end loop;
|
|
|
|
perform set_config('role', null, true);
|
|
end;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: broadcast_changes(text, text, text, text, text, record, record, text); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text DEFAULT 'ROW'::text) RETURNS void
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
-- Declare a variable to hold the JSONB representation of the row
|
|
row_data jsonb := '{}'::jsonb;
|
|
BEGIN
|
|
IF level = 'STATEMENT' THEN
|
|
RAISE EXCEPTION 'function can only be triggered for each row, not for each statement';
|
|
END IF;
|
|
-- Check the operation type and handle accordingly
|
|
IF operation = 'INSERT' OR operation = 'UPDATE' OR operation = 'DELETE' THEN
|
|
row_data := jsonb_build_object('old_record', OLD, 'record', NEW, 'operation', operation, 'table', table_name, 'schema', table_schema);
|
|
PERFORM realtime.send (row_data, event_name, topic_name);
|
|
ELSE
|
|
RAISE EXCEPTION 'Unexpected operation type: %', operation;
|
|
END IF;
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
RAISE EXCEPTION 'Failed to process the row: %', SQLERRM;
|
|
END;
|
|
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: build_prepared_statement_sql(text, regclass, realtime.wal_column[]); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) RETURNS text
|
|
LANGUAGE sql
|
|
AS $$
|
|
/*
|
|
Builds a sql string that, if executed, creates a prepared statement to
|
|
tests retrive a row from *entity* by its primary key columns.
|
|
Example
|
|
select realtime.build_prepared_statement_sql('public.notes', '{"id"}'::text[], '{"bigint"}'::text[])
|
|
*/
|
|
select
|
|
'prepare ' || prepared_statement_name || ' as
|
|
select
|
|
exists(
|
|
select
|
|
1
|
|
from
|
|
' || entity || '
|
|
where
|
|
' || string_agg(quote_ident(pkc.name) || '=' || quote_nullable(pkc.value #>> '{}') , ' and ') || '
|
|
)'
|
|
from
|
|
unnest(columns) pkc
|
|
where
|
|
pkc.is_pkey
|
|
group by
|
|
entity
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: cast(text, regtype); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime."cast"(val text, type_ regtype) RETURNS jsonb
|
|
LANGUAGE plpgsql IMMUTABLE
|
|
AS $$
|
|
declare
|
|
res jsonb;
|
|
begin
|
|
execute format('select to_jsonb(%L::'|| type_::text || ')', val) into res;
|
|
return res;
|
|
end
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: check_equality_op(realtime.equality_op, regtype, text, text); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) RETURNS boolean
|
|
LANGUAGE plpgsql IMMUTABLE
|
|
AS $$
|
|
/*
|
|
Casts *val_1* and *val_2* as type *type_* and check the *op* condition for truthiness
|
|
*/
|
|
declare
|
|
op_symbol text = (
|
|
case
|
|
when op = 'eq' then '='
|
|
when op = 'neq' then '!='
|
|
when op = 'lt' then '<'
|
|
when op = 'lte' then '<='
|
|
when op = 'gt' then '>'
|
|
when op = 'gte' then '>='
|
|
when op = 'in' then '= any'
|
|
else 'UNKNOWN OP'
|
|
end
|
|
);
|
|
res boolean;
|
|
begin
|
|
execute format(
|
|
'select %L::'|| type_::text || ' ' || op_symbol
|
|
|| ' ( %L::'
|
|
|| (
|
|
case
|
|
when op = 'in' then type_::text || '[]'
|
|
else type_::text end
|
|
)
|
|
|| ')', val_1, val_2) into res;
|
|
return res;
|
|
end;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: is_visible_through_filters(realtime.wal_column[], realtime.user_defined_filter[]); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) RETURNS boolean
|
|
LANGUAGE sql IMMUTABLE
|
|
AS $_$
|
|
/*
|
|
Should the record be visible (true) or filtered out (false) after *filters* are applied
|
|
*/
|
|
select
|
|
-- Default to allowed when no filters present
|
|
$2 is null -- no filters. this should not happen because subscriptions has a default
|
|
or array_length($2, 1) is null -- array length of an empty array is null
|
|
or bool_and(
|
|
coalesce(
|
|
realtime.check_equality_op(
|
|
op:=f.op,
|
|
type_:=coalesce(
|
|
col.type_oid::regtype, -- null when wal2json version <= 2.4
|
|
col.type_name::regtype
|
|
),
|
|
-- cast jsonb to text
|
|
val_1:=col.value #>> '{}',
|
|
val_2:=f.value
|
|
),
|
|
false -- if null, filter does not match
|
|
)
|
|
)
|
|
from
|
|
unnest(filters) f
|
|
join unnest(columns) col
|
|
on f.column_name = col.name;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: list_changes(name, name, integer, integer); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) RETURNS SETOF realtime.wal_rls
|
|
LANGUAGE sql
|
|
SET log_min_messages TO 'fatal'
|
|
AS $$
|
|
with pub as (
|
|
select
|
|
concat_ws(
|
|
',',
|
|
case when bool_or(pubinsert) then 'insert' else null end,
|
|
case when bool_or(pubupdate) then 'update' else null end,
|
|
case when bool_or(pubdelete) then 'delete' else null end
|
|
) as w2j_actions,
|
|
coalesce(
|
|
string_agg(
|
|
realtime.quote_wal2json(format('%I.%I', schemaname, tablename)::regclass),
|
|
','
|
|
) filter (where ppt.tablename is not null and ppt.tablename not like '% %'),
|
|
''
|
|
) w2j_add_tables
|
|
from
|
|
pg_publication pp
|
|
left join pg_publication_tables ppt
|
|
on pp.pubname = ppt.pubname
|
|
where
|
|
pp.pubname = publication
|
|
group by
|
|
pp.pubname
|
|
limit 1
|
|
),
|
|
w2j as (
|
|
select
|
|
x.*, pub.w2j_add_tables
|
|
from
|
|
pub,
|
|
pg_logical_slot_get_changes(
|
|
slot_name, null, max_changes,
|
|
'include-pk', 'true',
|
|
'include-transaction', 'false',
|
|
'include-timestamp', 'true',
|
|
'include-type-oids', 'true',
|
|
'format-version', '2',
|
|
'actions', pub.w2j_actions,
|
|
'add-tables', pub.w2j_add_tables
|
|
) x
|
|
)
|
|
select
|
|
xyz.wal,
|
|
xyz.is_rls_enabled,
|
|
xyz.subscription_ids,
|
|
xyz.errors
|
|
from
|
|
w2j,
|
|
realtime.apply_rls(
|
|
wal := w2j.data::jsonb,
|
|
max_record_bytes := max_record_bytes
|
|
) xyz(wal, is_rls_enabled, subscription_ids, errors)
|
|
where
|
|
w2j.w2j_add_tables <> ''
|
|
and xyz.subscription_ids[1] is not null
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: quote_wal2json(regclass); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.quote_wal2json(entity regclass) RETURNS text
|
|
LANGUAGE sql IMMUTABLE STRICT
|
|
AS $$
|
|
select
|
|
(
|
|
select string_agg('' || ch,'')
|
|
from unnest(string_to_array(nsp.nspname::text, null)) with ordinality x(ch, idx)
|
|
where
|
|
not (x.idx = 1 and x.ch = '"')
|
|
and not (
|
|
x.idx = array_length(string_to_array(nsp.nspname::text, null), 1)
|
|
and x.ch = '"'
|
|
)
|
|
)
|
|
|| '.'
|
|
|| (
|
|
select string_agg('' || ch,'')
|
|
from unnest(string_to_array(pc.relname::text, null)) with ordinality x(ch, idx)
|
|
where
|
|
not (x.idx = 1 and x.ch = '"')
|
|
and not (
|
|
x.idx = array_length(string_to_array(nsp.nspname::text, null), 1)
|
|
and x.ch = '"'
|
|
)
|
|
)
|
|
from
|
|
pg_class pc
|
|
join pg_namespace nsp
|
|
on pc.relnamespace = nsp.oid
|
|
where
|
|
pc.oid = entity
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: send(jsonb, text, text, boolean); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.send(payload jsonb, event text, topic text, private boolean DEFAULT true) RETURNS void
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
generated_id uuid;
|
|
final_payload jsonb;
|
|
BEGIN
|
|
BEGIN
|
|
-- Generate a new UUID for the id
|
|
generated_id := gen_random_uuid();
|
|
|
|
-- Check if payload has an 'id' key, if not, add the generated UUID
|
|
IF payload ? 'id' THEN
|
|
final_payload := payload;
|
|
ELSE
|
|
final_payload := jsonb_set(payload, '{id}', to_jsonb(generated_id));
|
|
END IF;
|
|
|
|
-- Set the topic configuration
|
|
EXECUTE format('SET LOCAL realtime.topic TO %L', topic);
|
|
|
|
-- Attempt to insert the message
|
|
INSERT INTO realtime.messages (id, payload, event, topic, private, extension)
|
|
VALUES (generated_id, final_payload, event, topic, private, 'broadcast');
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
-- Capture and notify the error
|
|
RAISE WARNING 'ErrorSendingBroadcastMessage: %', SQLERRM;
|
|
END;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: subscription_check_filters(); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.subscription_check_filters() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
/*
|
|
Validates that the user defined filters for a subscription:
|
|
- refer to valid columns that the claimed role may access
|
|
- values are coercable to the correct column type
|
|
*/
|
|
declare
|
|
col_names text[] = coalesce(
|
|
array_agg(c.column_name order by c.ordinal_position),
|
|
'{}'::text[]
|
|
)
|
|
from
|
|
information_schema.columns c
|
|
where
|
|
format('%I.%I', c.table_schema, c.table_name)::regclass = new.entity
|
|
and pg_catalog.has_column_privilege(
|
|
(new.claims ->> 'role'),
|
|
format('%I.%I', c.table_schema, c.table_name)::regclass,
|
|
c.column_name,
|
|
'SELECT'
|
|
);
|
|
filter realtime.user_defined_filter;
|
|
col_type regtype;
|
|
|
|
in_val jsonb;
|
|
begin
|
|
for filter in select * from unnest(new.filters) loop
|
|
-- Filtered column is valid
|
|
if not filter.column_name = any(col_names) then
|
|
raise exception 'invalid column for filter %', filter.column_name;
|
|
end if;
|
|
|
|
-- Type is sanitized and safe for string interpolation
|
|
col_type = (
|
|
select atttypid::regtype
|
|
from pg_catalog.pg_attribute
|
|
where attrelid = new.entity
|
|
and attname = filter.column_name
|
|
);
|
|
if col_type is null then
|
|
raise exception 'failed to lookup type for column %', filter.column_name;
|
|
end if;
|
|
|
|
-- Set maximum number of entries for in filter
|
|
if filter.op = 'in'::realtime.equality_op then
|
|
in_val = realtime.cast(filter.value, (col_type::text || '[]')::regtype);
|
|
if coalesce(jsonb_array_length(in_val), 0) > 100 then
|
|
raise exception 'too many values for `in` filter. Maximum 100';
|
|
end if;
|
|
else
|
|
-- raises an exception if value is not coercable to type
|
|
perform realtime.cast(filter.value, col_type);
|
|
end if;
|
|
|
|
end loop;
|
|
|
|
-- Apply consistent order to filters so the unique constraint on
|
|
-- (subscription_id, entity, filters) can't be tricked by a different filter order
|
|
new.filters = coalesce(
|
|
array_agg(f order by f.column_name, f.op, f.value),
|
|
'{}'
|
|
) from unnest(new.filters) f;
|
|
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: to_regrole(text); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.to_regrole(role_name text) RETURNS regrole
|
|
LANGUAGE sql IMMUTABLE
|
|
AS $$ select role_name::regrole $$;
|
|
|
|
|
|
--
|
|
-- Name: topic(); Type: FUNCTION; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION realtime.topic() RETURNS text
|
|
LANGUAGE sql STABLE
|
|
AS $$
|
|
select nullif(current_setting('realtime.topic', true), '')::text;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: can_insert_object(text, text, uuid, jsonb); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.can_insert_object(bucketid text, name text, owner uuid, metadata jsonb) RETURNS void
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
INSERT INTO "storage"."objects" ("bucket_id", "name", "owner", "metadata") VALUES (bucketid, name, owner, metadata);
|
|
-- hack to rollback the successful insert
|
|
RAISE sqlstate 'PT200' using
|
|
message = 'ROLLBACK',
|
|
detail = 'rollback successful insert';
|
|
END
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: enforce_bucket_name_length(); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.enforce_bucket_name_length() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
begin
|
|
if length(new.name) > 100 then
|
|
raise exception 'bucket name "%" is too long (% characters). Max is 100.', new.name, length(new.name);
|
|
end if;
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: extension(text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.extension(name text) RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
_parts text[];
|
|
_filename text;
|
|
BEGIN
|
|
select string_to_array(name, '/') into _parts;
|
|
select _parts[array_length(_parts,1)] into _filename;
|
|
-- @todo return the last part instead of 2
|
|
return reverse(split_part(reverse(_filename), '.', 1));
|
|
END
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: filename(text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.filename(name text) RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
_parts text[];
|
|
BEGIN
|
|
select string_to_array(name, '/') into _parts;
|
|
return _parts[array_length(_parts,1)];
|
|
END
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: foldername(text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.foldername(name text) RETURNS text[]
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
_parts text[];
|
|
BEGIN
|
|
select string_to_array(name, '/') into _parts;
|
|
return _parts[1:array_length(_parts,1)-1];
|
|
END
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: get_common_prefix(text, text, text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.get_common_prefix(p_key text, p_prefix text, p_delimiter text) RETURNS text
|
|
LANGUAGE sql IMMUTABLE
|
|
AS $$
|
|
SELECT CASE
|
|
WHEN position(p_delimiter IN substring(p_key FROM length(p_prefix) + 1)) > 0
|
|
THEN left(p_key, length(p_prefix) + position(p_delimiter IN substring(p_key FROM length(p_prefix) + 1)))
|
|
ELSE NULL
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: get_size_by_bucket(); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.get_size_by_bucket() RETURNS TABLE(size bigint, bucket_id text)
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
return query
|
|
select sum((metadata->>'size')::int) as size, obj.bucket_id
|
|
from "storage".objects as obj
|
|
group by obj.bucket_id;
|
|
END
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: list_multipart_uploads_with_delimiter(text, text, text, integer, text, text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.list_multipart_uploads_with_delimiter(bucket_id text, prefix_param text, delimiter_param text, max_keys integer DEFAULT 100, next_key_token text DEFAULT ''::text, next_upload_token text DEFAULT ''::text) RETURNS TABLE(key text, id text, created_at timestamp with time zone)
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
BEGIN
|
|
RETURN QUERY EXECUTE
|
|
'SELECT DISTINCT ON(key COLLATE "C") * from (
|
|
SELECT
|
|
CASE
|
|
WHEN position($2 IN substring(key from length($1) + 1)) > 0 THEN
|
|
substring(key from 1 for length($1) + position($2 IN substring(key from length($1) + 1)))
|
|
ELSE
|
|
key
|
|
END AS key, id, created_at
|
|
FROM
|
|
storage.s3_multipart_uploads
|
|
WHERE
|
|
bucket_id = $5 AND
|
|
key ILIKE $1 || ''%'' AND
|
|
CASE
|
|
WHEN $4 != '''' AND $6 = '''' THEN
|
|
CASE
|
|
WHEN position($2 IN substring(key from length($1) + 1)) > 0 THEN
|
|
substring(key from 1 for length($1) + position($2 IN substring(key from length($1) + 1))) COLLATE "C" > $4
|
|
ELSE
|
|
key COLLATE "C" > $4
|
|
END
|
|
ELSE
|
|
true
|
|
END AND
|
|
CASE
|
|
WHEN $6 != '''' THEN
|
|
id COLLATE "C" > $6
|
|
ELSE
|
|
true
|
|
END
|
|
ORDER BY
|
|
key COLLATE "C" ASC, created_at ASC) as e order by key COLLATE "C" LIMIT $3'
|
|
USING prefix_param, delimiter_param, max_keys, next_key_token, bucket_id, next_upload_token;
|
|
END;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: list_objects_with_delimiter(text, text, text, integer, text, text, text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.list_objects_with_delimiter(_bucket_id text, prefix_param text, delimiter_param text, max_keys integer DEFAULT 100, start_after text DEFAULT ''::text, next_token text DEFAULT ''::text, sort_order text DEFAULT 'asc'::text) RETURNS TABLE(name text, id uuid, metadata jsonb, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone)
|
|
LANGUAGE plpgsql STABLE
|
|
AS $_$
|
|
DECLARE
|
|
v_peek_name TEXT;
|
|
v_current RECORD;
|
|
v_common_prefix TEXT;
|
|
|
|
-- Configuration
|
|
v_is_asc BOOLEAN;
|
|
v_prefix TEXT;
|
|
v_start TEXT;
|
|
v_upper_bound TEXT;
|
|
v_file_batch_size INT;
|
|
|
|
-- Seek state
|
|
v_next_seek TEXT;
|
|
v_count INT := 0;
|
|
|
|
-- Dynamic SQL for batch query only
|
|
v_batch_query TEXT;
|
|
|
|
BEGIN
|
|
-- ========================================================================
|
|
-- INITIALIZATION
|
|
-- ========================================================================
|
|
v_is_asc := lower(coalesce(sort_order, 'asc')) = 'asc';
|
|
v_prefix := coalesce(prefix_param, '');
|
|
v_start := CASE WHEN coalesce(next_token, '') <> '' THEN next_token ELSE coalesce(start_after, '') END;
|
|
v_file_batch_size := LEAST(GREATEST(max_keys * 2, 100), 1000);
|
|
|
|
-- Calculate upper bound for prefix filtering (bytewise, using COLLATE "C")
|
|
IF v_prefix = '' THEN
|
|
v_upper_bound := NULL;
|
|
ELSIF right(v_prefix, 1) = delimiter_param THEN
|
|
v_upper_bound := left(v_prefix, -1) || chr(ascii(delimiter_param) + 1);
|
|
ELSE
|
|
v_upper_bound := left(v_prefix, -1) || chr(ascii(right(v_prefix, 1)) + 1);
|
|
END IF;
|
|
|
|
-- Build batch query (dynamic SQL - called infrequently, amortized over many rows)
|
|
IF v_is_asc THEN
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
|
|
'FROM storage.objects o WHERE o.bucket_id = $1 AND o.name COLLATE "C" >= $2 ' ||
|
|
'AND o.name COLLATE "C" < $3 ORDER BY o.name COLLATE "C" ASC LIMIT $4';
|
|
ELSE
|
|
v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
|
|
'FROM storage.objects o WHERE o.bucket_id = $1 AND o.name COLLATE "C" >= $2 ' ||
|
|
'ORDER BY o.name COLLATE "C" ASC LIMIT $4';
|
|
END IF;
|
|
ELSE
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
|
|
'FROM storage.objects o WHERE o.bucket_id = $1 AND o.name COLLATE "C" < $2 ' ||
|
|
'AND o.name COLLATE "C" >= $3 ORDER BY o.name COLLATE "C" DESC LIMIT $4';
|
|
ELSE
|
|
v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
|
|
'FROM storage.objects o WHERE o.bucket_id = $1 AND o.name COLLATE "C" < $2 ' ||
|
|
'ORDER BY o.name COLLATE "C" DESC LIMIT $4';
|
|
END IF;
|
|
END IF;
|
|
|
|
-- ========================================================================
|
|
-- SEEK INITIALIZATION: Determine starting position
|
|
-- ========================================================================
|
|
IF v_start = '' THEN
|
|
IF v_is_asc THEN
|
|
v_next_seek := v_prefix;
|
|
ELSE
|
|
-- DESC without cursor: find the last item in range
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
SELECT o.name INTO v_next_seek FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" >= v_prefix AND o.name COLLATE "C" < v_upper_bound
|
|
ORDER BY o.name COLLATE "C" DESC LIMIT 1;
|
|
ELSIF v_prefix <> '' THEN
|
|
SELECT o.name INTO v_next_seek FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" >= v_prefix
|
|
ORDER BY o.name COLLATE "C" DESC LIMIT 1;
|
|
ELSE
|
|
SELECT o.name INTO v_next_seek FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id
|
|
ORDER BY o.name COLLATE "C" DESC LIMIT 1;
|
|
END IF;
|
|
|
|
IF v_next_seek IS NOT NULL THEN
|
|
v_next_seek := v_next_seek || delimiter_param;
|
|
ELSE
|
|
RETURN;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
-- Cursor provided: determine if it refers to a folder or leaf
|
|
IF EXISTS (
|
|
SELECT 1 FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id
|
|
AND o.name COLLATE "C" LIKE v_start || delimiter_param || '%'
|
|
LIMIT 1
|
|
) THEN
|
|
-- Cursor refers to a folder
|
|
IF v_is_asc THEN
|
|
v_next_seek := v_start || chr(ascii(delimiter_param) + 1);
|
|
ELSE
|
|
v_next_seek := v_start || delimiter_param;
|
|
END IF;
|
|
ELSE
|
|
-- Cursor refers to a leaf object
|
|
IF v_is_asc THEN
|
|
v_next_seek := v_start || delimiter_param;
|
|
ELSE
|
|
v_next_seek := v_start;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
-- ========================================================================
|
|
-- MAIN LOOP: Hybrid peek-then-batch algorithm
|
|
-- Uses STATIC SQL for peek (hot path) and DYNAMIC SQL for batch
|
|
-- ========================================================================
|
|
LOOP
|
|
EXIT WHEN v_count >= max_keys;
|
|
|
|
-- STEP 1: PEEK using STATIC SQL (plan cached, very fast)
|
|
IF v_is_asc THEN
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" >= v_next_seek AND o.name COLLATE "C" < v_upper_bound
|
|
ORDER BY o.name COLLATE "C" ASC LIMIT 1;
|
|
ELSE
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" >= v_next_seek
|
|
ORDER BY o.name COLLATE "C" ASC LIMIT 1;
|
|
END IF;
|
|
ELSE
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" < v_next_seek AND o.name COLLATE "C" >= v_prefix
|
|
ORDER BY o.name COLLATE "C" DESC LIMIT 1;
|
|
ELSIF v_prefix <> '' THEN
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" < v_next_seek AND o.name COLLATE "C" >= v_prefix
|
|
ORDER BY o.name COLLATE "C" DESC LIMIT 1;
|
|
ELSE
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" < v_next_seek
|
|
ORDER BY o.name COLLATE "C" DESC LIMIT 1;
|
|
END IF;
|
|
END IF;
|
|
|
|
EXIT WHEN v_peek_name IS NULL;
|
|
|
|
-- STEP 2: Check if this is a FOLDER or FILE
|
|
v_common_prefix := storage.get_common_prefix(v_peek_name, v_prefix, delimiter_param);
|
|
|
|
IF v_common_prefix IS NOT NULL THEN
|
|
-- FOLDER: Emit and skip to next folder (no heap access needed)
|
|
name := rtrim(v_common_prefix, delimiter_param);
|
|
id := NULL;
|
|
updated_at := NULL;
|
|
created_at := NULL;
|
|
last_accessed_at := NULL;
|
|
metadata := NULL;
|
|
RETURN NEXT;
|
|
v_count := v_count + 1;
|
|
|
|
-- Advance seek past the folder range
|
|
IF v_is_asc THEN
|
|
v_next_seek := left(v_common_prefix, -1) || chr(ascii(delimiter_param) + 1);
|
|
ELSE
|
|
v_next_seek := v_common_prefix;
|
|
END IF;
|
|
ELSE
|
|
-- FILE: Batch fetch using DYNAMIC SQL (overhead amortized over many rows)
|
|
-- For ASC: upper_bound is the exclusive upper limit (< condition)
|
|
-- For DESC: prefix is the inclusive lower limit (>= condition)
|
|
FOR v_current IN EXECUTE v_batch_query USING _bucket_id, v_next_seek,
|
|
CASE WHEN v_is_asc THEN COALESCE(v_upper_bound, v_prefix) ELSE v_prefix END, v_file_batch_size
|
|
LOOP
|
|
v_common_prefix := storage.get_common_prefix(v_current.name, v_prefix, delimiter_param);
|
|
|
|
IF v_common_prefix IS NOT NULL THEN
|
|
-- Hit a folder: exit batch, let peek handle it
|
|
v_next_seek := v_current.name;
|
|
EXIT;
|
|
END IF;
|
|
|
|
-- Emit file
|
|
name := v_current.name;
|
|
id := v_current.id;
|
|
updated_at := v_current.updated_at;
|
|
created_at := v_current.created_at;
|
|
last_accessed_at := v_current.last_accessed_at;
|
|
metadata := v_current.metadata;
|
|
RETURN NEXT;
|
|
v_count := v_count + 1;
|
|
|
|
-- Advance seek past this file
|
|
IF v_is_asc THEN
|
|
v_next_seek := v_current.name || delimiter_param;
|
|
ELSE
|
|
v_next_seek := v_current.name;
|
|
END IF;
|
|
|
|
EXIT WHEN v_count >= max_keys;
|
|
END LOOP;
|
|
END IF;
|
|
END LOOP;
|
|
END;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: operation(); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.operation() RETURNS text
|
|
LANGUAGE plpgsql STABLE
|
|
AS $$
|
|
BEGIN
|
|
RETURN current_setting('storage.operation', true);
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: protect_delete(); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.protect_delete() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
-- Check if storage.allow_delete_query is set to 'true'
|
|
IF COALESCE(current_setting('storage.allow_delete_query', true), 'false') != 'true' THEN
|
|
RAISE EXCEPTION 'Direct deletion from storage tables is not allowed. Use the Storage API instead.'
|
|
USING HINT = 'This prevents accidental data loss from orphaned objects.',
|
|
ERRCODE = '42501';
|
|
END IF;
|
|
RETURN NULL;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: search(text, text, integer, integer, integer, text, text, text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.search(prefix text, bucketname text, limits integer DEFAULT 100, levels integer DEFAULT 1, offsets integer DEFAULT 0, search text DEFAULT ''::text, sortcolumn text DEFAULT 'name'::text, sortorder text DEFAULT 'asc'::text) RETURNS TABLE(name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb)
|
|
LANGUAGE plpgsql STABLE
|
|
AS $_$
|
|
DECLARE
|
|
v_peek_name TEXT;
|
|
v_current RECORD;
|
|
v_common_prefix TEXT;
|
|
v_delimiter CONSTANT TEXT := '/';
|
|
|
|
-- Configuration
|
|
v_limit INT;
|
|
v_prefix TEXT;
|
|
v_prefix_lower TEXT;
|
|
v_is_asc BOOLEAN;
|
|
v_order_by TEXT;
|
|
v_sort_order TEXT;
|
|
v_upper_bound TEXT;
|
|
v_file_batch_size INT;
|
|
|
|
-- Dynamic SQL for batch query only
|
|
v_batch_query TEXT;
|
|
|
|
-- Seek state
|
|
v_next_seek TEXT;
|
|
v_count INT := 0;
|
|
v_skipped INT := 0;
|
|
BEGIN
|
|
-- ========================================================================
|
|
-- INITIALIZATION
|
|
-- ========================================================================
|
|
v_limit := LEAST(coalesce(limits, 100), 1500);
|
|
v_prefix := coalesce(prefix, '') || coalesce(search, '');
|
|
v_prefix_lower := lower(v_prefix);
|
|
v_is_asc := lower(coalesce(sortorder, 'asc')) = 'asc';
|
|
v_file_batch_size := LEAST(GREATEST(v_limit * 2, 100), 1000);
|
|
|
|
-- Validate sort column
|
|
CASE lower(coalesce(sortcolumn, 'name'))
|
|
WHEN 'name' THEN v_order_by := 'name';
|
|
WHEN 'updated_at' THEN v_order_by := 'updated_at';
|
|
WHEN 'created_at' THEN v_order_by := 'created_at';
|
|
WHEN 'last_accessed_at' THEN v_order_by := 'last_accessed_at';
|
|
ELSE v_order_by := 'name';
|
|
END CASE;
|
|
|
|
v_sort_order := CASE WHEN v_is_asc THEN 'asc' ELSE 'desc' END;
|
|
|
|
-- ========================================================================
|
|
-- NON-NAME SORTING: Use path_tokens approach (unchanged)
|
|
-- ========================================================================
|
|
IF v_order_by != 'name' THEN
|
|
RETURN QUERY EXECUTE format(
|
|
$sql$
|
|
WITH folders AS (
|
|
SELECT path_tokens[$1] AS folder
|
|
FROM storage.objects
|
|
WHERE objects.name ILIKE $2 || '%%'
|
|
AND bucket_id = $3
|
|
AND array_length(objects.path_tokens, 1) <> $1
|
|
GROUP BY folder
|
|
ORDER BY folder %s
|
|
)
|
|
(SELECT folder AS "name",
|
|
NULL::uuid AS id,
|
|
NULL::timestamptz AS updated_at,
|
|
NULL::timestamptz AS created_at,
|
|
NULL::timestamptz AS last_accessed_at,
|
|
NULL::jsonb AS metadata FROM folders)
|
|
UNION ALL
|
|
(SELECT path_tokens[$1] AS "name",
|
|
id, updated_at, created_at, last_accessed_at, metadata
|
|
FROM storage.objects
|
|
WHERE objects.name ILIKE $2 || '%%'
|
|
AND bucket_id = $3
|
|
AND array_length(objects.path_tokens, 1) = $1
|
|
ORDER BY %I %s)
|
|
LIMIT $4 OFFSET $5
|
|
$sql$, v_sort_order, v_order_by, v_sort_order
|
|
) USING levels, v_prefix, bucketname, v_limit, offsets;
|
|
RETURN;
|
|
END IF;
|
|
|
|
-- ========================================================================
|
|
-- NAME SORTING: Hybrid skip-scan with batch optimization
|
|
-- ========================================================================
|
|
|
|
-- Calculate upper bound for prefix filtering
|
|
IF v_prefix_lower = '' THEN
|
|
v_upper_bound := NULL;
|
|
ELSIF right(v_prefix_lower, 1) = v_delimiter THEN
|
|
v_upper_bound := left(v_prefix_lower, -1) || chr(ascii(v_delimiter) + 1);
|
|
ELSE
|
|
v_upper_bound := left(v_prefix_lower, -1) || chr(ascii(right(v_prefix_lower, 1)) + 1);
|
|
END IF;
|
|
|
|
-- Build batch query (dynamic SQL - called infrequently, amortized over many rows)
|
|
IF v_is_asc THEN
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
|
|
'FROM storage.objects o WHERE o.bucket_id = $1 AND lower(o.name) COLLATE "C" >= $2 ' ||
|
|
'AND lower(o.name) COLLATE "C" < $3 ORDER BY lower(o.name) COLLATE "C" ASC LIMIT $4';
|
|
ELSE
|
|
v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
|
|
'FROM storage.objects o WHERE o.bucket_id = $1 AND lower(o.name) COLLATE "C" >= $2 ' ||
|
|
'ORDER BY lower(o.name) COLLATE "C" ASC LIMIT $4';
|
|
END IF;
|
|
ELSE
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
|
|
'FROM storage.objects o WHERE o.bucket_id = $1 AND lower(o.name) COLLATE "C" < $2 ' ||
|
|
'AND lower(o.name) COLLATE "C" >= $3 ORDER BY lower(o.name) COLLATE "C" DESC LIMIT $4';
|
|
ELSE
|
|
v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
|
|
'FROM storage.objects o WHERE o.bucket_id = $1 AND lower(o.name) COLLATE "C" < $2 ' ||
|
|
'ORDER BY lower(o.name) COLLATE "C" DESC LIMIT $4';
|
|
END IF;
|
|
END IF;
|
|
|
|
-- Initialize seek position
|
|
IF v_is_asc THEN
|
|
v_next_seek := v_prefix_lower;
|
|
ELSE
|
|
-- DESC: find the last item in range first (static SQL)
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" >= v_prefix_lower AND lower(o.name) COLLATE "C" < v_upper_bound
|
|
ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
|
|
ELSIF v_prefix_lower <> '' THEN
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" >= v_prefix_lower
|
|
ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
|
|
ELSE
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = bucketname
|
|
ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
|
|
END IF;
|
|
|
|
IF v_peek_name IS NOT NULL THEN
|
|
v_next_seek := lower(v_peek_name) || v_delimiter;
|
|
ELSE
|
|
RETURN;
|
|
END IF;
|
|
END IF;
|
|
|
|
-- ========================================================================
|
|
-- MAIN LOOP: Hybrid peek-then-batch algorithm
|
|
-- Uses STATIC SQL for peek (hot path) and DYNAMIC SQL for batch
|
|
-- ========================================================================
|
|
LOOP
|
|
EXIT WHEN v_count >= v_limit;
|
|
|
|
-- STEP 1: PEEK using STATIC SQL (plan cached, very fast)
|
|
IF v_is_asc THEN
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" >= v_next_seek AND lower(o.name) COLLATE "C" < v_upper_bound
|
|
ORDER BY lower(o.name) COLLATE "C" ASC LIMIT 1;
|
|
ELSE
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" >= v_next_seek
|
|
ORDER BY lower(o.name) COLLATE "C" ASC LIMIT 1;
|
|
END IF;
|
|
ELSE
|
|
IF v_upper_bound IS NOT NULL THEN
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" < v_next_seek AND lower(o.name) COLLATE "C" >= v_prefix_lower
|
|
ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
|
|
ELSIF v_prefix_lower <> '' THEN
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" < v_next_seek AND lower(o.name) COLLATE "C" >= v_prefix_lower
|
|
ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
|
|
ELSE
|
|
SELECT o.name INTO v_peek_name FROM storage.objects o
|
|
WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" < v_next_seek
|
|
ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
|
|
END IF;
|
|
END IF;
|
|
|
|
EXIT WHEN v_peek_name IS NULL;
|
|
|
|
-- STEP 2: Check if this is a FOLDER or FILE
|
|
v_common_prefix := storage.get_common_prefix(lower(v_peek_name), v_prefix_lower, v_delimiter);
|
|
|
|
IF v_common_prefix IS NOT NULL THEN
|
|
-- FOLDER: Handle offset, emit if needed, skip to next folder
|
|
IF v_skipped < offsets THEN
|
|
v_skipped := v_skipped + 1;
|
|
ELSE
|
|
name := split_part(rtrim(v_common_prefix, v_delimiter), v_delimiter, levels);
|
|
id := NULL;
|
|
updated_at := NULL;
|
|
created_at := NULL;
|
|
last_accessed_at := NULL;
|
|
metadata := NULL;
|
|
RETURN NEXT;
|
|
v_count := v_count + 1;
|
|
END IF;
|
|
|
|
-- Advance seek past the folder range
|
|
IF v_is_asc THEN
|
|
v_next_seek := lower(left(v_common_prefix, -1)) || chr(ascii(v_delimiter) + 1);
|
|
ELSE
|
|
v_next_seek := lower(v_common_prefix);
|
|
END IF;
|
|
ELSE
|
|
-- FILE: Batch fetch using DYNAMIC SQL (overhead amortized over many rows)
|
|
-- For ASC: upper_bound is the exclusive upper limit (< condition)
|
|
-- For DESC: prefix_lower is the inclusive lower limit (>= condition)
|
|
FOR v_current IN EXECUTE v_batch_query
|
|
USING bucketname, v_next_seek,
|
|
CASE WHEN v_is_asc THEN COALESCE(v_upper_bound, v_prefix_lower) ELSE v_prefix_lower END, v_file_batch_size
|
|
LOOP
|
|
v_common_prefix := storage.get_common_prefix(lower(v_current.name), v_prefix_lower, v_delimiter);
|
|
|
|
IF v_common_prefix IS NOT NULL THEN
|
|
-- Hit a folder: exit batch, let peek handle it
|
|
v_next_seek := lower(v_current.name);
|
|
EXIT;
|
|
END IF;
|
|
|
|
-- Handle offset skipping
|
|
IF v_skipped < offsets THEN
|
|
v_skipped := v_skipped + 1;
|
|
ELSE
|
|
-- Emit file
|
|
name := split_part(v_current.name, v_delimiter, levels);
|
|
id := v_current.id;
|
|
updated_at := v_current.updated_at;
|
|
created_at := v_current.created_at;
|
|
last_accessed_at := v_current.last_accessed_at;
|
|
metadata := v_current.metadata;
|
|
RETURN NEXT;
|
|
v_count := v_count + 1;
|
|
END IF;
|
|
|
|
-- Advance seek past this file
|
|
IF v_is_asc THEN
|
|
v_next_seek := lower(v_current.name) || v_delimiter;
|
|
ELSE
|
|
v_next_seek := lower(v_current.name);
|
|
END IF;
|
|
|
|
EXIT WHEN v_count >= v_limit;
|
|
END LOOP;
|
|
END IF;
|
|
END LOOP;
|
|
END;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: search_by_timestamp(text, text, integer, integer, text, text, text, text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.search_by_timestamp(p_prefix text, p_bucket_id text, p_limit integer, p_level integer, p_start_after text, p_sort_order text, p_sort_column text, p_sort_column_after text) RETURNS TABLE(key text, name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb)
|
|
LANGUAGE plpgsql STABLE
|
|
AS $_$
|
|
DECLARE
|
|
v_cursor_op text;
|
|
v_query text;
|
|
v_prefix text;
|
|
BEGIN
|
|
v_prefix := coalesce(p_prefix, '');
|
|
|
|
IF p_sort_order = 'asc' THEN
|
|
v_cursor_op := '>';
|
|
ELSE
|
|
v_cursor_op := '<';
|
|
END IF;
|
|
|
|
v_query := format($sql$
|
|
WITH raw_objects AS (
|
|
SELECT
|
|
o.name AS obj_name,
|
|
o.id AS obj_id,
|
|
o.updated_at AS obj_updated_at,
|
|
o.created_at AS obj_created_at,
|
|
o.last_accessed_at AS obj_last_accessed_at,
|
|
o.metadata AS obj_metadata,
|
|
storage.get_common_prefix(o.name, $1, '/') AS common_prefix
|
|
FROM storage.objects o
|
|
WHERE o.bucket_id = $2
|
|
AND o.name COLLATE "C" LIKE $1 || '%%'
|
|
),
|
|
-- Aggregate common prefixes (folders)
|
|
-- Both created_at and updated_at use MIN(obj_created_at) to match the old prefixes table behavior
|
|
aggregated_prefixes AS (
|
|
SELECT
|
|
rtrim(common_prefix, '/') AS name,
|
|
NULL::uuid AS id,
|
|
MIN(obj_created_at) AS updated_at,
|
|
MIN(obj_created_at) AS created_at,
|
|
NULL::timestamptz AS last_accessed_at,
|
|
NULL::jsonb AS metadata,
|
|
TRUE AS is_prefix
|
|
FROM raw_objects
|
|
WHERE common_prefix IS NOT NULL
|
|
GROUP BY common_prefix
|
|
),
|
|
leaf_objects AS (
|
|
SELECT
|
|
obj_name AS name,
|
|
obj_id AS id,
|
|
obj_updated_at AS updated_at,
|
|
obj_created_at AS created_at,
|
|
obj_last_accessed_at AS last_accessed_at,
|
|
obj_metadata AS metadata,
|
|
FALSE AS is_prefix
|
|
FROM raw_objects
|
|
WHERE common_prefix IS NULL
|
|
),
|
|
combined AS (
|
|
SELECT * FROM aggregated_prefixes
|
|
UNION ALL
|
|
SELECT * FROM leaf_objects
|
|
),
|
|
filtered AS (
|
|
SELECT *
|
|
FROM combined
|
|
WHERE (
|
|
$5 = ''
|
|
OR ROW(
|
|
date_trunc('milliseconds', %I),
|
|
name COLLATE "C"
|
|
) %s ROW(
|
|
COALESCE(NULLIF($6, '')::timestamptz, 'epoch'::timestamptz),
|
|
$5
|
|
)
|
|
)
|
|
)
|
|
SELECT
|
|
split_part(name, '/', $3) AS key,
|
|
name,
|
|
id,
|
|
updated_at,
|
|
created_at,
|
|
last_accessed_at,
|
|
metadata
|
|
FROM filtered
|
|
ORDER BY
|
|
COALESCE(date_trunc('milliseconds', %I), 'epoch'::timestamptz) %s,
|
|
name COLLATE "C" %s
|
|
LIMIT $4
|
|
$sql$,
|
|
p_sort_column,
|
|
v_cursor_op,
|
|
p_sort_column,
|
|
p_sort_order,
|
|
p_sort_order
|
|
);
|
|
|
|
RETURN QUERY EXECUTE v_query
|
|
USING v_prefix, p_bucket_id, p_level, p_limit, p_start_after, p_sort_column_after;
|
|
END;
|
|
$_$;
|
|
|
|
|
|
--
|
|
-- Name: search_v2(text, text, integer, integer, text, text, text, text); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.search_v2(prefix text, bucket_name text, limits integer DEFAULT 100, levels integer DEFAULT 1, start_after text DEFAULT ''::text, sort_order text DEFAULT 'asc'::text, sort_column text DEFAULT 'name'::text, sort_column_after text DEFAULT ''::text) RETURNS TABLE(key text, name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb)
|
|
LANGUAGE plpgsql STABLE
|
|
AS $$
|
|
DECLARE
|
|
v_sort_col text;
|
|
v_sort_ord text;
|
|
v_limit int;
|
|
BEGIN
|
|
-- Cap limit to maximum of 1500 records
|
|
v_limit := LEAST(coalesce(limits, 100), 1500);
|
|
|
|
-- Validate and normalize sort_order
|
|
v_sort_ord := lower(coalesce(sort_order, 'asc'));
|
|
IF v_sort_ord NOT IN ('asc', 'desc') THEN
|
|
v_sort_ord := 'asc';
|
|
END IF;
|
|
|
|
-- Validate and normalize sort_column
|
|
v_sort_col := lower(coalesce(sort_column, 'name'));
|
|
IF v_sort_col NOT IN ('name', 'updated_at', 'created_at') THEN
|
|
v_sort_col := 'name';
|
|
END IF;
|
|
|
|
-- Route to appropriate implementation
|
|
IF v_sort_col = 'name' THEN
|
|
-- Use list_objects_with_delimiter for name sorting (most efficient: O(k * log n))
|
|
RETURN QUERY
|
|
SELECT
|
|
split_part(l.name, '/', levels) AS key,
|
|
l.name AS name,
|
|
l.id,
|
|
l.updated_at,
|
|
l.created_at,
|
|
l.last_accessed_at,
|
|
l.metadata
|
|
FROM storage.list_objects_with_delimiter(
|
|
bucket_name,
|
|
coalesce(prefix, ''),
|
|
'/',
|
|
v_limit,
|
|
start_after,
|
|
'',
|
|
v_sort_ord
|
|
) l;
|
|
ELSE
|
|
-- Use aggregation approach for timestamp sorting
|
|
-- Not efficient for large datasets but supports correct pagination
|
|
RETURN QUERY SELECT * FROM storage.search_by_timestamp(
|
|
prefix, bucket_name, v_limit, levels, start_after,
|
|
v_sort_ord, v_sort_col, sort_column_after
|
|
);
|
|
END IF;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: update_updated_at_column(); Type: FUNCTION; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION storage.update_updated_at_column() RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
NEW.updated_at = now();
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: http_request(); Type: FUNCTION; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
CREATE FUNCTION supabase_functions.http_request() RETURNS trigger
|
|
LANGUAGE plpgsql SECURITY DEFINER
|
|
SET search_path TO 'supabase_functions'
|
|
AS $$
|
|
DECLARE
|
|
request_id bigint;
|
|
payload jsonb;
|
|
url text := TG_ARGV[0]::text;
|
|
method text := TG_ARGV[1]::text;
|
|
headers jsonb DEFAULT '{}'::jsonb;
|
|
params jsonb DEFAULT '{}'::jsonb;
|
|
timeout_ms integer DEFAULT 1000;
|
|
BEGIN
|
|
IF url IS NULL OR url = 'null' THEN
|
|
RAISE EXCEPTION 'url argument is missing';
|
|
END IF;
|
|
|
|
IF method IS NULL OR method = 'null' THEN
|
|
RAISE EXCEPTION 'method argument is missing';
|
|
END IF;
|
|
|
|
IF TG_ARGV[2] IS NULL OR TG_ARGV[2] = 'null' THEN
|
|
headers = '{"Content-Type": "application/json"}'::jsonb;
|
|
ELSE
|
|
headers = TG_ARGV[2]::jsonb;
|
|
END IF;
|
|
|
|
IF TG_ARGV[3] IS NULL OR TG_ARGV[3] = 'null' THEN
|
|
params = '{}'::jsonb;
|
|
ELSE
|
|
params = TG_ARGV[3]::jsonb;
|
|
END IF;
|
|
|
|
IF TG_ARGV[4] IS NULL OR TG_ARGV[4] = 'null' THEN
|
|
timeout_ms = 1000;
|
|
ELSE
|
|
timeout_ms = TG_ARGV[4]::integer;
|
|
END IF;
|
|
|
|
CASE
|
|
WHEN method = 'GET' THEN
|
|
SELECT http_get INTO request_id FROM net.http_get(
|
|
url,
|
|
params,
|
|
headers,
|
|
timeout_ms
|
|
);
|
|
WHEN method = 'POST' THEN
|
|
payload = jsonb_build_object(
|
|
'old_record', OLD,
|
|
'record', NEW,
|
|
'type', TG_OP,
|
|
'table', TG_TABLE_NAME,
|
|
'schema', TG_TABLE_SCHEMA
|
|
);
|
|
|
|
SELECT http_post INTO request_id FROM net.http_post(
|
|
url,
|
|
payload,
|
|
params,
|
|
headers,
|
|
timeout_ms
|
|
);
|
|
ELSE
|
|
RAISE EXCEPTION 'method argument % is invalid', method;
|
|
END CASE;
|
|
|
|
INSERT INTO supabase_functions.hooks
|
|
(hook_table_id, hook_name, request_id)
|
|
VALUES
|
|
(TG_RELID, TG_NAME, request_id);
|
|
|
|
RETURN NEW;
|
|
END
|
|
$$;
|
|
|
|
|
|
--
|
|
-- Name: extensions; Type: TABLE; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE _realtime.extensions (
|
|
id uuid NOT NULL,
|
|
type text,
|
|
settings jsonb,
|
|
tenant_external_id text,
|
|
inserted_at timestamp(0) without time zone NOT NULL,
|
|
updated_at timestamp(0) without time zone NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: schema_migrations; Type: TABLE; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE _realtime.schema_migrations (
|
|
version bigint NOT NULL,
|
|
inserted_at timestamp(0) without time zone
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tenants; Type: TABLE; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE _realtime.tenants (
|
|
id uuid NOT NULL,
|
|
name text,
|
|
external_id text,
|
|
jwt_secret text,
|
|
max_concurrent_users integer DEFAULT 200 NOT NULL,
|
|
inserted_at timestamp(0) without time zone NOT NULL,
|
|
updated_at timestamp(0) without time zone NOT NULL,
|
|
max_events_per_second integer DEFAULT 100 NOT NULL,
|
|
postgres_cdc_default text DEFAULT 'postgres_cdc_rls'::text,
|
|
max_bytes_per_second integer DEFAULT 100000 NOT NULL,
|
|
max_channels_per_client integer DEFAULT 100 NOT NULL,
|
|
max_joins_per_second integer DEFAULT 500 NOT NULL,
|
|
suspend boolean DEFAULT false,
|
|
jwt_jwks jsonb,
|
|
notify_private_alpha boolean DEFAULT false,
|
|
private_only boolean DEFAULT false NOT NULL,
|
|
migrations_ran integer DEFAULT 0,
|
|
broadcast_adapter character varying(255) DEFAULT 'gen_rpc'::character varying,
|
|
max_presence_events_per_second integer DEFAULT 1000,
|
|
max_payload_size_in_kb integer DEFAULT 3000,
|
|
CONSTRAINT jwt_secret_or_jwt_jwks_required CHECK (((jwt_secret IS NOT NULL) OR (jwt_jwks IS NOT NULL)))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: audit_log_entries; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.audit_log_entries (
|
|
instance_id uuid,
|
|
id uuid NOT NULL,
|
|
payload json,
|
|
created_at timestamp with time zone,
|
|
ip_address character varying(64) DEFAULT ''::character varying NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE audit_log_entries; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.audit_log_entries IS 'Auth: Audit trail for user actions.';
|
|
|
|
|
|
--
|
|
-- Name: flow_state; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.flow_state (
|
|
id uuid NOT NULL,
|
|
user_id uuid,
|
|
auth_code text,
|
|
code_challenge_method auth.code_challenge_method,
|
|
code_challenge text,
|
|
provider_type text NOT NULL,
|
|
provider_access_token text,
|
|
provider_refresh_token text,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
authentication_method text NOT NULL,
|
|
auth_code_issued_at timestamp with time zone,
|
|
invite_token text,
|
|
referrer text,
|
|
oauth_client_state_id uuid,
|
|
linking_target_id uuid,
|
|
email_optional boolean DEFAULT false NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE flow_state; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.flow_state IS 'Stores metadata for all OAuth/SSO login flows';
|
|
|
|
|
|
--
|
|
-- Name: identities; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.identities (
|
|
provider_id text NOT NULL,
|
|
user_id uuid NOT NULL,
|
|
identity_data jsonb NOT NULL,
|
|
provider text NOT NULL,
|
|
last_sign_in_at timestamp with time zone,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
email text GENERATED ALWAYS AS (lower((identity_data ->> 'email'::text))) STORED,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE identities; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.identities IS 'Auth: Stores identities associated to a user.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN identities.email; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN auth.identities.email IS 'Auth: Email is a generated column that references the optional email property in the identity_data';
|
|
|
|
|
|
--
|
|
-- Name: instances; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.instances (
|
|
id uuid NOT NULL,
|
|
uuid uuid,
|
|
raw_base_config text,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE instances; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.instances IS 'Auth: Manages users across multiple sites.';
|
|
|
|
|
|
--
|
|
-- Name: mfa_amr_claims; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.mfa_amr_claims (
|
|
session_id uuid NOT NULL,
|
|
created_at timestamp with time zone NOT NULL,
|
|
updated_at timestamp with time zone NOT NULL,
|
|
authentication_method text NOT NULL,
|
|
id uuid NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE mfa_amr_claims; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.mfa_amr_claims IS 'auth: stores authenticator method reference claims for multi factor authentication';
|
|
|
|
|
|
--
|
|
-- Name: mfa_challenges; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.mfa_challenges (
|
|
id uuid NOT NULL,
|
|
factor_id uuid NOT NULL,
|
|
created_at timestamp with time zone NOT NULL,
|
|
verified_at timestamp with time zone,
|
|
ip_address inet NOT NULL,
|
|
otp_code text,
|
|
web_authn_session_data jsonb
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE mfa_challenges; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.mfa_challenges IS 'auth: stores metadata about challenge requests made';
|
|
|
|
|
|
--
|
|
-- Name: mfa_factors; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.mfa_factors (
|
|
id uuid NOT NULL,
|
|
user_id uuid NOT NULL,
|
|
friendly_name text,
|
|
factor_type auth.factor_type NOT NULL,
|
|
status auth.factor_status NOT NULL,
|
|
created_at timestamp with time zone NOT NULL,
|
|
updated_at timestamp with time zone NOT NULL,
|
|
secret text,
|
|
phone text,
|
|
last_challenged_at timestamp with time zone,
|
|
web_authn_credential jsonb,
|
|
web_authn_aaguid uuid,
|
|
last_webauthn_challenge_data jsonb
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE mfa_factors; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.mfa_factors IS 'auth: stores metadata about factors';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN mfa_factors.last_webauthn_challenge_data; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN auth.mfa_factors.last_webauthn_challenge_data IS 'Stores the latest WebAuthn challenge data including attestation/assertion for customer verification';
|
|
|
|
|
|
--
|
|
-- Name: oauth_authorizations; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.oauth_authorizations (
|
|
id uuid NOT NULL,
|
|
authorization_id text NOT NULL,
|
|
client_id uuid NOT NULL,
|
|
user_id uuid,
|
|
redirect_uri text NOT NULL,
|
|
scope text NOT NULL,
|
|
state text,
|
|
resource text,
|
|
code_challenge text,
|
|
code_challenge_method auth.code_challenge_method,
|
|
response_type auth.oauth_response_type DEFAULT 'code'::auth.oauth_response_type NOT NULL,
|
|
status auth.oauth_authorization_status DEFAULT 'pending'::auth.oauth_authorization_status NOT NULL,
|
|
authorization_code text,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
expires_at timestamp with time zone DEFAULT (now() + '00:03:00'::interval) NOT NULL,
|
|
approved_at timestamp with time zone,
|
|
nonce text,
|
|
CONSTRAINT oauth_authorizations_authorization_code_length CHECK ((char_length(authorization_code) <= 255)),
|
|
CONSTRAINT oauth_authorizations_code_challenge_length CHECK ((char_length(code_challenge) <= 128)),
|
|
CONSTRAINT oauth_authorizations_expires_at_future CHECK ((expires_at > created_at)),
|
|
CONSTRAINT oauth_authorizations_nonce_length CHECK ((char_length(nonce) <= 255)),
|
|
CONSTRAINT oauth_authorizations_redirect_uri_length CHECK ((char_length(redirect_uri) <= 2048)),
|
|
CONSTRAINT oauth_authorizations_resource_length CHECK ((char_length(resource) <= 2048)),
|
|
CONSTRAINT oauth_authorizations_scope_length CHECK ((char_length(scope) <= 4096)),
|
|
CONSTRAINT oauth_authorizations_state_length CHECK ((char_length(state) <= 4096))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: oauth_client_states; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.oauth_client_states (
|
|
id uuid NOT NULL,
|
|
provider_type text NOT NULL,
|
|
code_verifier text,
|
|
created_at timestamp with time zone NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE oauth_client_states; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.oauth_client_states IS 'Stores OAuth states for third-party provider authentication flows where Supabase acts as the OAuth client.';
|
|
|
|
|
|
--
|
|
-- Name: oauth_clients; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.oauth_clients (
|
|
id uuid NOT NULL,
|
|
client_secret_hash text,
|
|
registration_type auth.oauth_registration_type NOT NULL,
|
|
redirect_uris text NOT NULL,
|
|
grant_types text NOT NULL,
|
|
client_name text,
|
|
client_uri text,
|
|
logo_uri text,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
deleted_at timestamp with time zone,
|
|
client_type auth.oauth_client_type DEFAULT 'confidential'::auth.oauth_client_type NOT NULL,
|
|
token_endpoint_auth_method text NOT NULL,
|
|
CONSTRAINT oauth_clients_client_name_length CHECK ((char_length(client_name) <= 1024)),
|
|
CONSTRAINT oauth_clients_client_uri_length CHECK ((char_length(client_uri) <= 2048)),
|
|
CONSTRAINT oauth_clients_logo_uri_length CHECK ((char_length(logo_uri) <= 2048)),
|
|
CONSTRAINT oauth_clients_token_endpoint_auth_method_check CHECK ((token_endpoint_auth_method = ANY (ARRAY['client_secret_basic'::text, 'client_secret_post'::text, 'none'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: oauth_consents; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.oauth_consents (
|
|
id uuid NOT NULL,
|
|
user_id uuid NOT NULL,
|
|
client_id uuid NOT NULL,
|
|
scopes text NOT NULL,
|
|
granted_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
revoked_at timestamp with time zone,
|
|
CONSTRAINT oauth_consents_revoked_after_granted CHECK (((revoked_at IS NULL) OR (revoked_at >= granted_at))),
|
|
CONSTRAINT oauth_consents_scopes_length CHECK ((char_length(scopes) <= 2048)),
|
|
CONSTRAINT oauth_consents_scopes_not_empty CHECK ((char_length(TRIM(BOTH FROM scopes)) > 0))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: one_time_tokens; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.one_time_tokens (
|
|
id uuid NOT NULL,
|
|
user_id uuid NOT NULL,
|
|
token_type auth.one_time_token_type NOT NULL,
|
|
token_hash text NOT NULL,
|
|
relates_to text NOT NULL,
|
|
created_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT one_time_tokens_token_hash_check CHECK ((char_length(token_hash) > 0))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.refresh_tokens (
|
|
instance_id uuid,
|
|
id bigint NOT NULL,
|
|
token character varying(255),
|
|
user_id character varying(255),
|
|
revoked boolean,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
parent character varying(255),
|
|
session_id uuid
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE refresh_tokens; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.refresh_tokens IS 'Auth: Store of tokens used to refresh JWT tokens once they expire.';
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens_id_seq; Type: SEQUENCE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE SEQUENCE auth.refresh_tokens_id_seq
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens_id_seq; Type: SEQUENCE OWNED BY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER SEQUENCE auth.refresh_tokens_id_seq OWNED BY auth.refresh_tokens.id;
|
|
|
|
|
|
--
|
|
-- Name: saml_providers; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.saml_providers (
|
|
id uuid NOT NULL,
|
|
sso_provider_id uuid NOT NULL,
|
|
entity_id text NOT NULL,
|
|
metadata_xml text NOT NULL,
|
|
metadata_url text,
|
|
attribute_mapping jsonb,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
name_id_format text,
|
|
CONSTRAINT "entity_id not empty" CHECK ((char_length(entity_id) > 0)),
|
|
CONSTRAINT "metadata_url not empty" CHECK (((metadata_url = NULL::text) OR (char_length(metadata_url) > 0))),
|
|
CONSTRAINT "metadata_xml not empty" CHECK ((char_length(metadata_xml) > 0))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE saml_providers; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.saml_providers IS 'Auth: Manages SAML Identity Provider connections.';
|
|
|
|
|
|
--
|
|
-- Name: saml_relay_states; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.saml_relay_states (
|
|
id uuid NOT NULL,
|
|
sso_provider_id uuid NOT NULL,
|
|
request_id text NOT NULL,
|
|
for_email text,
|
|
redirect_to text,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
flow_state_id uuid,
|
|
CONSTRAINT "request_id not empty" CHECK ((char_length(request_id) > 0))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE saml_relay_states; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.saml_relay_states IS 'Auth: Contains SAML Relay State information for each Service Provider initiated login.';
|
|
|
|
|
|
--
|
|
-- Name: schema_migrations; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.schema_migrations (
|
|
version character varying(255) NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE schema_migrations; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.schema_migrations IS 'Auth: Manages updates to the auth system.';
|
|
|
|
|
|
--
|
|
-- Name: sessions; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.sessions (
|
|
id uuid NOT NULL,
|
|
user_id uuid NOT NULL,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
factor_id uuid,
|
|
aal auth.aal_level,
|
|
not_after timestamp with time zone,
|
|
refreshed_at timestamp without time zone,
|
|
user_agent text,
|
|
ip inet,
|
|
tag text,
|
|
oauth_client_id uuid,
|
|
refresh_token_hmac_key text,
|
|
refresh_token_counter bigint,
|
|
scopes text,
|
|
CONSTRAINT sessions_scopes_length CHECK ((char_length(scopes) <= 4096))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE sessions; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.sessions IS 'Auth: Stores session data associated to a user.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN sessions.not_after; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN auth.sessions.not_after IS 'Auth: Not after is a nullable column that contains a timestamp after which the session should be regarded as expired.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN sessions.refresh_token_hmac_key; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN auth.sessions.refresh_token_hmac_key IS 'Holds a HMAC-SHA256 key used to sign refresh tokens for this session.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN sessions.refresh_token_counter; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN auth.sessions.refresh_token_counter IS 'Holds the ID (counter) of the last issued refresh token.';
|
|
|
|
|
|
--
|
|
-- Name: sso_domains; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.sso_domains (
|
|
id uuid NOT NULL,
|
|
sso_provider_id uuid NOT NULL,
|
|
domain text NOT NULL,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
CONSTRAINT "domain not empty" CHECK ((char_length(domain) > 0))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE sso_domains; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.sso_domains IS 'Auth: Manages SSO email address domain mapping to an SSO Identity Provider.';
|
|
|
|
|
|
--
|
|
-- Name: sso_providers; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.sso_providers (
|
|
id uuid NOT NULL,
|
|
resource_id text,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
disabled boolean,
|
|
CONSTRAINT "resource_id not empty" CHECK (((resource_id = NULL::text) OR (char_length(resource_id) > 0)))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE sso_providers; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.sso_providers IS 'Auth: Manages SSO identity provider information; see saml_providers for SAML.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN sso_providers.resource_id; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN auth.sso_providers.resource_id IS 'Auth: Uniquely identifies a SSO provider according to a user-chosen resource ID (case insensitive), useful in infrastructure as code.';
|
|
|
|
|
|
--
|
|
-- Name: users; Type: TABLE; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TABLE auth.users (
|
|
instance_id uuid,
|
|
id uuid NOT NULL,
|
|
aud character varying(255),
|
|
role character varying(255),
|
|
email character varying(255),
|
|
encrypted_password character varying(255),
|
|
email_confirmed_at timestamp with time zone,
|
|
invited_at timestamp with time zone,
|
|
confirmation_token character varying(255),
|
|
confirmation_sent_at timestamp with time zone,
|
|
recovery_token character varying(255),
|
|
recovery_sent_at timestamp with time zone,
|
|
email_change_token_new character varying(255),
|
|
email_change character varying(255),
|
|
email_change_sent_at timestamp with time zone,
|
|
last_sign_in_at timestamp with time zone,
|
|
raw_app_meta_data jsonb,
|
|
raw_user_meta_data jsonb,
|
|
is_super_admin boolean,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
phone text DEFAULT NULL::character varying,
|
|
phone_confirmed_at timestamp with time zone,
|
|
phone_change text DEFAULT ''::character varying,
|
|
phone_change_token character varying(255) DEFAULT ''::character varying,
|
|
phone_change_sent_at timestamp with time zone,
|
|
confirmed_at timestamp with time zone GENERATED ALWAYS AS (LEAST(email_confirmed_at, phone_confirmed_at)) STORED,
|
|
email_change_token_current character varying(255) DEFAULT ''::character varying,
|
|
email_change_confirm_status smallint DEFAULT 0,
|
|
banned_until timestamp with time zone,
|
|
reauthentication_token character varying(255) DEFAULT ''::character varying,
|
|
reauthentication_sent_at timestamp with time zone,
|
|
is_sso_user boolean DEFAULT false NOT NULL,
|
|
deleted_at timestamp with time zone,
|
|
is_anonymous boolean DEFAULT false NOT NULL,
|
|
CONSTRAINT users_email_change_confirm_status_check CHECK (((email_change_confirm_status >= 0) AND (email_change_confirm_status <= 2)))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE users; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE auth.users IS 'Auth: Stores user login data within a secure schema.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN users.is_sso_user; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN auth.users.is_sso_user IS 'Auth: Set this column to true when the account comes from SSO. These accounts can have duplicate emails.';
|
|
|
|
|
|
--
|
|
-- Name: _db_migrations; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public._db_migrations (
|
|
id integer NOT NULL,
|
|
filename text NOT NULL,
|
|
hash text NOT NULL,
|
|
category text DEFAULT 'migration'::text NOT NULL,
|
|
applied_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: _db_migrations_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE SEQUENCE public._db_migrations_id_seq
|
|
AS integer
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
|
|
--
|
|
-- Name: _db_migrations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER SEQUENCE public._db_migrations_id_seq OWNED BY public._db_migrations.id;
|
|
|
|
|
|
--
|
|
-- Name: addon_credits; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.addon_credits (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
owner_id uuid,
|
|
addon_type text NOT NULL,
|
|
balance integer DEFAULT 0 NOT NULL,
|
|
total_purchased integer DEFAULT 0 NOT NULL,
|
|
total_consumed integer DEFAULT 0 NOT NULL,
|
|
low_balance_threshold integer DEFAULT 10,
|
|
low_balance_notified boolean DEFAULT false,
|
|
daily_limit integer,
|
|
hourly_limit integer,
|
|
daily_used integer DEFAULT 0,
|
|
hourly_used integer DEFAULT 0,
|
|
daily_reset_at timestamp with time zone,
|
|
hourly_reset_at timestamp with time zone,
|
|
from_number_override text,
|
|
expires_at timestamp with time zone,
|
|
is_active boolean DEFAULT true,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE addon_credits; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE public.addon_credits IS 'Saldo de cr??ditos de add-ons por tenant. Um registro por (tenant_id, addon_type).';
|
|
|
|
|
|
--
|
|
-- Name: addon_products; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.addon_products (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
slug text NOT NULL,
|
|
name text NOT NULL,
|
|
description text,
|
|
addon_type text NOT NULL,
|
|
icon text DEFAULT 'pi pi-box'::text,
|
|
credits_amount integer DEFAULT 0,
|
|
price_cents integer DEFAULT 0 NOT NULL,
|
|
currency text DEFAULT 'BRL'::text,
|
|
is_active boolean DEFAULT true,
|
|
is_visible boolean DEFAULT true,
|
|
sort_order integer DEFAULT 0,
|
|
metadata jsonb DEFAULT '{}'::jsonb,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now(),
|
|
deleted_at timestamp with time zone
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE addon_products; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE public.addon_products IS 'Cat??logo de recursos extras vendidos pela plataforma (SMS, servidor, dom??nio, etc.)';
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.addon_transactions (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
owner_id uuid,
|
|
addon_type text NOT NULL,
|
|
type text NOT NULL,
|
|
amount integer NOT NULL,
|
|
balance_before integer DEFAULT 0 NOT NULL,
|
|
balance_after integer DEFAULT 0 NOT NULL,
|
|
product_id uuid,
|
|
queue_id uuid,
|
|
description text,
|
|
admin_user_id uuid,
|
|
payment_method text,
|
|
payment_reference text,
|
|
price_cents integer,
|
|
currency text DEFAULT 'BRL'::text,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
metadata jsonb DEFAULT '{}'::jsonb
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE addon_transactions; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE public.addon_transactions IS 'Hist??rico de todas as transa????es de cr??ditos: compras, consumo, ajustes, reembolsos.';
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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,
|
|
slot_mode text DEFAULT 'fixed'::text NOT NULL,
|
|
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 agenda_configuracoes_slot_mode_chk CHECK ((slot_mode = ANY (ARRAY['fixed'::text, 'dynamic'::text]))),
|
|
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)))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.agenda_eventos (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
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,
|
|
price numeric(10,2),
|
|
billing_contract_id uuid,
|
|
billed boolean DEFAULT false NOT NULL,
|
|
services_customized boolean DEFAULT false NOT NULL,
|
|
insurance_plan_id uuid,
|
|
insurance_guide_number text,
|
|
insurance_value numeric(10,2),
|
|
insurance_plan_service_id uuid,
|
|
CONSTRAINT agenda_eventos_check CHECK ((fim_em > inicio_em))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN agenda_eventos.price; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.agenda_eventos.price IS 'Valor da sess??o em BRL. Preenchido automaticamente pela tabela professional_pricing do profissional.';
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE SEQUENCE public.agenda_online_slots_id_seq
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER SEQUENCE public.agenda_online_slots_id_seq OWNED BY public.agenda_online_slots.id;
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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)))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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)))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_regras; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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)))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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,
|
|
pagamento_modo text DEFAULT 'sem_pagamento'::text NOT NULL,
|
|
pagamento_metodos_visiveis text[] DEFAULT '{}'::text[] 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)))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN agendador_configuracoes.pagamento_modo; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.agendador_configuracoes.pagamento_modo IS 'sem_pagamento | pagar_na_hora | pix_antecipado';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN agendador_configuracoes.pagamento_metodos_visiveis; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.agendador_configuracoes.pagamento_metodos_visiveis IS 'M??todos exibidos ao paciente quando pagamento_modo = pagar_na_hora. Ex: {pix, deposito, dinheiro, cartao, convenio}';
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: billing_contracts; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.billing_contracts (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
patient_id uuid NOT NULL,
|
|
type text NOT NULL,
|
|
total_sessions integer,
|
|
sessions_used integer DEFAULT 0,
|
|
package_price numeric(10,2),
|
|
amount numeric(10,2),
|
|
billing_interval text,
|
|
active_from timestamp with time zone DEFAULT now(),
|
|
active_to timestamp with time zone,
|
|
status text DEFAULT 'active'::text NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
CONSTRAINT billing_contracts_interval_chk CHECK (((billing_interval IS NULL) OR (billing_interval = ANY (ARRAY['monthly'::text, 'weekly'::text])))),
|
|
CONSTRAINT billing_contracts_sess_used_chk CHECK (((sessions_used IS NULL) OR (sessions_used >= 0))),
|
|
CONSTRAINT billing_contracts_status_chk CHECK ((status = ANY (ARRAY['active'::text, 'completed'::text, 'cancelled'::text]))),
|
|
CONSTRAINT billing_contracts_total_sess_chk CHECK (((total_sessions IS NULL) OR (total_sessions > 0))),
|
|
CONSTRAINT billing_contracts_type_chk CHECK ((type = ANY (ARRAY['per_session'::text, 'package'::text, 'subscription'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: commitment_services; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.commitment_services (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
commitment_id uuid NOT NULL,
|
|
service_id uuid NOT NULL,
|
|
quantity integer DEFAULT 1 NOT NULL,
|
|
unit_price numeric(10,2) NOT NULL,
|
|
discount_pct numeric(5,2) DEFAULT 0,
|
|
discount_flat numeric(10,2) DEFAULT 0,
|
|
final_price numeric(10,2) NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
CONSTRAINT commitment_services_disc_flat_chk CHECK ((discount_flat >= (0)::numeric)),
|
|
CONSTRAINT commitment_services_disc_pct_chk CHECK (((discount_pct >= (0)::numeric) AND (discount_pct <= (100)::numeric))),
|
|
CONSTRAINT commitment_services_final_price_chk CHECK ((final_price >= (0)::numeric)),
|
|
CONSTRAINT commitment_services_quantity_chk CHECK ((quantity > 0))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: company_profiles; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.company_profiles (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
nome_fantasia text,
|
|
razao_social text,
|
|
tipo_empresa text,
|
|
cnpj text,
|
|
ie text,
|
|
im text,
|
|
cep text,
|
|
logradouro text,
|
|
numero text,
|
|
complemento text,
|
|
bairro text,
|
|
cidade text,
|
|
estado text,
|
|
email text,
|
|
telefone text,
|
|
site text,
|
|
logo_url text,
|
|
redes_sociais jsonb DEFAULT '[]'::jsonb NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: current_tenant_id; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE VIEW public.current_tenant_id AS
|
|
SELECT current_setting('request.jwt.claim.tenant_id'::text, true) AS current_setting;
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: dev_user_credentials; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: email_layout_config; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.email_layout_config (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
header_config jsonb DEFAULT '{"layout": null, "content": "", "enabled": false}'::jsonb NOT NULL,
|
|
footer_config jsonb DEFAULT '{"layout": null, "content": "", "enabled": false}'::jsonb NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: email_templates_global; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.email_templates_global (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
key text NOT NULL,
|
|
domain text NOT NULL,
|
|
channel text DEFAULT 'email'::text NOT NULL,
|
|
subject text NOT NULL,
|
|
body_html text NOT NULL,
|
|
body_text text,
|
|
version integer DEFAULT 1 NOT NULL,
|
|
is_active boolean DEFAULT true NOT NULL,
|
|
variables jsonb,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: email_templates_tenant; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.email_templates_tenant (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
owner_id uuid,
|
|
template_key text NOT NULL,
|
|
subject text,
|
|
body_html text,
|
|
body_text text,
|
|
enabled boolean DEFAULT true NOT NULL,
|
|
synced_version integer,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: entitlements_invalidation; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.entitlements_invalidation (
|
|
owner_id uuid NOT NULL,
|
|
changed_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: features; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN features.descricao; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.features.descricao IS 'Descri????o humana da feature (exibi????o no admin e documenta????o).';
|
|
|
|
|
|
--
|
|
-- Name: feriados; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: financial_categories; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.financial_categories (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
user_id uuid NOT NULL,
|
|
name text NOT NULL,
|
|
type public.financial_record_type DEFAULT 'receita'::public.financial_record_type NOT NULL,
|
|
color text DEFAULT '#6366f1'::text,
|
|
icon text DEFAULT 'pi pi-tag'::text,
|
|
sort_order integer DEFAULT 0,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: financial_exceptions; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.financial_exceptions (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid,
|
|
tenant_id uuid NOT NULL,
|
|
exception_type text NOT NULL,
|
|
charge_mode text NOT NULL,
|
|
charge_value numeric(10,2),
|
|
charge_pct numeric(5,2),
|
|
min_hours_notice integer,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now(),
|
|
CONSTRAINT financial_exceptions_charge_chk CHECK ((charge_mode = ANY (ARRAY['none'::text, 'full'::text, 'fixed_fee'::text, 'percentage'::text]))),
|
|
CONSTRAINT financial_exceptions_type_chk CHECK ((exception_type = ANY (ARRAY['patient_no_show'::text, 'patient_cancellation'::text, 'professional_cancellation'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: global_notices; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.global_notices (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
title text,
|
|
message text DEFAULT ''::text NOT NULL,
|
|
variant text DEFAULT 'info'::text NOT NULL,
|
|
roles text[] DEFAULT '{}'::text[] NOT NULL,
|
|
contexts text[] DEFAULT '{}'::text[] NOT NULL,
|
|
starts_at timestamp with time zone,
|
|
ends_at timestamp with time zone,
|
|
is_active boolean DEFAULT true NOT NULL,
|
|
priority integer DEFAULT 0 NOT NULL,
|
|
dismissible boolean DEFAULT true NOT NULL,
|
|
persist_dismiss boolean DEFAULT true NOT NULL,
|
|
dismiss_scope text DEFAULT 'device'::text NOT NULL,
|
|
show_once boolean DEFAULT false NOT NULL,
|
|
max_views integer,
|
|
cooldown_minutes integer,
|
|
version integer DEFAULT 1 NOT NULL,
|
|
action_type text DEFAULT 'none'::text NOT NULL,
|
|
action_label text,
|
|
action_url text,
|
|
action_route text,
|
|
views_count integer DEFAULT 0 NOT NULL,
|
|
clicks_count 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,
|
|
created_by uuid,
|
|
content_align text DEFAULT 'left'::text NOT NULL,
|
|
link_target text DEFAULT '_blank'::text NOT NULL,
|
|
CONSTRAINT global_notices_action_type_check CHECK ((action_type = ANY (ARRAY['none'::text, 'internal'::text, 'external'::text]))),
|
|
CONSTRAINT global_notices_content_align_check CHECK ((content_align = ANY (ARRAY['left'::text, 'center'::text, 'right'::text, 'justify'::text]))),
|
|
CONSTRAINT global_notices_dismiss_scope_check CHECK ((dismiss_scope = ANY (ARRAY['session'::text, 'device'::text, 'user'::text]))),
|
|
CONSTRAINT global_notices_link_target_check CHECK ((link_target = ANY (ARRAY['_blank'::text, '_self'::text, '_parent'::text, '_top'::text]))),
|
|
CONSTRAINT global_notices_variant_check CHECK ((variant = ANY (ARRAY['info'::text, 'success'::text, 'warning'::text, 'error'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: insurance_plan_services; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.insurance_plan_services (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
insurance_plan_id uuid NOT NULL,
|
|
name text NOT NULL,
|
|
value numeric(10,2) NOT NULL,
|
|
active boolean DEFAULT true NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: insurance_plans; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.insurance_plans (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
name text NOT NULL,
|
|
notes text,
|
|
default_value numeric(10,2),
|
|
active boolean DEFAULT true NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: login_carousel_slides; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.login_carousel_slides (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
title text NOT NULL,
|
|
body text NOT NULL,
|
|
icon text DEFAULT 'pi-star'::text NOT NULL,
|
|
ordem integer DEFAULT 0 NOT NULL,
|
|
ativo boolean DEFAULT true NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: module_features; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: modules; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: notice_dismissals; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.notice_dismissals (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
notice_id uuid NOT NULL,
|
|
user_id uuid NOT NULL,
|
|
version integer DEFAULT 1 NOT NULL,
|
|
dismissed_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: notification_channels; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.notification_channels (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
channel text NOT NULL,
|
|
provider text NOT NULL,
|
|
is_active boolean DEFAULT false NOT NULL,
|
|
display_name text,
|
|
sender_address text,
|
|
credentials jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
connection_status text DEFAULT 'disconnected'::text,
|
|
last_health_check timestamp with time zone,
|
|
metadata jsonb DEFAULT '{}'::jsonb,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
deleted_at timestamp with time zone,
|
|
CONSTRAINT notification_channels_channel_check CHECK ((channel = ANY (ARRAY['whatsapp'::text, 'email'::text, 'sms'::text]))),
|
|
CONSTRAINT notification_channels_connection_status_check CHECK ((connection_status = ANY (ARRAY['connected'::text, 'disconnected'::text, 'connecting'::text, 'qr_pending'::text, 'error'::text]))),
|
|
CONSTRAINT notification_channels_provider_check CHECK ((provider = ANY (ARRAY['evolution_api'::text, 'meta_official'::text, 'twilio'::text, 'zenvia'::text, 'sendgrid'::text, 'resend'::text, 'smtp'::text, 'zapi'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: notification_logs; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.notification_logs (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
queue_id uuid,
|
|
agenda_evento_id uuid,
|
|
patient_id uuid NOT NULL,
|
|
channel text NOT NULL,
|
|
template_key text NOT NULL,
|
|
schedule_key text,
|
|
recipient_address text NOT NULL,
|
|
resolved_message text,
|
|
resolved_vars jsonb,
|
|
status text NOT NULL,
|
|
provider text,
|
|
provider_message_id text,
|
|
provider_status text,
|
|
provider_response jsonb,
|
|
sent_at timestamp with time zone,
|
|
delivered_at timestamp with time zone,
|
|
read_at timestamp with time zone,
|
|
failed_at timestamp with time zone,
|
|
failure_reason text,
|
|
estimated_cost_brl numeric(8,4) DEFAULT 0,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT notification_logs_status_check CHECK ((status = ANY (ARRAY['sent'::text, 'delivered'::text, 'read'::text, 'failed'::text, 'bounced'::text, 'opted_out'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: notification_preferences; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.notification_preferences (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
patient_id uuid NOT NULL,
|
|
whatsapp_opt_in boolean DEFAULT true NOT NULL,
|
|
email_opt_in boolean DEFAULT true NOT NULL,
|
|
sms_opt_in boolean DEFAULT false NOT NULL,
|
|
preferred_time_start time without time zone DEFAULT '08:00:00'::time without time zone,
|
|
preferred_time_end time without time zone DEFAULT '20:00:00'::time without time zone,
|
|
lgpd_consent_given boolean DEFAULT false NOT NULL,
|
|
lgpd_consent_date timestamp with time zone,
|
|
lgpd_consent_version text,
|
|
lgpd_consent_ip inet,
|
|
lgpd_opt_out_date timestamp with time zone,
|
|
lgpd_opt_out_reason text,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
deleted_at timestamp with time zone
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: notification_queue; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.notification_queue (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
agenda_evento_id uuid,
|
|
patient_id uuid NOT NULL,
|
|
channel text NOT NULL,
|
|
template_key text NOT NULL,
|
|
schedule_key text NOT NULL,
|
|
resolved_vars jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
recipient_address text NOT NULL,
|
|
status text DEFAULT 'pendente'::text NOT NULL,
|
|
scheduled_at timestamp with time zone NOT NULL,
|
|
sent_at timestamp with time zone,
|
|
next_retry_at timestamp with time zone,
|
|
attempts integer DEFAULT 0 NOT NULL,
|
|
max_attempts integer DEFAULT 5 NOT NULL,
|
|
last_error text,
|
|
idempotency_key text NOT NULL,
|
|
provider_message_id text,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT notification_queue_channel_check CHECK ((channel = ANY (ARRAY['whatsapp'::text, 'email'::text, 'sms'::text]))),
|
|
CONSTRAINT notification_queue_status_check CHECK ((status = ANY (ARRAY['pendente'::text, 'processando'::text, 'enviado'::text, 'falhou'::text, 'cancelado'::text, 'ignorado'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: notification_schedules; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.notification_schedules (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
schedule_key text NOT NULL,
|
|
event_type text NOT NULL,
|
|
trigger_type text NOT NULL,
|
|
offset_minutes integer DEFAULT 0,
|
|
whatsapp_enabled boolean DEFAULT true NOT NULL,
|
|
email_enabled boolean DEFAULT true NOT NULL,
|
|
sms_enabled boolean DEFAULT false NOT NULL,
|
|
allowed_time_start time without time zone DEFAULT '08:00:00'::time without time zone,
|
|
allowed_time_end time without time zone DEFAULT '20:00:00'::time without time zone,
|
|
skip_weekends boolean DEFAULT false,
|
|
skip_holidays boolean DEFAULT false,
|
|
is_active boolean DEFAULT true NOT NULL,
|
|
sort_order integer DEFAULT 0,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
deleted_at timestamp with time zone,
|
|
CONSTRAINT notification_schedules_event_type_check CHECK ((event_type = ANY (ARRAY['lembrete_sessao'::text, 'confirmacao_sessao'::text, 'cancelamento_sessao'::text, 'reagendamento'::text, 'cobranca_pendente'::text, 'boas_vindas_paciente'::text]))),
|
|
CONSTRAINT notification_schedules_trigger_type_check CHECK ((trigger_type = ANY (ARRAY['before_event'::text, 'after_event'::text, 'immediate'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: notification_templates; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.notification_templates (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid,
|
|
owner_id uuid,
|
|
key text NOT NULL,
|
|
domain text NOT NULL,
|
|
channel text NOT NULL,
|
|
event_type text NOT NULL,
|
|
body_text text NOT NULL,
|
|
meta_template_name text,
|
|
meta_template_namespace text,
|
|
meta_components jsonb,
|
|
meta_status text DEFAULT 'draft'::text,
|
|
variables jsonb DEFAULT '[]'::jsonb,
|
|
version integer DEFAULT 1 NOT NULL,
|
|
is_active boolean DEFAULT true NOT NULL,
|
|
is_default 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,
|
|
deleted_at timestamp with time zone,
|
|
CONSTRAINT notification_templates_channel_check CHECK ((channel = ANY (ARRAY['whatsapp'::text, 'sms'::text]))),
|
|
CONSTRAINT notification_templates_domain_check CHECK ((domain = ANY (ARRAY['session'::text, 'intake'::text, 'billing'::text, 'system'::text]))),
|
|
CONSTRAINT notification_templates_event_type_check CHECK ((event_type = ANY (ARRAY['lembrete_sessao'::text, 'confirmacao_sessao'::text, 'cancelamento_sessao'::text, 'reagendamento'::text, 'cobranca_pendente'::text, 'boas_vindas_paciente'::text, 'intake_recebido'::text, 'intake_aprovado'::text, 'intake_rejeitado'::text]))),
|
|
CONSTRAINT notification_templates_meta_status_check CHECK ((meta_status = ANY (ARRAY['draft'::text, 'pending_approval'::text, 'approved'::text, 'rejected'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: notifications; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.notifications (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid,
|
|
type text NOT NULL,
|
|
ref_id uuid,
|
|
ref_table text,
|
|
payload jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
read_at timestamp with time zone,
|
|
archived boolean DEFAULT false NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT notifications_type_check CHECK ((type = ANY (ARRAY['new_scheduling'::text, 'new_patient'::text, 'recurrence_alert'::text, 'session_status'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: plan_features; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tenant_modules; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: owner_feature_entitlements; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: owner_users; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: patient_discounts; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.patient_discounts (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
patient_id uuid NOT NULL,
|
|
discount_pct numeric(5,2) DEFAULT 0,
|
|
discount_flat numeric(10,2) DEFAULT 0,
|
|
reason text,
|
|
active boolean DEFAULT true NOT NULL,
|
|
active_from timestamp with time zone DEFAULT now(),
|
|
active_to timestamp with time zone,
|
|
created_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: patient_group_patient; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: patient_groups; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: patient_invites; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: patient_tags; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: patients; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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, 'Arquivado'::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))))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN patients.avatar_url; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.patients.avatar_url IS 'URL p??blica da imagem de avatar armazenada no Supabase Storage';
|
|
|
|
|
|
--
|
|
-- Name: payment_settings; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.payment_settings (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid,
|
|
pix_ativo boolean DEFAULT false NOT NULL,
|
|
pix_tipo text DEFAULT 'cpf'::text NOT NULL,
|
|
pix_chave text DEFAULT ''::text NOT NULL,
|
|
pix_nome_titular text DEFAULT ''::text NOT NULL,
|
|
deposito_ativo boolean DEFAULT false NOT NULL,
|
|
deposito_banco text DEFAULT ''::text NOT NULL,
|
|
deposito_agencia text DEFAULT ''::text NOT NULL,
|
|
deposito_conta text DEFAULT ''::text NOT NULL,
|
|
deposito_tipo_conta text DEFAULT 'corrente'::text NOT NULL,
|
|
deposito_titular text DEFAULT ''::text NOT NULL,
|
|
deposito_cpf_cnpj text DEFAULT ''::text NOT NULL,
|
|
dinheiro_ativo boolean DEFAULT false NOT NULL,
|
|
cartao_ativo boolean DEFAULT false NOT NULL,
|
|
cartao_instrucao text DEFAULT ''::text NOT NULL,
|
|
convenio_ativo boolean DEFAULT false NOT NULL,
|
|
convenio_lista text DEFAULT ''::text NOT NULL,
|
|
observacoes_pagamento text DEFAULT ''::text NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: plan_prices; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE plan_prices; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE public.plan_prices IS 'Hist??rico de pre??os por plano (fonte: manual/gateway).';
|
|
|
|
|
|
--
|
|
-- Name: plan_public; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE plan_public; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE public.plan_public IS 'Configura????o de vitrine (p??gina p??blica) dos planos.';
|
|
|
|
|
|
--
|
|
-- Name: plan_public_bullets; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: plans; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN plans.name; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.plans.name IS 'Nome interno do plano (admin). A key ?? t??cnica/imut??vel.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN plans.target; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.plans.target IS 'P??blico-alvo do plano: patient, therapist ou clinic.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN plans.max_supervisees; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.plans.max_supervisees IS 'Limite de terapeutas que podem ser supervisionados. Apenas para planos target=supervisor. NULL = sem limite.';
|
|
|
|
|
|
--
|
|
-- Name: professional_pricing; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.professional_pricing (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
determined_commitment_id uuid,
|
|
price numeric(10,2) NOT NULL,
|
|
notes text,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE professional_pricing; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE public.professional_pricing IS 'DEPRECATED: substitu??da por public.services. Manter at?? pr??xima release de limpeza.';
|
|
|
|
|
|
--
|
|
-- Name: profiles; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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,
|
|
nickname text,
|
|
work_description text,
|
|
work_description_other text,
|
|
site_url text,
|
|
social_instagram text,
|
|
social_youtube text,
|
|
social_facebook text,
|
|
social_x text,
|
|
social_custom jsonb DEFAULT '[]'::jsonb 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.phone; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.phone IS 'WhatsApp / telefone no formato (99) 99999-9999';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.bio; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.bio IS 'Breve apresenta????o p??blica (m??x 300 chars no front)';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.account_type; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
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).';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.platform_roles; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
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.';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.nickname; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.nickname IS 'Apelido preferido para comunica????o interna (Ag??ncia PSI)';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.work_description; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.work_description IS 'Categoria de trabalho selecionada no perfil p??blico';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.work_description_other; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.work_description_other IS 'Descri????o livre quando work_description = ''outro''';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.site_url; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.site_url IS 'Endere??o do site pessoal ou profissional';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.social_instagram; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.social_instagram IS 'Handle ou URL do Instagram';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.social_youtube; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.social_youtube IS 'Handle ou URL do canal no YouTube';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.social_facebook; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.social_facebook IS 'Handle ou URL da p??gina no Facebook';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.social_x; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.social_x IS 'Handle ou URL do perfil no X (Twitter)';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN profiles.social_custom; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.profiles.social_custom IS 'Array JSON com redes adicionais livres: [{name, url}]';
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exceptions; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.recurrence_rule_services (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
rule_id uuid NOT NULL,
|
|
service_id uuid NOT NULL,
|
|
quantity integer DEFAULT 1 NOT NULL,
|
|
unit_price numeric(10,2) NOT NULL,
|
|
discount_pct numeric(5,2) DEFAULT 0,
|
|
discount_flat numeric(10,2) DEFAULT 0,
|
|
final_price numeric(10,2) NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
CONSTRAINT recurrence_rule_services_disc_flat_chk CHECK ((discount_flat >= (0)::numeric)),
|
|
CONSTRAINT recurrence_rule_services_disc_pct_chk CHECK (((discount_pct >= (0)::numeric) AND (discount_pct <= (100)::numeric))),
|
|
CONSTRAINT recurrence_rule_services_final_price_chk CHECK ((final_price >= (0)::numeric)),
|
|
CONSTRAINT recurrence_rule_services_quantity_chk CHECK ((quantity > 0))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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,
|
|
price numeric(10,2),
|
|
insurance_plan_id uuid,
|
|
insurance_guide_number text,
|
|
insurance_value numeric(10,2),
|
|
insurance_plan_service_id uuid,
|
|
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))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: saas_admins; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.saas_admins (
|
|
user_id uuid NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: saas_docs; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN saas_docs.categoria; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.saas_docs.categoria IS 'Agrupa docs no portal FAQ (ex: Conta, Agenda, Pagamentos)';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN saas_docs.exibir_no_faq; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.saas_docs.exibir_no_faq IS 'Se true, a doc e seus itens FAQ aparecem no portal de FAQ';
|
|
|
|
|
|
--
|
|
-- Name: saas_faq; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_itens; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE saas_faq_itens; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE public.saas_faq_itens IS 'Pares pergunta/resposta vinculados a um documento de ajuda';
|
|
|
|
|
|
--
|
|
-- Name: services; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.services (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
owner_id uuid NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
name text NOT NULL,
|
|
description text,
|
|
price numeric(10,2) NOT NULL,
|
|
duration_min integer,
|
|
active boolean DEFAULT true NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: subscription_events; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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]))))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_personal; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_tenant; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_legacy; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: support_sessions; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.support_sessions (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
tenant_id uuid NOT NULL,
|
|
admin_id uuid NOT NULL,
|
|
token text DEFAULT encode(extensions.gen_random_bytes(32), 'hex'::text) NOT NULL,
|
|
expires_at timestamp with time zone DEFAULT (now() + '01:00:00'::interval) NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tenant_feature_exceptions_log; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tenant_features; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tenant_invites; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: tenants; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN tenants.kind; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
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.';
|
|
|
|
|
|
--
|
|
-- Name: therapist_payout_records; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE public.therapist_payout_records (
|
|
payout_id uuid NOT NULL,
|
|
financial_record_id uuid NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: user_settings; Type: TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TABLE 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,
|
|
layout_variant text DEFAULT 'classic'::text NOT NULL,
|
|
CONSTRAINT user_settings_layout_variant_check CHECK ((layout_variant = ANY (ARRAY['classic'::text, 'rail'::text]))),
|
|
CONSTRAINT user_settings_menu_mode_check CHECK ((menu_mode = ANY (ARRAY['static'::text, 'overlay'::text]))),
|
|
CONSTRAINT user_settings_theme_mode_check CHECK ((theme_mode = ANY (ARRAY['light'::text, 'dark'::text])))
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE user_settings; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE public.user_settings IS 'Prefer??ncias de apar??ncia e layout por usu??rio';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN user_settings.user_id; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.user_settings.user_id IS 'FK = auth.users.id ??? um registro por usu??rio';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN user_settings.theme_mode; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.user_settings.theme_mode IS 'light | dark';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN user_settings.preset; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.user_settings.preset IS 'Preset PrimeVue: Aura | Lara | Nora';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN user_settings.primary_color; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.user_settings.primary_color IS 'Nome da cor prim??ria (ex: blue, emerald, noir)';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN user_settings.surface_color; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.user_settings.surface_color IS 'Nome da surface (ex: slate, zinc, neutral)';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN user_settings.menu_mode; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.user_settings.menu_mode IS 'static | overlay';
|
|
|
|
|
|
--
|
|
-- Name: COLUMN user_settings.layout_variant; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN public.user_settings.layout_variant IS 'classic (sidebar) | rail (mini rail + painel)';
|
|
|
|
|
|
--
|
|
-- Name: v_auth_users_public; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE VIEW public.v_auth_users_public AS
|
|
SELECT id AS user_id,
|
|
email,
|
|
created_at,
|
|
last_sign_in_at
|
|
FROM auth.users u;
|
|
|
|
|
|
--
|
|
-- Name: v_cashflow_projection; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE VIEW public.v_cashflow_projection WITH (security_invoker='on') AS
|
|
SELECT gs.mes,
|
|
to_char(gs.mes, 'YYYY-MM'::text) AS mes_label,
|
|
COALESCE(sum(fr.final_amount) FILTER (WHERE ((fr.type = 'receita'::public.financial_record_type) AND (fr.status = ANY (ARRAY['pending'::text, 'overdue'::text])))), (0)::numeric) AS receitas_projetadas,
|
|
COALESCE(sum(fr.final_amount) FILTER (WHERE ((fr.type = 'despesa'::public.financial_record_type) AND (fr.status = ANY (ARRAY['pending'::text, 'overdue'::text])))), (0)::numeric) AS despesas_projetadas,
|
|
COALESCE(sum(fr.final_amount) FILTER (WHERE ((fr.type = 'receita'::public.financial_record_type) AND (fr.status = 'pending'::text))), (0)::numeric) AS receitas_pendentes,
|
|
COALESCE(sum(fr.final_amount) FILTER (WHERE ((fr.type = 'receita'::public.financial_record_type) AND (fr.status = 'overdue'::text))), (0)::numeric) AS receitas_vencidas,
|
|
COALESCE(sum(fr.final_amount) FILTER (WHERE ((fr.type = 'despesa'::public.financial_record_type) AND (fr.status = 'pending'::text))), (0)::numeric) AS despesas_pendentes,
|
|
COALESCE(sum(fr.final_amount) FILTER (WHERE ((fr.type = 'despesa'::public.financial_record_type) AND (fr.status = 'overdue'::text))), (0)::numeric) AS despesas_vencidas,
|
|
(COALESCE(sum(fr.final_amount) FILTER (WHERE ((fr.type = 'receita'::public.financial_record_type) AND (fr.status = ANY (ARRAY['pending'::text, 'overdue'::text])))), (0)::numeric) - COALESCE(sum(fr.final_amount) FILTER (WHERE ((fr.type = 'despesa'::public.financial_record_type) AND (fr.status = ANY (ARRAY['pending'::text, 'overdue'::text])))), (0)::numeric)) AS saldo_projetado,
|
|
count(fr.id) FILTER (WHERE (fr.status = ANY (ARRAY['pending'::text, 'overdue'::text]))) AS count_registros
|
|
FROM (generate_series(((date_trunc('month'::text, (CURRENT_DATE)::timestamp with time zone))::date)::timestamp with time zone, (((date_trunc('month'::text, (CURRENT_DATE)::timestamp with time zone) + '5 mons'::interval))::date)::timestamp with time zone, '1 mon'::interval) gs(mes)
|
|
LEFT JOIN public.financial_records fr ON (((fr.deleted_at IS NULL) AND (fr.status = ANY (ARRAY['pending'::text, 'overdue'::text])) AND ((date_trunc('month'::text, (fr.due_date)::timestamp with time zone))::date = gs.mes))))
|
|
GROUP BY gs.mes
|
|
ORDER BY gs.mes;
|
|
|
|
|
|
--
|
|
-- Name: VIEW v_cashflow_projection; Type: COMMENT; Schema: public; Owner: -
|
|
--
|
|
|
|
COMMENT ON VIEW public.v_cashflow_projection IS 'Fluxo de caixa projetado: pr??ximos 6 meses com totais de pending+overdue por due_date. Usa security_invoker=on ??? filtra automaticamente pelo auth.uid() via RLS de financial_records.';
|
|
|
|
|
|
--
|
|
-- Name: v_commitment_totals; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: v_patient_groups_with_counts; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: v_plan_active_prices; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: v_public_pricing; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: v_subscription_feature_mismatch; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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));
|
|
|
|
|
|
--
|
|
-- Name: v_subscription_health; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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)));
|
|
|
|
|
|
--
|
|
-- Name: v_subscription_health_v2; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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)));
|
|
|
|
|
|
--
|
|
-- Name: v_tag_patient_counts; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_active_subscription; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_entitlements; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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)));
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_entitlements_full; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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)));
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_entitlements_json; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_feature_exceptions; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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));
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_feature_mismatch; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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));
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_members_with_profiles; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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)));
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_people; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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));
|
|
|
|
|
|
--
|
|
-- Name: v_tenant_staff; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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()));
|
|
|
|
|
|
--
|
|
-- Name: v_user_active_subscription; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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;
|
|
|
|
|
|
--
|
|
-- Name: v_user_entitlements; Type: VIEW; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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)));
|
|
|
|
|
|
--
|
|
-- Name: messages; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.messages (
|
|
topic text NOT NULL,
|
|
extension text NOT NULL,
|
|
payload jsonb,
|
|
event text,
|
|
private boolean DEFAULT false,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
inserted_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
)
|
|
PARTITION BY RANGE (inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_20; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.messages_2026_03_20 (
|
|
topic text NOT NULL,
|
|
extension text NOT NULL,
|
|
payload jsonb,
|
|
event text,
|
|
private boolean DEFAULT false,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
inserted_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_21; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.messages_2026_03_21 (
|
|
topic text NOT NULL,
|
|
extension text NOT NULL,
|
|
payload jsonb,
|
|
event text,
|
|
private boolean DEFAULT false,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
inserted_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_22; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.messages_2026_03_22 (
|
|
topic text NOT NULL,
|
|
extension text NOT NULL,
|
|
payload jsonb,
|
|
event text,
|
|
private boolean DEFAULT false,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
inserted_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_23; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.messages_2026_03_23 (
|
|
topic text NOT NULL,
|
|
extension text NOT NULL,
|
|
payload jsonb,
|
|
event text,
|
|
private boolean DEFAULT false,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
inserted_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_24; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.messages_2026_03_24 (
|
|
topic text NOT NULL,
|
|
extension text NOT NULL,
|
|
payload jsonb,
|
|
event text,
|
|
private boolean DEFAULT false,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
inserted_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_25; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.messages_2026_03_25 (
|
|
topic text NOT NULL,
|
|
extension text NOT NULL,
|
|
payload jsonb,
|
|
event text,
|
|
private boolean DEFAULT false,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
inserted_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_26; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.messages_2026_03_26 (
|
|
topic text NOT NULL,
|
|
extension text NOT NULL,
|
|
payload jsonb,
|
|
event text,
|
|
private boolean DEFAULT false,
|
|
updated_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
inserted_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: schema_migrations; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.schema_migrations (
|
|
version bigint NOT NULL,
|
|
inserted_at timestamp(0) without time zone
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: subscription; Type: TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TABLE realtime.subscription (
|
|
id bigint NOT NULL,
|
|
subscription_id uuid NOT NULL,
|
|
entity regclass NOT NULL,
|
|
filters realtime.user_defined_filter[] DEFAULT '{}'::realtime.user_defined_filter[] NOT NULL,
|
|
claims jsonb NOT NULL,
|
|
claims_role regrole GENERATED ALWAYS AS (realtime.to_regrole((claims ->> 'role'::text))) STORED NOT NULL,
|
|
created_at timestamp without time zone DEFAULT timezone('utc'::text, now()) NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: subscription_id_seq; Type: SEQUENCE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE realtime.subscription ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
|
|
SEQUENCE NAME realtime.subscription_id_seq
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: buckets; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.buckets (
|
|
id text NOT NULL,
|
|
name text NOT NULL,
|
|
owner uuid,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now(),
|
|
public boolean DEFAULT false,
|
|
avif_autodetection boolean DEFAULT false,
|
|
file_size_limit bigint,
|
|
allowed_mime_types text[],
|
|
owner_id text,
|
|
type storage.buckettype DEFAULT 'STANDARD'::storage.buckettype NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN buckets.owner; Type: COMMENT; Schema: storage; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN storage.buckets.owner IS 'Field is deprecated, use owner_id instead';
|
|
|
|
|
|
--
|
|
-- Name: buckets_analytics; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.buckets_analytics (
|
|
name text NOT NULL,
|
|
type storage.buckettype DEFAULT 'ANALYTICS'::storage.buckettype NOT NULL,
|
|
format text DEFAULT 'ICEBERG'::text NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
deleted_at timestamp with time zone
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: buckets_vectors; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.buckets_vectors (
|
|
id text NOT NULL,
|
|
type storage.buckettype DEFAULT 'VECTOR'::storage.buckettype NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: iceberg_namespaces; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.iceberg_namespaces (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
bucket_name text NOT NULL,
|
|
name text NOT NULL COLLATE pg_catalog."C",
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
metadata jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
catalog_id uuid NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: iceberg_tables; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.iceberg_tables (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
namespace_id uuid NOT NULL,
|
|
bucket_name text NOT NULL,
|
|
name text NOT NULL COLLATE pg_catalog."C",
|
|
location text NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
remote_table_id text,
|
|
shard_key text,
|
|
shard_id text,
|
|
catalog_id uuid NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: migrations; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.migrations (
|
|
id integer NOT NULL,
|
|
name character varying(100) NOT NULL,
|
|
hash character varying(40) NOT NULL,
|
|
executed_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: objects; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.objects (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
bucket_id text,
|
|
name text,
|
|
owner uuid,
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now(),
|
|
last_accessed_at timestamp with time zone DEFAULT now(),
|
|
metadata jsonb,
|
|
path_tokens text[] GENERATED ALWAYS AS (string_to_array(name, '/'::text)) STORED,
|
|
version text,
|
|
owner_id text,
|
|
user_metadata jsonb
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: COLUMN objects.owner; Type: COMMENT; Schema: storage; Owner: -
|
|
--
|
|
|
|
COMMENT ON COLUMN storage.objects.owner IS 'Field is deprecated, use owner_id instead';
|
|
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.s3_multipart_uploads (
|
|
id text NOT NULL,
|
|
in_progress_size bigint DEFAULT 0 NOT NULL,
|
|
upload_signature text NOT NULL,
|
|
bucket_id text NOT NULL,
|
|
key text NOT NULL COLLATE pg_catalog."C",
|
|
version text NOT NULL,
|
|
owner_id text,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
user_metadata jsonb
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads_parts; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.s3_multipart_uploads_parts (
|
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
upload_id text NOT NULL,
|
|
size bigint DEFAULT 0 NOT NULL,
|
|
part_number integer NOT NULL,
|
|
bucket_id text NOT NULL,
|
|
key text NOT NULL COLLATE pg_catalog."C",
|
|
etag text NOT NULL,
|
|
owner_id text,
|
|
version text NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: vector_indexes; Type: TABLE; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TABLE storage.vector_indexes (
|
|
id text DEFAULT gen_random_uuid() NOT NULL,
|
|
name text NOT NULL COLLATE pg_catalog."C",
|
|
bucket_id text NOT NULL,
|
|
data_type text NOT NULL,
|
|
dimension integer NOT NULL,
|
|
distance_metric text NOT NULL,
|
|
metadata_configuration jsonb,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: hooks; Type: TABLE; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
CREATE TABLE supabase_functions.hooks (
|
|
id bigint NOT NULL,
|
|
hook_table_id integer NOT NULL,
|
|
hook_name text NOT NULL,
|
|
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
request_id bigint
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: TABLE hooks; Type: COMMENT; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
COMMENT ON TABLE supabase_functions.hooks IS 'Supabase Functions Hooks: Audit trail for triggered hooks.';
|
|
|
|
|
|
--
|
|
-- Name: hooks_id_seq; Type: SEQUENCE; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
CREATE SEQUENCE supabase_functions.hooks_id_seq
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
|
|
--
|
|
-- Name: hooks_id_seq; Type: SEQUENCE OWNED BY; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
ALTER SEQUENCE supabase_functions.hooks_id_seq OWNED BY supabase_functions.hooks.id;
|
|
|
|
|
|
--
|
|
-- Name: migrations; Type: TABLE; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
CREATE TABLE supabase_functions.migrations (
|
|
version text NOT NULL,
|
|
inserted_at timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_20; Type: TABLE ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_03_20 FOR VALUES FROM ('2026-03-20 00:00:00') TO ('2026-03-21 00:00:00');
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_21; Type: TABLE ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_03_21 FOR VALUES FROM ('2026-03-21 00:00:00') TO ('2026-03-22 00:00:00');
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_22; Type: TABLE ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_03_22 FOR VALUES FROM ('2026-03-22 00:00:00') TO ('2026-03-23 00:00:00');
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_23; Type: TABLE ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_03_23 FOR VALUES FROM ('2026-03-23 00:00:00') TO ('2026-03-24 00:00:00');
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_24; Type: TABLE ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_03_24 FOR VALUES FROM ('2026-03-24 00:00:00') TO ('2026-03-25 00:00:00');
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_25; Type: TABLE ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_03_25 FOR VALUES FROM ('2026-03-25 00:00:00') TO ('2026-03-26 00:00:00');
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_26; Type: TABLE ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_03_26 FOR VALUES FROM ('2026-03-26 00:00:00') TO ('2026-03-27 00:00:00');
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens id; Type: DEFAULT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.refresh_tokens ALTER COLUMN id SET DEFAULT nextval('auth.refresh_tokens_id_seq'::regclass);
|
|
|
|
|
|
--
|
|
-- Name: _db_migrations id; Type: DEFAULT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public._db_migrations ALTER COLUMN id SET DEFAULT nextval('public._db_migrations_id_seq'::regclass);
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots id; Type: DEFAULT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_online_slots ALTER COLUMN id SET DEFAULT nextval('public.agenda_online_slots_id_seq'::regclass);
|
|
|
|
|
|
--
|
|
-- Name: hooks id; Type: DEFAULT; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY supabase_functions.hooks ALTER COLUMN id SET DEFAULT nextval('supabase_functions.hooks_id_seq'::regclass);
|
|
|
|
|
|
--
|
|
-- Data for Name: extensions; Type: TABLE DATA; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
COPY _realtime.extensions (id, type, settings, tenant_external_id, inserted_at, updated_at) FROM stdin;
|
|
9213a133-aa56-4098-88f7-953f17ea8e1c postgres_cdc_rls {"region": "us-east-1", "db_host": "jojNM5epTA6mHrc9dSyLoHNyb6lzYaXqj0adu+DMEsk9UXGm67BsSlbKWPaH8DuL", "db_name": "sWBpZNdjggEPTQVlI52Zfw==", "db_port": "+enMDFi1J/3IrrquHHwUmA==", "db_user": "uxbEq/zz8DXVD53TOI1zmw==", "slot_name": "supabase_realtime_replication_slot", "db_password": "sWBpZNdjggEPTQVlI52Zfw==", "publication": "supabase_realtime", "ssl_enforced": false, "poll_interval_ms": 100, "poll_max_changes": 100, "poll_max_record_bytes": 1048576} realtime-dev 2026-03-23 10:13:39 2026-03-23 10:13:39
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: schema_migrations; Type: TABLE DATA; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
COPY _realtime.schema_migrations (version, inserted_at) FROM stdin;
|
|
20210706140551 2026-03-23 10:13:14
|
|
20220329161857 2026-03-23 10:13:14
|
|
20220410212326 2026-03-23 10:13:14
|
|
20220506102948 2026-03-23 10:13:14
|
|
20220527210857 2026-03-23 10:13:14
|
|
20220815211129 2026-03-23 10:13:14
|
|
20220815215024 2026-03-23 10:13:14
|
|
20220818141501 2026-03-23 10:13:14
|
|
20221018173709 2026-03-23 10:13:14
|
|
20221102172703 2026-03-23 10:13:14
|
|
20221223010058 2026-03-23 10:13:14
|
|
20230110180046 2026-03-23 10:13:14
|
|
20230810220907 2026-03-23 10:13:14
|
|
20230810220924 2026-03-23 10:13:14
|
|
20231024094642 2026-03-23 10:13:14
|
|
20240306114423 2026-03-23 10:13:14
|
|
20240418082835 2026-03-23 10:13:14
|
|
20240625211759 2026-03-23 10:13:14
|
|
20240704172020 2026-03-23 10:13:14
|
|
20240902173232 2026-03-23 10:13:14
|
|
20241106103258 2026-03-23 10:13:14
|
|
20250424203323 2026-03-23 10:13:14
|
|
20250613072131 2026-03-23 10:13:14
|
|
20250711044927 2026-03-23 10:13:14
|
|
20250811121559 2026-03-23 10:13:14
|
|
20250926223044 2026-03-23 10:13:14
|
|
20251204170944 2026-03-23 10:13:14
|
|
20251218000543 2026-03-23 10:13:14
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: tenants; Type: TABLE DATA; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
COPY _realtime.tenants (id, name, external_id, jwt_secret, max_concurrent_users, inserted_at, updated_at, max_events_per_second, postgres_cdc_default, max_bytes_per_second, max_channels_per_client, max_joins_per_second, suspend, jwt_jwks, notify_private_alpha, private_only, migrations_ran, broadcast_adapter, max_presence_events_per_second, max_payload_size_in_kb) FROM stdin;
|
|
4351d01f-9b11-4cea-b9fb-220f6fb88d72 realtime-dev realtime-dev iNjicxc4+llvc9wovDvqymwfnj9teWMlyOIbJ8Fh6j2WNU8CIJ2ZgjR6MUIKqSmeDmvpsKLsZ9jgXJmQPpwL8w== 200 2026-03-23 10:13:39 2026-03-23 10:13:39 100 postgres_cdc_rls 100000 100 100 f {"keys": [{"x": "M5Sjqn5zwC9Kl1zVfUUGvv9boQjCGd45G8sdopBExB4", "y": "P6IXMvA2WYXSHSOMTBH2jsw_9rrzGy89FjPf6oOsIxQ", "alg": "ES256", "crv": "P-256", "ext": true, "kid": "b81269f1-21d8-4f2e-b719-c2240a840d90", "kty": "EC", "use": "sig", "key_ops": ["verify"]}, {"k": "c3VwZXItc2VjcmV0LWp3dC10b2tlbi13aXRoLWF0LWxlYXN0LTMyLWNoYXJhY3RlcnMtbG9uZw", "kty": "oct"}]} f f 65 gen_rpc 1000 3000
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: audit_log_entries; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.audit_log_entries (instance_id, id, payload, created_at, ip_address) FROM stdin;
|
|
00000000-0000-0000-0000-000000000000 f3a9bb5c-a48b-48da-83b0-5e5f71cc1278 {"action":"login","actor_id":"aaaaaaaa-0002-0002-0002-000000000002","actor_username":"terapeuta@agenciapsi.com.br","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}} 2026-03-23 10:58:23.661651+00
|
|
00000000-0000-0000-0000-000000000000 015ae6c3-f000-49f5-a05a-7e43256a5ead {"action":"logout","actor_id":"aaaaaaaa-0002-0002-0002-000000000002","actor_username":"terapeuta@agenciapsi.com.br","actor_via_sso":false,"log_type":"account"} 2026-03-23 10:59:13.173068+00
|
|
00000000-0000-0000-0000-000000000000 2222f6e6-4a78-4c44-88cf-65b677a0bdb6 {"action":"login","actor_id":"aaaaaaaa-0006-0006-0006-000000000006","actor_username":"saas@agenciapsi.com.br","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}} 2026-03-23 10:59:17.817071+00
|
|
00000000-0000-0000-0000-000000000000 12c8d5f5-46f0-4e67-96d2-7722167c7b3c {"action":"logout","actor_id":"aaaaaaaa-0006-0006-0006-000000000006","actor_username":"saas@agenciapsi.com.br","actor_via_sso":false,"log_type":"account"} 2026-03-23 11:30:05.361177+00
|
|
00000000-0000-0000-0000-000000000000 4aa98446-9aa8-4442-985a-aae3fbd28cd2 {"action":"login","actor_id":"aaaaaaaa-0002-0002-0002-000000000002","actor_username":"terapeuta@agenciapsi.com.br","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}} 2026-03-23 11:30:08.832248+00
|
|
00000000-0000-0000-0000-000000000000 4e5e241b-0ba7-4772-a492-5dce48836688 {"action":"token_refreshed","actor_id":"aaaaaaaa-0002-0002-0002-000000000002","actor_username":"terapeuta@agenciapsi.com.br","actor_via_sso":false,"log_type":"token"} 2026-03-23 12:28:24.672784+00
|
|
00000000-0000-0000-0000-000000000000 12c376a9-7e40-4701-b163-173b66bbcc05 {"action":"token_revoked","actor_id":"aaaaaaaa-0002-0002-0002-000000000002","actor_username":"terapeuta@agenciapsi.com.br","actor_via_sso":false,"log_type":"token"} 2026-03-23 12:28:24.674266+00
|
|
00000000-0000-0000-0000-000000000000 54e723ec-3977-4d92-8595-ce7ab53dbd86 {"action":"token_refreshed","actor_id":"aaaaaaaa-0002-0002-0002-000000000002","actor_username":"terapeuta@agenciapsi.com.br","actor_via_sso":false,"log_type":"token"} 2026-03-23 13:30:01.59908+00
|
|
00000000-0000-0000-0000-000000000000 de3c62a2-5771-4cb3-8bc5-a0f2c5cdf7bd {"action":"token_revoked","actor_id":"aaaaaaaa-0002-0002-0002-000000000002","actor_username":"terapeuta@agenciapsi.com.br","actor_via_sso":false,"log_type":"token"} 2026-03-23 13:30:01.600518+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: flow_state; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.flow_state (id, user_id, auth_code, code_challenge_method, code_challenge, provider_type, provider_access_token, provider_refresh_token, created_at, updated_at, authentication_method, auth_code_issued_at, invite_token, referrer, oauth_client_state_id, linking_target_id, email_optional) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: identities; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.identities (provider_id, user_id, identity_data, provider, last_sign_in_at, created_at, updated_at, id) FROM stdin;
|
|
paciente@agenciapsi.com.br aaaaaaaa-0001-0001-0001-000000000001 {"sub": "aaaaaaaa-0001-0001-0001-000000000001", "email": "paciente@agenciapsi.com.br", "email_verified": true} email 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 977a296d-b7ac-4151-8017-3099808e1f7f
|
|
terapeuta@agenciapsi.com.br aaaaaaaa-0002-0002-0002-000000000002 {"sub": "aaaaaaaa-0002-0002-0002-000000000002", "email": "terapeuta@agenciapsi.com.br", "email_verified": true} email 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 44ccd811-6c51-48e9-81a8-77247022c693
|
|
clinica1@agenciapsi.com.br aaaaaaaa-0003-0003-0003-000000000003 {"sub": "aaaaaaaa-0003-0003-0003-000000000003", "email": "clinica1@agenciapsi.com.br", "email_verified": true} email 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 433175a2-4065-47ab-96dd-32508c9a7389
|
|
clinica2@agenciapsi.com.br aaaaaaaa-0004-0004-0004-000000000004 {"sub": "aaaaaaaa-0004-0004-0004-000000000004", "email": "clinica2@agenciapsi.com.br", "email_verified": true} email 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 390305dc-1f61-44e8-9c95-bd9de9591e5a
|
|
clinica3@agenciapsi.com.br aaaaaaaa-0005-0005-0005-000000000005 {"sub": "aaaaaaaa-0005-0005-0005-000000000005", "email": "clinica3@agenciapsi.com.br", "email_verified": true} email 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 f669ef52-181e-44d5-8649-833d6b133313
|
|
saas@agenciapsi.com.br aaaaaaaa-0006-0006-0006-000000000006 {"sub": "aaaaaaaa-0006-0006-0006-000000000006", "email": "saas@agenciapsi.com.br", "email_verified": true} email 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 e6af6a5e-55ce-4872-a745-40d688d08982
|
|
supervisor@agenciapsi.com.br aaaaaaaa-0007-0007-0007-000000000007 {"sub": "aaaaaaaa-0007-0007-0007-000000000007", "email": "supervisor@agenciapsi.com.br", "email_verified": true} email 2026-03-23 14:18:05.215881+00 2026-03-23 14:18:05.215881+00 2026-03-23 14:18:05.215881+00 8dff38d2-1b09-4b88-9038-28b747358645
|
|
editor@agenciapsi.com.br aaaaaaaa-0008-0008-0008-000000000008 {"sub": "aaaaaaaa-0008-0008-0008-000000000008", "email": "editor@agenciapsi.com.br", "email_verified": true} email 2026-03-23 14:18:05.215881+00 2026-03-23 14:18:05.215881+00 2026-03-23 14:18:05.215881+00 a7856eb7-e96f-4752-84a3-b676503b74ae
|
|
therapist2@agenciapsi.com.br aaaaaaaa-0009-0009-0009-000000000009 {"sub": "aaaaaaaa-0009-0009-0009-000000000009", "email": "therapist2@agenciapsi.com.br", "email_verified": true} email 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 8129cc38-db24-4f84-b48e-bf0b46235811
|
|
therapist3@agenciapsi.com.br aaaaaaaa-0010-0010-0010-000000000010 {"sub": "aaaaaaaa-0010-0010-0010-000000000010", "email": "therapist3@agenciapsi.com.br", "email_verified": true} email 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 754b015d-3c88-4104-b246-eede6fffabba
|
|
secretary@agenciapsi.com.br aaaaaaaa-0011-0011-0011-000000000011 {"sub": "aaaaaaaa-0011-0011-0011-000000000011", "email": "secretary@agenciapsi.com.br", "email_verified": true} email 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 a7aa272b-659f-4bc7-8667-10cf49200410
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: instances; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.instances (id, uuid, raw_base_config, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: mfa_amr_claims; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.mfa_amr_claims (session_id, created_at, updated_at, authentication_method, id) FROM stdin;
|
|
d545b1ef-1cd2-4b5d-8c10-5aaa55b73347 2026-03-23 11:30:08.845745+00 2026-03-23 11:30:08.845745+00 password 6fc54c9d-9ad4-478d-a526-d69f1468151d
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: mfa_challenges; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.mfa_challenges (id, factor_id, created_at, verified_at, ip_address, otp_code, web_authn_session_data) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: mfa_factors; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.mfa_factors (id, user_id, friendly_name, factor_type, status, created_at, updated_at, secret, phone, last_challenged_at, web_authn_credential, web_authn_aaguid, last_webauthn_challenge_data) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: oauth_authorizations; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.oauth_authorizations (id, authorization_id, client_id, user_id, redirect_uri, scope, state, resource, code_challenge, code_challenge_method, response_type, status, authorization_code, created_at, expires_at, approved_at, nonce) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: oauth_client_states; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.oauth_client_states (id, provider_type, code_verifier, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: oauth_clients; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.oauth_clients (id, client_secret_hash, registration_type, redirect_uris, grant_types, client_name, client_uri, logo_uri, created_at, updated_at, deleted_at, client_type, token_endpoint_auth_method) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: oauth_consents; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.oauth_consents (id, user_id, client_id, scopes, granted_at, revoked_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: one_time_tokens; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.one_time_tokens (id, user_id, token_type, token_hash, relates_to, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: refresh_tokens; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.refresh_tokens (instance_id, id, token, user_id, revoked, created_at, updated_at, parent, session_id) FROM stdin;
|
|
00000000-0000-0000-0000-000000000000 3 oghbb2rkjyup aaaaaaaa-0002-0002-0002-000000000002 t 2026-03-23 11:30:08.84168+00 2026-03-23 12:28:24.675183+00 \N d545b1ef-1cd2-4b5d-8c10-5aaa55b73347
|
|
00000000-0000-0000-0000-000000000000 4 jnzyuofg2p7m aaaaaaaa-0002-0002-0002-000000000002 t 2026-03-23 12:28:24.676374+00 2026-03-23 13:30:01.601437+00 oghbb2rkjyup d545b1ef-1cd2-4b5d-8c10-5aaa55b73347
|
|
00000000-0000-0000-0000-000000000000 5 nkklcrhwvr3v aaaaaaaa-0002-0002-0002-000000000002 f 2026-03-23 13:30:01.602593+00 2026-03-23 13:30:01.602593+00 jnzyuofg2p7m d545b1ef-1cd2-4b5d-8c10-5aaa55b73347
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: saml_providers; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.saml_providers (id, sso_provider_id, entity_id, metadata_xml, metadata_url, attribute_mapping, created_at, updated_at, name_id_format) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: saml_relay_states; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.saml_relay_states (id, sso_provider_id, request_id, for_email, redirect_to, created_at, updated_at, flow_state_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: schema_migrations; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.schema_migrations (version) FROM stdin;
|
|
20171026211738
|
|
20171026211808
|
|
20171026211834
|
|
20180103212743
|
|
20180108183307
|
|
20180119214651
|
|
20180125194653
|
|
00
|
|
20210710035447
|
|
20210722035447
|
|
20210730183235
|
|
20210909172000
|
|
20210927181326
|
|
20211122151130
|
|
20211124214934
|
|
20211202183645
|
|
20220114185221
|
|
20220114185340
|
|
20220224000811
|
|
20220323170000
|
|
20220429102000
|
|
20220531120530
|
|
20220614074223
|
|
20220811173540
|
|
20221003041349
|
|
20221003041400
|
|
20221011041400
|
|
20221020193600
|
|
20221021073300
|
|
20221021082433
|
|
20221027105023
|
|
20221114143122
|
|
20221114143410
|
|
20221125140132
|
|
20221208132122
|
|
20221215195500
|
|
20221215195800
|
|
20221215195900
|
|
20230116124310
|
|
20230116124412
|
|
20230131181311
|
|
20230322519590
|
|
20230402418590
|
|
20230411005111
|
|
20230508135423
|
|
20230523124323
|
|
20230818113222
|
|
20230914180801
|
|
20231027141322
|
|
20231114161723
|
|
20231117164230
|
|
20240115144230
|
|
20240214120130
|
|
20240306115329
|
|
20240314092811
|
|
20240427152123
|
|
20240612123726
|
|
20240729123726
|
|
20240802193726
|
|
20240806073726
|
|
20241009103726
|
|
20250717082212
|
|
20250731150234
|
|
20250804100000
|
|
20250901200500
|
|
20250903112500
|
|
20250904133000
|
|
20250925093508
|
|
20251007112900
|
|
20251104100000
|
|
20251111201300
|
|
20251201000000
|
|
20260115000000
|
|
20260121000000
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: sessions; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.sessions (id, user_id, created_at, updated_at, factor_id, aal, not_after, refreshed_at, user_agent, ip, tag, oauth_client_id, refresh_token_hmac_key, refresh_token_counter, scopes) FROM stdin;
|
|
d545b1ef-1cd2-4b5d-8c10-5aaa55b73347 aaaaaaaa-0002-0002-0002-000000000002 2026-03-23 11:30:08.834336+00 2026-03-23 13:30:01.610731+00 \N aal1 \N 2026-03-23 13:30:01.610654 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 172.19.0.1 \N \N \N \N \N
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: sso_domains; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.sso_domains (id, sso_provider_id, domain, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: sso_providers; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.sso_providers (id, resource_id, created_at, updated_at, disabled) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: users; Type: TABLE DATA; Schema: auth; Owner: -
|
|
--
|
|
|
|
COPY auth.users (instance_id, id, aud, role, email, encrypted_password, email_confirmed_at, invited_at, confirmation_token, confirmation_sent_at, recovery_token, recovery_sent_at, email_change_token_new, email_change, email_change_sent_at, last_sign_in_at, raw_app_meta_data, raw_user_meta_data, is_super_admin, created_at, updated_at, phone, phone_confirmed_at, phone_change, phone_change_token, phone_change_sent_at, email_change_token_current, email_change_confirm_status, banned_until, reauthentication_token, reauthentication_sent_at, is_sso_user, deleted_at, is_anonymous) FROM stdin;
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0001-0001-0001-000000000001 authenticated authenticated paciente@agenciapsi.com.br $2a$06$ipEc7puaVhQnpusOGhAYgOcrVHq4RnqZeDooS8FaehzHhueScf9S. 2026-03-23 10:46:29.876072+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Ana Paciente"} \N 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0005-0005-0005-000000000005 authenticated authenticated clinica3@agenciapsi.com.br $2a$06$L3aFykCSdduzTHEKsEQ3q.GdHTb5EJBvbIit4k7ZgnbRd5BCGuTxu 2026-03-23 10:46:29.876072+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Clínica Bem Estar"} \N 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0006-0006-0006-000000000006 authenticated authenticated saas@agenciapsi.com.br $2a$06$QsvWGUd7HQTv6kSQDbRsiOkNcLM4O2BnQflXPbx3MK9E4RPGz5FvS 2026-03-23 10:46:29.876072+00 \N \N \N \N 2026-03-23 10:59:17.829375+00 {"provider": "email", "providers": ["email"]} {"name": "Admin Plataforma"} \N 2026-03-23 10:46:29.876072+00 2026-03-23 10:59:17.835203+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0011-0011-0011-000000000011 authenticated authenticated secretary@agenciapsi.com.br $2a$06$O7HeygRYgJViriMFCImLZu7DD.3A9wZWb9y3c5G2PIURgJ65UnqT. 2026-03-23 14:18:06.087973+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Gabriela Secretária"} \N 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0002-0002-0002-000000000002 authenticated authenticated terapeuta@agenciapsi.com.br $2a$06$CztXijQkaPZa6pUwXmMHWuzSF19GiVtRBdMLp.k4iWf7ftGWNBIg6 2026-03-23 10:46:29.876072+00 \N \N \N \N 2026-03-23 11:30:08.834253+00 {"provider": "email", "providers": ["email"]} {"name": "Bruno Terapeuta"} \N 2026-03-23 10:46:29.876072+00 2026-03-23 13:30:01.604245+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0007-0007-0007-000000000007 authenticated authenticated supervisor@agenciapsi.com.br $2a$06$.kF47/tagPNwSpgGM4ryZOu01L0ykU2IXakM8trZ.Hon1TTUDeqYK 2026-03-23 14:18:05.215881+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Carlos Supervisor"} \N 2026-03-23 14:18:05.215881+00 2026-03-23 14:18:05.215881+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0008-0008-0008-000000000008 authenticated authenticated editor@agenciapsi.com.br $2a$06$lcF3sQOKaQOMwo5OTPPpcODcMtjDoUpHw3rOBhJMYow15LoJFLvH6 2026-03-23 14:18:05.215881+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Diana Editora"} \N 2026-03-23 14:18:05.215881+00 2026-03-23 14:18:05.215881+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0009-0009-0009-000000000009 authenticated authenticated therapist2@agenciapsi.com.br $2a$06$16hf/nUbN0lElm9l8vQI4ek8vIM2T8ymiJTQ8CHXXw/jD1gMuDFJS 2026-03-23 14:18:06.087973+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Eva Terapeuta"} \N 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0010-0010-0010-000000000010 authenticated authenticated therapist3@agenciapsi.com.br $2a$06$sBJPPHRI/MsrCTEeCK5/vOhASc/SNLeO.B/QEE2MZNWEP8FamyCXW 2026-03-23 14:18:06.087973+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Felipe Terapeuta"} \N 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0003-0003-0003-000000000003 authenticated authenticated clinica1@agenciapsi.com.br $2a$06$cxZ2uXWIOS9MgzoyzSla8Oocid6wKtEBPA4k9QyC8DvwzmOsI0co2 2026-03-23 10:46:29.876072+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Clínica Espaço Psi"} \N 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N \N 0 \N \N f \N f
|
|
00000000-0000-0000-0000-000000000000 aaaaaaaa-0004-0004-0004-000000000004 authenticated authenticated clinica2@agenciapsi.com.br $2a$06$ZSW6FPPCmhO8EkfSM4/QLu/J32HRe/87zoNLvPtCbqTdNBbanaLPi 2026-03-23 10:46:29.876072+00 \N \N \N \N \N {"provider": "email", "providers": ["email"]} {"name": "Clínica Mente Sã"} \N 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N \N 0 \N \N f \N f
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: job; Type: TABLE DATA; Schema: cron; Owner: -
|
|
--
|
|
|
|
COPY cron.job (jobid, schedule, command, nodename, nodeport, database, username, active, jobname) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: job_run_details; Type: TABLE DATA; Schema: cron; Owner: -
|
|
--
|
|
|
|
COPY cron.job_run_details (jobid, runid, job_pid, database, username, command, status, return_message, start_time, end_time) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: _db_migrations; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public._db_migrations (id, filename, hash, category, applied_at) FROM stdin;
|
|
1 seed_001_fixed.sql 87fc24517f6446f7 seed 2026-03-23 14:15:02.14603+00
|
|
2 seed_002.sql b05d565b35c97300 seed 2026-03-23 14:15:02.45035+00
|
|
3 seed_003.sql 257ef8bba4e319a2 seed 2026-03-23 14:15:02.755322+00
|
|
4 seed_010_plans.sql 0de612f2301e27d3 seed 2026-03-23 14:15:02.974622+00
|
|
5 seed_011_features.sql e7326ac0e33e4fee seed 2026-03-23 14:15:03.261589+00
|
|
6 seed_012_plan_features.sql f0e1b4ab684383f7 seed 2026-03-23 14:15:03.553899+00
|
|
7 seed_013_subscriptions.sql b61e4af59262f3ac seed 2026-03-23 14:15:03.816997+00
|
|
8 seed_014_global_data.sql a7bc086bc6f052ee seed 2026-03-23 14:15:04.080095+00
|
|
9 fix_addon_credits_fk.sql aaff13facb98e4d8 fix 2026-03-23 14:15:04.372331+00
|
|
10 fix_addon_rls_saas_admin.sql 84d85284eb441afc fix 2026-03-23 14:15:04.630692+00
|
|
11 fix_missing_subscriptions.sql f5740f6eef9e5405 fix 2026-03-23 14:15:04.916745+00
|
|
12 fix_notification_templates_rls_admin.sql ede371cbce54e13e fix 2026-03-23 14:15:05.15764+00
|
|
13 fix_seed_patient_groups.sql e9b870ba0ad5f359 fix 2026-03-23 14:15:05.485322+00
|
|
14 fix_subscriptions_validate_scope.sql c814a90d768d339c fix 2026-03-23 14:15:06.461275+00
|
|
15 fix_template_keys_match_populate.sql e0fdd2a420abaeb8 fix 2026-03-23 14:15:06.977464+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: addon_credits; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.addon_credits (id, tenant_id, owner_id, addon_type, balance, total_purchased, total_consumed, low_balance_threshold, low_balance_notified, daily_limit, hourly_limit, daily_used, hourly_used, daily_reset_at, hourly_reset_at, from_number_override, expires_at, is_active, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: addon_products; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.addon_products (id, slug, name, description, addon_type, icon, credits_amount, price_cents, currency, is_active, is_visible, sort_order, metadata, created_at, updated_at, deleted_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: addon_transactions; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.addon_transactions (id, tenant_id, owner_id, addon_type, type, amount, balance_before, balance_after, product_id, queue_id, description, admin_user_id, payment_method, payment_reference, price_cents, currency, created_at, metadata) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agenda_bloqueios; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agenda_bloqueios (id, owner_id, tenant_id, tipo, titulo, data_inicio, data_fim, hora_inicio, hora_fim, recorrente, dia_semana, observacao, origem, created_at) FROM stdin;
|
|
f809fcb6-0369-42fd-985a-5d9976798e88 aaaaaaaa-0002-0002-0002-000000000002 bbbbbbbb-0002-0002-0002-000000000002 bloqueio Feriado: Sexta-feira Santa 2026-04-03 2026-04-03 \N \N f \N \N agenda_feriado 2026-03-23 11:32:18.225845+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agenda_configuracoes; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agenda_configuracoes (owner_id, duracao_padrao_minutos, intervalo_padrao_minutos, timezone, usar_horario_admin_custom, admin_inicio_visualizacao, admin_fim_visualizacao, admin_slot_visual_minutos, online_ativo, online_min_antecedencia_horas, online_max_dias_futuro, online_cancelar_ate_horas, online_reagendar_ate_horas, online_limite_agendamentos_futuros, online_modo, online_buffer_antes_min, online_buffer_depois_min, online_modalidade, created_at, updated_at, usar_granularidade_custom, granularidade_min, setup_concluido, setup_concluido_em, agenda_view_mode, agenda_custom_start, agenda_custom_end, session_duration_min, session_break_min, pausas_semanais, setup_clinica_concluido, setup_clinica_concluido_em, tenant_id, jornada_igual_todos, slot_mode) FROM stdin;
|
|
aaaaaaaa-0002-0002-0002-000000000002 50 0 America/Sao_Paulo f \N \N 30 f 24 60 12 12 1 automatico 0 0 ambos 2026-03-23 10:58:31.422764+00 2026-03-23 11:32:02.551544+00 f \N t 2026-03-23 11:32:02.465+00 full_24h \N \N 50 10 [{"id": "64aae49bb44ef819d1a76b459", "fim": "13:00", "label": "Almoço", "inicio": "12:00", "dia_semana": 0}, {"id": "64aae49bb44ef819d1a76b459", "fim": "13:00", "label": "Almoço", "inicio": "12:00", "dia_semana": 1}, {"id": "64aae49bb44ef819d1a76b459", "fim": "13:00", "label": "Almoço", "inicio": "12:00", "dia_semana": 2}, {"id": "64aae49bb44ef819d1a76b459", "fim": "13:00", "label": "Almoço", "inicio": "12:00", "dia_semana": 3}, {"id": "64aae49bb44ef819d1a76b459", "fim": "13:00", "label": "Almoço", "inicio": "12:00", "dia_semana": 4}, {"id": "64aae49bb44ef819d1a76b459", "fim": "13:00", "label": "Almoço", "inicio": "12:00", "dia_semana": 5}] f \N bbbbbbbb-0002-0002-0002-000000000002 t fixed
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agenda_eventos; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agenda_eventos (id, owner_id, tipo, status, titulo, observacoes, inicio_em, fim_em, created_at, updated_at, terapeuta_id, tenant_id, visibility_scope, mirror_of_event_id, mirror_source, patient_id, determined_commitment_id, link_online, titulo_custom, extra_fields, recurrence_id, recurrence_date, modalidade, price, billing_contract_id, billed, services_customized, insurance_plan_id, insurance_guide_number, insurance_value, insurance_plan_service_id) FROM stdin;
|
|
dbf6b44e-24f1-4cd2-86f5-a594fa39f9d3 aaaaaaaa-0002-0002-0002-000000000002 sessao agendado Otto Rank [Sess??o] \N 2026-03-23 13:00:00+00 2026-03-23 13:50:00+00 2026-03-23 11:33:08.0471+00 2026-03-23 11:33:08.0471+00 \N bbbbbbbb-0002-0002-0002-000000000002 public \N \N 6449e64b-050b-419f-8845-029b6f10a17d 42a8c681-8b32-4608-870f-b617acbe249e \N \N \N \N \N presencial 0.00 \N f f \N \N \N \N
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agenda_excecoes; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agenda_excecoes (id, owner_id, data, hora_inicio, hora_fim, tipo, motivo, created_at, updated_at, status, fonte, aplicavel_online, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agenda_online_slots; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agenda_online_slots (id, owner_id, weekday, "time", enabled, created_at, updated_at, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agenda_regras_semanais; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agenda_regras_semanais (id, owner_id, dia_semana, hora_inicio, hora_fim, modalidade, ativo, created_at, updated_at, tenant_id) FROM stdin;
|
|
a3212bcd-fc80-40c3-b3ea-92d31d1d051a aaaaaaaa-0002-0002-0002-000000000002 0 08:00:00 18:00:00 ambos t 2026-03-23 11:31:24.019622+00 2026-03-23 11:31:24.019622+00 bbbbbbbb-0002-0002-0002-000000000002
|
|
cbeae6bd-1ebd-494d-b5c0-2f3a8bf09e14 aaaaaaaa-0002-0002-0002-000000000002 1 08:00:00 18:00:00 ambos t 2026-03-23 11:31:24.019622+00 2026-03-23 11:31:24.019622+00 bbbbbbbb-0002-0002-0002-000000000002
|
|
dd9ecded-d82c-4d87-a2df-85b89c331001 aaaaaaaa-0002-0002-0002-000000000002 2 08:00:00 18:00:00 ambos t 2026-03-23 11:31:24.019622+00 2026-03-23 11:31:24.019622+00 bbbbbbbb-0002-0002-0002-000000000002
|
|
ce5054c2-f382-4135-8365-06b3dab7ea1c aaaaaaaa-0002-0002-0002-000000000002 3 08:00:00 18:00:00 ambos t 2026-03-23 11:31:24.019622+00 2026-03-23 11:31:24.019622+00 bbbbbbbb-0002-0002-0002-000000000002
|
|
e8e22a8d-4deb-4eeb-a9e8-e1f906030499 aaaaaaaa-0002-0002-0002-000000000002 4 08:00:00 18:00:00 ambos t 2026-03-23 11:31:24.019622+00 2026-03-23 11:31:24.019622+00 bbbbbbbb-0002-0002-0002-000000000002
|
|
265ff3ab-645f-4dd6-8a91-4a3a4d085ff0 aaaaaaaa-0002-0002-0002-000000000002 5 08:00:00 18:00:00 ambos t 2026-03-23 11:31:24.019622+00 2026-03-23 11:31:24.019622+00 bbbbbbbb-0002-0002-0002-000000000002
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agenda_slots_bloqueados_semanais; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agenda_slots_bloqueados_semanais (id, owner_id, dia_semana, hora_inicio, motivo, ativo, created_at, updated_at, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agenda_slots_regras; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agenda_slots_regras (id, owner_id, dia_semana, passo_minutos, offset_minutos, buffer_antes_min, buffer_depois_min, min_antecedencia_horas, ativo, created_at, updated_at, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agendador_configuracoes; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agendador_configuracoes (owner_id, tenant_id, ativo, link_slug, imagem_fundo_url, imagem_header_url, logomarca_url, cor_primaria, nome_exibicao, endereco, botao_como_chegar_ativo, maps_url, modo_aprovacao, modalidade, tipos_habilitados, duracao_sessao_min, antecedencia_minima_horas, prazo_resposta_horas, reserva_horas, pagamento_obrigatorio, pix_chave, pix_countdown_minutos, triagem_motivo, triagem_como_conheceu, verificacao_email, exigir_aceite_lgpd, mensagem_boas_vindas, texto_como_se_preparar, texto_termos_lgpd, created_at, updated_at, pagamento_modo, pagamento_metodos_visiveis) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: agendador_solicitacoes; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.agendador_solicitacoes (id, owner_id, tenant_id, paciente_nome, paciente_sobrenome, paciente_email, paciente_celular, paciente_cpf, tipo, modalidade, data_solicitada, hora_solicitada, reservado_ate, motivo, como_conheceu, pix_status, pix_pago_em, status, recusado_motivo, autorizado_em, autorizado_por, user_id, patient_id, evento_id, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: billing_contracts; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.billing_contracts (id, owner_id, tenant_id, patient_id, type, total_sessions, sessions_used, package_price, amount, billing_interval, active_from, active_to, status, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: commitment_services; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.commitment_services (id, commitment_id, service_id, quantity, unit_price, discount_pct, discount_flat, final_price, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: commitment_time_logs; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.commitment_time_logs (id, tenant_id, commitment_id, calendar_event_id, source, started_at, ended_at, minutes, created_by, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: company_profiles; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.company_profiles (id, tenant_id, nome_fantasia, razao_social, tipo_empresa, cnpj, ie, im, cep, logradouro, numero, complemento, bairro, cidade, estado, email, telefone, site, logo_url, redes_sociais, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: determined_commitment_fields; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.determined_commitment_fields (id, tenant_id, commitment_id, key, label, field_type, required, sort_order, created_at, updated_at) FROM stdin;
|
|
3f45731e-f025-4a95-b37d-35becf557474 bbbbbbbb-0002-0002-0002-000000000002 5944e5d9-622d-4db1-b73d-0083a6a4a9a1 book Livro text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
7cb99c51-3de2-4216-be29-1067d1d2a6e8 bbbbbbbb-0002-0002-0002-000000000002 5944e5d9-622d-4db1-b73d-0083a6a4a9a1 author Autor text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
29a48e4d-b4b9-41e6-8a3f-23e862b11f71 bbbbbbbb-0002-0002-0002-000000000002 5944e5d9-622d-4db1-b73d-0083a6a4a9a1 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
de1bf25c-2c6e-4de1-9be2-9976eb26e9e6 bbbbbbbb-0002-0002-0002-000000000002 717e552c-99cc-4375-b7f2-a1b29f3581e3 supervisor Supervisor text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
0a2f4c96-be82-49a1-b0bc-65d08bf29078 bbbbbbbb-0002-0002-0002-000000000002 717e552c-99cc-4375-b7f2-a1b29f3581e3 topic Assunto text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
ea018b37-ac9a-49a5-93dd-ebc4f2bcc069 bbbbbbbb-0002-0002-0002-000000000002 717e552c-99cc-4375-b7f2-a1b29f3581e3 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
4f4fff30-8b01-46cc-a6c9-25e0c623b03c bbbbbbbb-0002-0002-0002-000000000002 b3bf589d-4a72-429f-b9bd-ba426c3f42f1 theme Tema text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
3ddb7185-eea6-43e4-bab7-686aa996f4e6 bbbbbbbb-0002-0002-0002-000000000002 b3bf589d-4a72-429f-b9bd-ba426c3f42f1 group Turma text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
20c208a1-eae7-4021-916f-a3a45f7d9e84 bbbbbbbb-0002-0002-0002-000000000002 b3bf589d-4a72-429f-b9bd-ba426c3f42f1 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
82c2b726-8de7-4bdd-a7ab-0fe519200f2c bbbbbbbb-0002-0002-0002-000000000002 e19a2e0e-cd6a-4cee-97e0-50a43ea69df1 analyst Analista text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
88bb598e-44f1-4090-a09a-21a11e628ab0 bbbbbbbb-0002-0002-0002-000000000002 e19a2e0e-cd6a-4cee-97e0-50a43ea69df1 focus Foco text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
f0aa7c4c-e26d-42c2-8f90-5e4a87308fe9 bbbbbbbb-0002-0002-0002-000000000002 e19a2e0e-cd6a-4cee-97e0-50a43ea69df1 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
fa8083ef-7e1f-4e00-84b6-6dd197a31e11 bbbbbbbb-0003-0003-0003-000000000003 cd1076b1-0f3d-460e-842f-1585c0ae2a64 book Livro text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
2fea846d-3d7f-4946-8b8a-921756d1375d bbbbbbbb-0003-0003-0003-000000000003 cd1076b1-0f3d-460e-842f-1585c0ae2a64 author Autor text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
7f71d073-7337-40c3-9f2b-80d359ee6825 bbbbbbbb-0003-0003-0003-000000000003 cd1076b1-0f3d-460e-842f-1585c0ae2a64 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
9ea25942-9529-4ffb-99b1-17c8f48fa1b3 bbbbbbbb-0003-0003-0003-000000000003 9ded91f1-1974-4e56-afc6-12b2e8f9456c supervisor Supervisor text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
642ee453-276b-4636-808b-0deed8827416 bbbbbbbb-0003-0003-0003-000000000003 9ded91f1-1974-4e56-afc6-12b2e8f9456c topic Assunto text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
1107588b-dafc-49f0-adf1-1d478410fbab bbbbbbbb-0003-0003-0003-000000000003 9ded91f1-1974-4e56-afc6-12b2e8f9456c notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
2d00519b-2d66-4b66-9471-4edfd7f03152 bbbbbbbb-0003-0003-0003-000000000003 b82819d4-02a1-40c5-bf57-6e2e0425e62d theme Tema text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
6fb9b8f8-0a50-4267-93ff-a154487d0ee2 bbbbbbbb-0003-0003-0003-000000000003 b82819d4-02a1-40c5-bf57-6e2e0425e62d group Turma text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
99d0df7d-20f7-49df-acd8-c359b195348d bbbbbbbb-0003-0003-0003-000000000003 b82819d4-02a1-40c5-bf57-6e2e0425e62d notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
241c3b0f-78c1-4485-9f11-c8fc5fdf6650 bbbbbbbb-0003-0003-0003-000000000003 b5c43dc2-a3a1-40ca-8b75-02ec649fd914 analyst Analista text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
08440a39-027f-4879-8091-7a9b2cf522c1 bbbbbbbb-0003-0003-0003-000000000003 b5c43dc2-a3a1-40ca-8b75-02ec649fd914 focus Foco text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
d11f4029-c46e-42bf-b7aa-bc3b1cc9874a bbbbbbbb-0003-0003-0003-000000000003 b5c43dc2-a3a1-40ca-8b75-02ec649fd914 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
d2d11b9f-5dcf-4355-bc33-c977ac7591a9 bbbbbbbb-0004-0004-0004-000000000004 2e5f4151-e259-4261-8954-e3d196a28383 book Livro text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
2d3e3c6e-6ca0-4170-b9ed-e45e470a8738 bbbbbbbb-0004-0004-0004-000000000004 2e5f4151-e259-4261-8954-e3d196a28383 author Autor text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
a7003c31-46b1-44a2-876e-034f3c61ce8c bbbbbbbb-0004-0004-0004-000000000004 2e5f4151-e259-4261-8954-e3d196a28383 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
29f2cb01-22c2-45c3-ba02-55b908b5ceac bbbbbbbb-0004-0004-0004-000000000004 0d6cb161-8d89-4b18-9323-5631e8cddd8f supervisor Supervisor text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
e0b8f4dd-740c-4162-b988-62fc8216de8c bbbbbbbb-0004-0004-0004-000000000004 0d6cb161-8d89-4b18-9323-5631e8cddd8f topic Assunto text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
187902e7-4497-4ab6-81f7-7dbe177189e9 bbbbbbbb-0004-0004-0004-000000000004 0d6cb161-8d89-4b18-9323-5631e8cddd8f notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
4ef4ac8e-adf4-4034-851f-3767ef37a8e4 bbbbbbbb-0004-0004-0004-000000000004 bec193c2-172b-40ef-a5fe-91b7c44c841e theme Tema text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
4972b76d-c080-4989-a4f8-3d3c57a9b96e bbbbbbbb-0004-0004-0004-000000000004 bec193c2-172b-40ef-a5fe-91b7c44c841e group Turma text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
fc589056-f8b8-4d96-94f0-7ac49ab53059 bbbbbbbb-0004-0004-0004-000000000004 bec193c2-172b-40ef-a5fe-91b7c44c841e notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
4300058b-c0b4-4b86-8f6e-eda6d99553fc bbbbbbbb-0004-0004-0004-000000000004 d11aa6fe-ef08-4610-8a6f-4b472ccd1b64 analyst Analista text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
20add80c-2807-42c9-8c42-40291a49e5df bbbbbbbb-0004-0004-0004-000000000004 d11aa6fe-ef08-4610-8a6f-4b472ccd1b64 focus Foco text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
4d01680a-733e-4c0c-a26a-e19b962fe9fa bbbbbbbb-0004-0004-0004-000000000004 d11aa6fe-ef08-4610-8a6f-4b472ccd1b64 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
e56ad576-c831-444a-bb21-0bcd74630d48 bbbbbbbb-0005-0005-0005-000000000005 793f5b1d-b218-40a3-aa73-3e1440d9ea66 book Livro text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
cc36d270-7961-481f-8a8b-99e0b9ef2e64 bbbbbbbb-0005-0005-0005-000000000005 793f5b1d-b218-40a3-aa73-3e1440d9ea66 author Autor text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
8eb622a4-8ee9-4c34-af09-9dd5c74923fa bbbbbbbb-0005-0005-0005-000000000005 793f5b1d-b218-40a3-aa73-3e1440d9ea66 notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
24d0c58f-3382-4ea8-81e7-3dc32f122b90 bbbbbbbb-0005-0005-0005-000000000005 83666a58-2e53-49a6-8b13-73eeb203e5ba supervisor Supervisor text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
4993e870-d101-4754-b2bc-18205255d643 bbbbbbbb-0005-0005-0005-000000000005 83666a58-2e53-49a6-8b13-73eeb203e5ba topic Assunto text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
b6e403de-e93a-42e0-832a-e6103a935421 bbbbbbbb-0005-0005-0005-000000000005 83666a58-2e53-49a6-8b13-73eeb203e5ba notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
a552127c-1b16-464c-a8f3-d7bdf054b0a9 bbbbbbbb-0005-0005-0005-000000000005 8c1a77a1-b66f-462e-940d-2f60d080149c theme Tema text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
be9ecf92-2dc8-4f62-94f3-223b0165c0af bbbbbbbb-0005-0005-0005-000000000005 8c1a77a1-b66f-462e-940d-2f60d080149c group Turma text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
7f7a9b35-60f1-4192-bf6c-d91ca42813a1 bbbbbbbb-0005-0005-0005-000000000005 8c1a77a1-b66f-462e-940d-2f60d080149c notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
528d426f-23d4-422f-8624-5b4178ce3a8b bbbbbbbb-0005-0005-0005-000000000005 a72b9eb5-747f-4ec3-8bb4-f9c17925e7ad analyst Analista text f 10 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
11a02a30-7a0a-4baf-acdd-2525c2f2cf84 bbbbbbbb-0005-0005-0005-000000000005 a72b9eb5-747f-4ec3-8bb4-f9c17925e7ad focus Foco text f 20 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
f456679b-05d7-4ccc-ae3b-c5f673f8f6f8 bbbbbbbb-0005-0005-0005-000000000005 a72b9eb5-747f-4ec3-8bb4-f9c17925e7ad notes Observa????o textarea f 30 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00
|
|
07ba5c18-9ebb-4b38-bd2f-591b8e4f7f87 bbbbbbbb-0009-0009-0009-000000000009 fc6da673-fd7c-4101-b980-54eb3842804c book Livro text f 10 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
92eec7d8-20f3-46e4-8700-c80e9bd90bcb bbbbbbbb-0009-0009-0009-000000000009 fc6da673-fd7c-4101-b980-54eb3842804c author Autor text f 20 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
fdf6b850-b627-494e-9cb0-d1a044409b3c bbbbbbbb-0009-0009-0009-000000000009 fc6da673-fd7c-4101-b980-54eb3842804c notes Observa????o textarea f 30 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
ef9a9605-9b0f-4671-b056-835c56844cf9 bbbbbbbb-0009-0009-0009-000000000009 3dbb8c2f-6fab-478f-b094-5bc13606a504 supervisor Supervisor text f 10 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
e19f0ad4-fe52-4595-84aa-cf11828a7ecd bbbbbbbb-0009-0009-0009-000000000009 3dbb8c2f-6fab-478f-b094-5bc13606a504 topic Assunto text f 20 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
41a085ac-6849-4e29-8728-79e1a47c1ac5 bbbbbbbb-0009-0009-0009-000000000009 3dbb8c2f-6fab-478f-b094-5bc13606a504 notes Observa????o textarea f 30 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
8fdaad8b-f31c-4510-9b72-7346026103b9 bbbbbbbb-0009-0009-0009-000000000009 4c4a8ced-d109-443b-bc83-817c858f9bb6 theme Tema text f 10 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
9e53f6f5-6770-4f3e-8b0e-cb18c9df54b7 bbbbbbbb-0009-0009-0009-000000000009 4c4a8ced-d109-443b-bc83-817c858f9bb6 group Turma text f 20 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
222021b7-6917-4977-a08f-e19532aa2a0e bbbbbbbb-0009-0009-0009-000000000009 4c4a8ced-d109-443b-bc83-817c858f9bb6 notes Observa????o textarea f 30 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
329eebff-55c4-49e2-87ee-b3d0f418234b bbbbbbbb-0009-0009-0009-000000000009 b180f6e4-39ad-464c-842e-d42dc60cdf13 analyst Analista text f 10 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
e87c45d8-8f5f-476d-811d-5b5b4a764e07 bbbbbbbb-0009-0009-0009-000000000009 b180f6e4-39ad-464c-842e-d42dc60cdf13 focus Foco text f 20 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
2a8c3eff-4eed-4b2d-98e7-50267ebb910e bbbbbbbb-0009-0009-0009-000000000009 b180f6e4-39ad-464c-842e-d42dc60cdf13 notes Observa????o textarea f 30 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
e6109ef3-7409-4268-8ecf-eaff64fa9498 bbbbbbbb-0010-0010-0010-000000000010 fe52a6b2-e86e-47e0-9dc7-9b7e63599cff book Livro text f 10 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
2069cb4c-3c49-4a82-ada1-63082d14bba3 bbbbbbbb-0010-0010-0010-000000000010 fe52a6b2-e86e-47e0-9dc7-9b7e63599cff author Autor text f 20 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
d8428a90-f534-4794-99a7-1c752d42e0d2 bbbbbbbb-0010-0010-0010-000000000010 fe52a6b2-e86e-47e0-9dc7-9b7e63599cff notes Observa????o textarea f 30 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
69435311-e703-4fbb-84b8-d634fd0148fe bbbbbbbb-0010-0010-0010-000000000010 fb2724d6-3938-4b3f-b8ec-aeb4417a4057 supervisor Supervisor text f 10 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
2c71883c-dee5-420e-9c7a-d1b1ade908f5 bbbbbbbb-0010-0010-0010-000000000010 fb2724d6-3938-4b3f-b8ec-aeb4417a4057 topic Assunto text f 20 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
1cf750d0-449d-4780-8828-bffce53cc651 bbbbbbbb-0010-0010-0010-000000000010 fb2724d6-3938-4b3f-b8ec-aeb4417a4057 notes Observa????o textarea f 30 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
e38226ca-3af4-41c3-a901-9edfc0814e46 bbbbbbbb-0010-0010-0010-000000000010 53193b8a-8af1-4824-a7c6-22cbb7459c45 theme Tema text f 10 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
6100b0b2-db5c-4aeb-98e3-3c6f6a20f058 bbbbbbbb-0010-0010-0010-000000000010 53193b8a-8af1-4824-a7c6-22cbb7459c45 group Turma text f 20 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
ef948cc1-4e2b-4c7a-9043-956a6341085a bbbbbbbb-0010-0010-0010-000000000010 53193b8a-8af1-4824-a7c6-22cbb7459c45 notes Observa????o textarea f 30 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
9405625b-f781-4b5d-836c-19371fccefab bbbbbbbb-0010-0010-0010-000000000010 29b5f51c-0833-4902-8c03-ee8bb7836a33 analyst Analista text f 10 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
cc414a63-c433-4269-be6c-caad9f83408d bbbbbbbb-0010-0010-0010-000000000010 29b5f51c-0833-4902-8c03-ee8bb7836a33 focus Foco text f 20 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
c5c4f4c9-2e74-4f65-b5d9-ee1121005cbc bbbbbbbb-0010-0010-0010-000000000010 29b5f51c-0833-4902-8c03-ee8bb7836a33 notes Observa????o textarea f 30 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: determined_commitments; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.determined_commitments (id, tenant_id, created_by, is_native, native_key, is_locked, active, name, description, created_at, updated_at, bg_color, text_color) FROM stdin;
|
|
5944e5d9-622d-4db1-b73d-0083a6a4a9a1 bbbbbbbb-0002-0002-0002-000000000002 \N t reading f t Leitura Praticar leitura 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N
|
|
b3bf589d-4a72-429f-b9bd-ba426c3f42f1 bbbbbbbb-0002-0002-0002-000000000002 \N t class f f Aula Dar aula 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N
|
|
cd1076b1-0f3d-460e-842f-1585c0ae2a64 bbbbbbbb-0003-0003-0003-000000000003 \N t reading f t Leitura Praticar leitura 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N
|
|
b82819d4-02a1-40c5-bf57-6e2e0425e62d bbbbbbbb-0003-0003-0003-000000000003 \N t class f f Aula Dar aula 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N
|
|
2e5f4151-e259-4261-8954-e3d196a28383 bbbbbbbb-0004-0004-0004-000000000004 \N t reading f t Leitura Praticar leitura 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N
|
|
bec193c2-172b-40ef-a5fe-91b7c44c841e bbbbbbbb-0004-0004-0004-000000000004 \N t class f f Aula Dar aula 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N
|
|
793f5b1d-b218-40a3-aa73-3e1440d9ea66 bbbbbbbb-0005-0005-0005-000000000005 \N t reading f t Leitura Praticar leitura 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N
|
|
8c1a77a1-b66f-462e-940d-2f60d080149c bbbbbbbb-0005-0005-0005-000000000005 \N t class f f Aula Dar aula 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N
|
|
fc6da673-fd7c-4101-b980-54eb3842804c bbbbbbbb-0009-0009-0009-000000000009 \N t reading f t Leitura Praticar leitura 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00 \N \N
|
|
4c4a8ced-d109-443b-bc83-817c858f9bb6 bbbbbbbb-0009-0009-0009-000000000009 \N t class f f Aula Dar aula 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00 \N \N
|
|
fe52a6b2-e86e-47e0-9dc7-9b7e63599cff bbbbbbbb-0010-0010-0010-000000000010 \N t reading f t Leitura Praticar leitura 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00 \N \N
|
|
53193b8a-8af1-4824-a7c6-22cbb7459c45 bbbbbbbb-0010-0010-0010-000000000010 \N t class f f Aula Dar aula 2026-03-23 11:27:09.865999+00 2026-03-23 11:27:09.865999+00 \N \N
|
|
e19a2e0e-cd6a-4cee-97e0-50a43ea69df1 bbbbbbbb-0002-0002-0002-000000000002 \N t analysis f t Análise Pessoal Minha an??lise pessoal 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
d2ea6a5e-e563-434b-950e-2d27bbf445ec bbbbbbbb-0003-0003-0003-000000000003 \N t session t t Sessão Sess??o com paciente 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
21f39315-5171-42ce-848c-129c1955206b bbbbbbbb-0004-0004-0004-000000000004 \N t session t t Sessão Sess??o com paciente 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
3276b032-6990-4bfc-942d-9155943c241e bbbbbbbb-0005-0005-0005-000000000005 \N t session t t Sessão Sess??o com paciente 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
fb194a3e-06ee-4704-a8cb-fe302dd2528e bbbbbbbb-0009-0009-0009-000000000009 \N t session t t Sessão Sess??o com paciente 2026-03-23 11:27:09.865999+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
1936c4af-5757-4c10-ad8f-8a5988287acc bbbbbbbb-0010-0010-0010-000000000010 \N t session t t Sessão Sess??o com paciente 2026-03-23 11:27:09.865999+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
42a8c681-8b32-4608-870f-b617acbe249e bbbbbbbb-0002-0002-0002-000000000002 \N t session t t Sessão Sessão com paciente 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 6366f1 #ffffff
|
|
717e552c-99cc-4375-b7f2-a1b29f3581e3 bbbbbbbb-0002-0002-0002-000000000002 \N t supervision f t Supervisão Supervis??o 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
9ded91f1-1974-4e56-afc6-12b2e8f9456c bbbbbbbb-0003-0003-0003-000000000003 \N t supervision f t Supervisão Supervis??o 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
0d6cb161-8d89-4b18-9323-5631e8cddd8f bbbbbbbb-0004-0004-0004-000000000004 \N t supervision f t Supervisão Supervis??o 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
83666a58-2e53-49a6-8b13-73eeb203e5ba bbbbbbbb-0005-0005-0005-000000000005 \N t supervision f t Supervisão Supervis??o 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
3dbb8c2f-6fab-478f-b094-5bc13606a504 bbbbbbbb-0009-0009-0009-000000000009 \N t supervision f t Supervisão Supervis??o 2026-03-23 11:27:09.865999+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
fb2724d6-3938-4b3f-b8ec-aeb4417a4057 bbbbbbbb-0010-0010-0010-000000000010 \N t supervision f t Supervisão Supervis??o 2026-03-23 11:27:09.865999+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
b5c43dc2-a3a1-40ca-8b75-02ec649fd914 bbbbbbbb-0003-0003-0003-000000000003 \N t analysis f t Análise Pessoal Minha an??lise pessoal 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
d11aa6fe-ef08-4610-8a6f-4b472ccd1b64 bbbbbbbb-0004-0004-0004-000000000004 \N t analysis f t Análise Pessoal Minha an??lise pessoal 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
a72b9eb5-747f-4ec3-8bb4-f9c17925e7ad bbbbbbbb-0005-0005-0005-000000000005 \N t analysis f t Análise Pessoal Minha an??lise pessoal 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
b180f6e4-39ad-464c-842e-d42dc60cdf13 bbbbbbbb-0009-0009-0009-000000000009 \N t analysis f t Análise Pessoal Minha an??lise pessoal 2026-03-23 11:27:09.865999+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
29b5f51c-0833-4902-8c03-ee8bb7836a33 bbbbbbbb-0010-0010-0010-000000000010 \N t analysis f t Análise Pessoal Minha an??lise pessoal 2026-03-23 11:27:09.865999+00 2026-03-23 14:21:19.247486+00 \N \N
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: dev_user_credentials; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.dev_user_credentials (id, user_id, email, password_dev, kind, note, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: email_layout_config; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.email_layout_config (id, tenant_id, header_config, footer_config, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: email_templates_global; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.email_templates_global (id, key, domain, channel, subject, body_html, body_text, version, is_active, variables, created_at, updated_at) FROM stdin;
|
|
be1e52ec-0c1d-4cbe-97da-9c47ce052631 session.reminder.email session email Lembrete: sua sessão amanhã às {{session_time}} \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Este é um lembrete da sua sessão agendada para <strong>{{session_date}}</strong> às <strong>{{session_time}}</strong>.</p>\n <p>Modalidade: <strong>{{session_modality}}</strong></p>\n {{#if session_link}}\n <p><a href="{{session_link}}">Clique aqui para entrar na sessão online</a></p>\n {{/if}}\n <p>Em caso de necessidade de cancelamento, entre em contato com antecedência.</p>\n <p>Até logo,<br><strong>{{therapist_name}}</strong></p>\n Olá, {{patient_name}}! Lembrete da sua sessão: {{session_date}} às {{session_time}} ({{session_modality}}). 2 t {"patient_name": "Nome completo do paciente", "session_date": "Data da sessão (ex: 20/03/2026)", "session_link": "Link da videochamada (apenas online)", "session_time": "Horário da sessão (ex: 14:00)", "therapist_name": "Nome do terapeuta", "session_modality": "Presencial ou Online"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
bf956245-c79a-4ed0-86f1-e0be57072cc8 session.confirmation.email session email Sessão confirmada — {{session_date}} às {{session_time}} \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Sua sessão foi confirmada com sucesso.</p>\n <ul>\n <li><strong>Data:</strong> {{session_date}}</li>\n <li><strong>Horário:</strong> {{session_time}}</li>\n <li><strong>Modalidade:</strong> {{session_modality}}</li>\n {{#if session_address}}<li><strong>Local:</strong> {{session_address}}</li>{{/if}}\n </ul>\n <p>Até lá,<br><strong>{{therapist_name}}</strong></p>\n Sessão confirmada: {{session_date}} às {{session_time}} ({{session_modality}}). 1 t {"patient_name": "Nome do paciente", "session_date": "Data da sessão", "session_time": "Horário da sessão", "therapist_name": "Nome do terapeuta", "session_address": "Endereço (apenas presencial)", "session_modality": "Presencial ou Online"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
9039f35e-e31f-4bad-a6a5-2b865f1152b3 session.cancellation.email session email Sessão cancelada — {{session_date}} \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Informamos que sua sessão do dia <strong>{{session_date}}</strong> às <strong>{{session_time}}</strong> foi cancelada.</p>\n {{#if cancellation_reason}}<p>Motivo: {{cancellation_reason}}</p>{{/if}}\n <p>Entre em contato para reagendar.</p>\n <p><strong>{{therapist_name}}</strong></p>\n \N 1 t {"patient_name": "Nome do paciente", "session_date": "Data cancelada", "session_time": "Horário cancelado", "therapist_name": "Nome do terapeuta", "cancellation_reason": "Motivo do cancelamento (opcional)"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
ff36dccc-6fe1-4391-9eac-bd03927b38f5 session.rescheduled.email session email Sessão reagendada — {{session_date}} às {{session_time}} \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Sua sessão foi reagendada para <strong>{{session_date}}</strong> às <strong>{{session_time}}</strong>.</p>\n <p>Modalidade: <strong>{{session_modality}}</strong></p>\n <p>Até lá,<br><strong>{{therapist_name}}</strong></p>\n \N 1 t {"patient_name": "Nome do paciente", "session_date": "Nova data", "session_time": "Novo horário", "therapist_name": "Nome do terapeuta", "session_modality": "Presencial ou Online"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
f17b10f8-d811-4f83-bf5e-3ed636262f28 intake.received.email intake email Recebemos seu cadastro — {{clinic_name}} \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Recebemos seu cadastro com sucesso. Nossa equipe entrará em contato em breve para dar continuidade ao processo.</p>\n <p>Obrigado pela confiança,<br><strong>{{clinic_name}}</strong></p>\n \N 1 t {"clinic_name": "Nome da clínica ou terapeuta", "patient_name": "Nome do solicitante"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
5b4a9a8b-bc92-4030-92ec-acbb6f9e7ee0 intake.approved.email intake email Cadastro aprovado — bem-vindo(a)! \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Seu cadastro foi aprovado. Você já pode acessar o portal e agendar sua primeira sessão.</p>\n <p><a href="{{portal_link}}">Acessar portal →</a></p>\n <p>Qualquer dúvida, estamos à disposição.<br><strong>{{therapist_name}}</strong></p>\n \N 1 t {"portal_link": "Link do portal do paciente", "patient_name": "Nome do paciente", "therapist_name": "Nome do terapeuta"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
04da6880-708a-4018-9b1f-0f398d152e0c intake.rejected.email intake email Atualização sobre seu cadastro — {{clinic_name}} \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Agradecemos seu interesse. Infelizmente não será possível dar continuidade ao seu cadastro no momento.</p>\n {{#if rejection_reason}}<p>{{rejection_reason}}</p>{{/if}}\n <p><strong>{{clinic_name}}</strong></p>\n \N 1 t {"clinic_name": "Nome da clínica", "patient_name": "Nome do paciente", "rejection_reason": "Motivo (opcional)"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
3e9ae66a-598c-4763-ab61-f02bb71323a4 scheduler.request_accepted.email session email Sua solicitação foi aceita — {{session_date}} às {{session_time}} \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Sua solicitação de agendamento foi aceita.</p>\n <ul>\n <li><strong>Data:</strong> {{session_date}}</li>\n <li><strong>Horário:</strong> {{session_time}}</li>\n <li><strong>Tipo:</strong> {{session_type}}</li>\n <li><strong>Modalidade:</strong> {{session_modality}}</li>\n </ul>\n <p>Até logo,<br><strong>{{therapist_name}}</strong></p>\n \N 1 t {"patient_name": "Nome do paciente", "session_date": "Data confirmada", "session_time": "Horário confirmado", "session_type": "Primeira consulta / Retorno", "therapist_name": "Nome do terapeuta", "session_modality": "Presencial ou Online"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
7c7f736d-1ddb-46ba-ab41-f66d2267b730 scheduler.request_rejected.email session email Atualização sobre sua solicitação de agendamento \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Infelizmente não foi possível confirmar sua solicitação de agendamento para <strong>{{session_date}}</strong>.</p>\n {{#if rejection_reason}}<p>Motivo: {{rejection_reason}}</p>{{/if}}\n <p>Entre em contato para verificar outros horários disponíveis.</p>\n <p><strong>{{therapist_name}}</strong></p>\n \N 1 t {"patient_name": "Nome do paciente", "session_date": "Data solicitada", "therapist_name": "Nome do terapeuta", "rejection_reason": "Motivo (opcional)"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
78a33f29-3428-482f-9b0e-362c69ff20a8 system.welcome.email system email Bem-vindo(a) ao {{clinic_name}}! \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Seja bem-vindo(a)! Sua conta foi criada com sucesso.</p>\n <p><a href="{{portal_link}}">Acessar minha área →</a></p>\n \N 1 t {"clinic_name": "Nome da clínica", "portal_link": "Link do portal", "patient_name": "Nome do paciente"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
21a3fab3-01af-4b16-bd63-50929be5001d system.password_reset.email system email Redefinição de senha \n <p>Olá, <strong>{{patient_name}}</strong>!</p>\n <p>Recebemos uma solicitação para redefinir sua senha.</p>\n <p><a href="{{reset_link}}">Clique aqui para redefinir sua senha →</a></p>\n <p>Se você não solicitou a redefinição, ignore este e-mail.</p>\n \N 1 t {"reset_link": "Link de redefinição de senha", "patient_name": "Nome do usuário"} 2026-03-23 11:27:15.104483+00 2026-03-23 14:18:08.414378+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: email_templates_tenant; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.email_templates_tenant (id, tenant_id, owner_id, template_key, subject, body_html, body_text, enabled, synced_version, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: entitlements_invalidation; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.entitlements_invalidation (owner_id, changed_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: features; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.features (id, key, description, created_at, descricao, name) FROM stdin;
|
|
5e539124-630f-4c2a-a9de-7999317085e6 agenda.view Visualização da agenda 2026-02-21 02:36:01.562728+00 Visualizar agenda Agenda - Visualizar
|
|
a74fef14-c9d9-4884-ba45-f81c60e0783a agenda.manage Gerenciamento completo da agenda 2026-02-21 02:35:50.629667+00 Adicionar Compromissos na agenda Agenda - Gerenciar
|
|
a56482a1-0787-49da-90a7-e1857488734a patients Módulo de pacientes 2026-03-02 12:35:19.955748+00 Pacientes Pacientes
|
|
57f631a1-9ebe-480b-a2cb-144ad32ff5f0 patients.view Visualização de pacientes 2026-02-28 11:15:14.275572+00 Visualizar pacientes Pacientes - Visualizar
|
|
4e5bc50b-e339-42fe-9d91-61e8555f83e7 patients.manage Gerenciamento completo de pacientes 2026-02-28 11:15:14.275572+00 Gerenciar pacientes Pacientes - Gerenciar
|
|
53a48c3b-0617-4618-adf8-f3a255c51ee4 online_scheduling Sistema de agendamento online 2026-03-01 09:59:15.432733+00 Agendamento online Agendamento Online
|
|
5739aa27-b089-4b15-b149-31b13d768825 online_scheduling.manage Gerenciamento do agendamento online 2026-02-15 21:50:02.056357+00 Gerenciar agendamento online (admin) Agendamento Online - Gerenciar
|
|
0bfe0b1c-8c3d-4c0c-af29-2ddc24f31bc7 online_scheduling.public Página pública do agendador 2026-02-15 21:50:02.056357+00 Página pública de agendamento Agendamento Online - Público
|
|
f5d66212-fd73-4472-a306-07928e5deaec reminders Sistema de lembretes automáticos 2026-03-01 09:59:15.432733+00 Lembretes Lembretes
|
|
b3efa25d-60a4-4974-8153-6ec098b3d477 reports_basic Relatórios básicos 2026-03-01 09:59:15.432733+00 Relatórios básicos Relatórios Básicos
|
|
bf133ad1-da8e-4ea9-bd66-21901cb50075 reports_advanced Relatórios avançados com exportação 2026-03-01 09:59:15.432733+00 Relatórios avançados Relatórios Avançados
|
|
336aeeba-b18e-4e68-8303-d42ba09f4b20 secretary Funcionalidade de secretária 2026-03-01 09:59:15.432733+00 Secretaria Secretária
|
|
30c9cdd5-7c8c-44d9-8c0b-614165bb9496 shared_reception Recepção compartilhada entre terapeutas 2026-03-02 12:35:19.955748+00 Recepção / Secretária Recepção Compartilhada
|
|
74fc1321-4d17-49c3-b72e-db3a7f4be451 rooms Gerenciamento de salas 2026-03-02 12:35:19.955748+00 Salas / Coworking Salas
|
|
c109ad27-0edf-4774-91a7-94dac4faab49 intake_public Formulário de intake público 2026-03-02 12:35:19.955748+00 Link externo de cadastro Intake Público
|
|
90e92108-8124-40ee-88a0-f0ecafb57d76 intakes_pro Funcionalidades avançadas de intake 2026-02-15 23:29:55.845638+00 Formulários PRO Intakes PRO
|
|
f393178c-284d-422f-b096-8793f85428d5 custom_branding Personalização de marca 2026-03-01 09:59:15.432733+00 Personalização de marca Branding Personalizado
|
|
d6f54674-ea8b-484b-af0e-99127a510da2 api_access Acesso via API 2026-03-01 09:59:15.432733+00 Integrações/API Acesso API
|
|
a5593d96-dd95-46bb-bef0-bd379b56ad50 audit_log Log de auditoria completo 2026-03-01 09:59:15.432733+00 Auditoria Log de Auditoria
|
|
8cc81988-d02a-4542-9cb2-ce2ed7c18d60 sms_reminder Lembretes via SMS 2026-02-15 23:29:55.845638+00 Lembretes por SMS Lembrete SMS
|
|
9b36c65d-b3b3-4bed-b6d5-f7ee8c087c80 clinic_calendar Visão consolidada do calendário 2026-03-01 09:59:15.432733+00 Agenda da clínica Calendário da Clínica
|
|
a830e45b-3bb4-4b17-812d-fe83777a2377 advanced_reports Relatórios avançados da clínica 2026-02-15 23:29:55.845638+00 Relatórios avançados Relatórios Avançados (Clínica)
|
|
9ab8bdbb-838b-4946-aa5d-fd9cfdd257b3 supervisor.access Acesso ao módulo de supervisão 2026-03-05 00:58:17.218326+00 Acesso básico ao espaço de supervisão (sala, lista de supervisionados). Supervisor - Acesso
|
|
1167b54a-0e93-43a2-94d7-c12e64eb56de supervisor.invite Convidar supervisionados 2026-03-05 00:58:17.218326+00 Permite convidar terapeutas para participar da sala de supervisão. Supervisor - Convidar
|
|
761e4495-b46a-4791-9519-86ffe48dc47f supervisor.sessions Gerenciar sessões de supervisão 2026-03-05 00:58:17.218326+00 Agendamento e registro de sessões de supervisão. Supervisor - Sessões
|
|
7e82ee01-44f6-4b3f-9861-840c58e13f58 supervisor.reports Relatórios de supervisão 2026-03-05 00:58:17.218326+00 Relatórios avançados de progresso e evolução dos supervisionados. Supervisor - Relatórios
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: feriados; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.feriados (id, tenant_id, owner_id, tipo, nome, data, cidade, estado, observacao, bloqueia_sessoes, criado_em) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: financial_categories; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.financial_categories (id, user_id, name, type, color, icon, sort_order, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: financial_exceptions; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.financial_exceptions (id, owner_id, tenant_id, exception_type, charge_mode, charge_value, charge_pct, min_hours_notice, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: financial_records; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.financial_records (id, owner_id, tenant_id, type, amount, description, category, payment_method, paid_at, due_date, installments, installment_number, installment_group, agenda_evento_id, patient_id, clinic_fee_pct, clinic_fee_amount, insurance_plan_id, notes, tags, created_at, updated_at, deleted_at, discount_amount, final_amount, status, category_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: global_notices; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.global_notices (id, title, message, variant, roles, contexts, starts_at, ends_at, is_active, priority, dismissible, persist_dismiss, dismiss_scope, show_once, max_views, cooldown_minutes, version, action_type, action_label, action_url, action_route, views_count, clicks_count, created_at, updated_at, created_by, content_align, link_target) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: insurance_plan_services; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.insurance_plan_services (id, insurance_plan_id, name, value, active, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: insurance_plans; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.insurance_plans (id, owner_id, tenant_id, name, notes, default_value, active, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: login_carousel_slides; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.login_carousel_slides (id, title, body, icon, ordem, ativo, created_at, updated_at) FROM stdin;
|
|
0af63b3a-1819-4384-bf94-b29cbe84aca3 <strong>Gestão clínica simplificada</strong> Agendamentos, prontuários e sessões em um único painel. Foco no que importa: <em>seus pacientes</em>. pi-calendar-clock 0 t 2026-03-23 14:18:08.414378+00 2026-03-23 14:18:08.414378+00
|
|
c02309d3-85cf-452f-bb85-363889aea9f3 <strong>Gestão clínica simplificada</strong> Gerencie agenda, pacientes e financeiro em um só lugar. Simples, rápido e seguro. pi-users 1 t 2026-03-23 14:18:08.414378+00 2026-03-23 14:18:08.414378+00
|
|
763a600e-987c-4e42-8f62-29b5dea59c39 <strong>Múltiplos profissionais, uma só plataforma</strong> Ideal para clínicas com vários terapeutas. Cada profissional com sua agenda e seus pacientes. pi-shield 2 t 2026-03-23 14:18:08.414378+00 2026-03-23 14:18:08.414378+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: module_features; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.module_features (module_id, feature_id, enabled, limits, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: modules; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.modules (id, key, name, description, is_active, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: notice_dismissals; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.notice_dismissals (id, notice_id, user_id, version, dismissed_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: notification_channels; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.notification_channels (id, tenant_id, owner_id, channel, provider, is_active, display_name, sender_address, credentials, connection_status, last_health_check, metadata, created_at, updated_at, deleted_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: notification_logs; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.notification_logs (id, tenant_id, owner_id, queue_id, agenda_evento_id, patient_id, channel, template_key, schedule_key, recipient_address, resolved_message, resolved_vars, status, provider, provider_message_id, provider_status, provider_response, sent_at, delivered_at, read_at, failed_at, failure_reason, estimated_cost_brl, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: notification_preferences; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.notification_preferences (id, tenant_id, owner_id, patient_id, whatsapp_opt_in, email_opt_in, sms_opt_in, preferred_time_start, preferred_time_end, lgpd_consent_given, lgpd_consent_date, lgpd_consent_version, lgpd_consent_ip, lgpd_opt_out_date, lgpd_opt_out_reason, created_at, updated_at, deleted_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: notification_queue; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.notification_queue (id, tenant_id, owner_id, agenda_evento_id, patient_id, channel, template_key, schedule_key, resolved_vars, recipient_address, status, scheduled_at, sent_at, next_retry_at, attempts, max_attempts, last_error, idempotency_key, provider_message_id, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: notification_schedules; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.notification_schedules (id, tenant_id, owner_id, schedule_key, event_type, trigger_type, offset_minutes, whatsapp_enabled, email_enabled, sms_enabled, allowed_time_start, allowed_time_end, skip_weekends, skip_holidays, is_active, sort_order, created_at, updated_at, deleted_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: notification_templates; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.notification_templates (id, tenant_id, owner_id, key, domain, channel, event_type, body_text, meta_template_name, meta_template_namespace, meta_components, meta_status, variables, version, is_active, is_default, created_at, updated_at, deleted_at) FROM stdin;
|
|
37311b1a-2919-4f38-8dbc-7ccf81942062 \N \N session.reminder.whatsapp session whatsapp lembrete_sessao Olá {{nome_paciente}}! 👋\n\nLembrete: você tem sessão agendada para *{{data_sessao}}* às *{{hora_sessao}}* com {{nome_terapeuta}}.\n\n📋 {{modalidade}}\n\nPara confirmar, responda ✅\nPara cancelar, responda ❌\n\nSe precisar remarcar, entre em contato.\n\n_Responda SAIR para não receber mais lembretes._ \N \N \N draft ["nome_paciente", "data_sessao", "hora_sessao", "nome_terapeuta", "modalidade"] 1 t t 2026-03-23 11:27:15.104483+00 2026-03-23 11:27:15.104483+00 \N
|
|
4e61a64d-b2f9-49de-9d27-6496ddba8aef \N \N session.confirmation.whatsapp session whatsapp confirmacao_sessao ✅ Sessão confirmada!\n\nOlá {{nome_paciente}}, sua sessão com {{nome_terapeuta}} foi confirmada:\n\n📅 {{data_sessao}} às {{hora_sessao}}\n📋 {{modalidade}}\n\nTe esperamos! \N \N \N draft ["nome_paciente", "data_sessao", "hora_sessao", "nome_terapeuta", "modalidade"] 1 t t 2026-03-23 11:27:15.104483+00 2026-03-23 11:27:15.104483+00 \N
|
|
262e9dba-0324-478f-9d76-3faba555ec3c \N \N session.cancellation.whatsapp session whatsapp cancelamento_sessao Olá {{nome_paciente}},\n\nSua sessão de {{data_sessao}} às {{hora_sessao}} com {{nome_terapeuta}} foi *cancelada*.\n\nSe desejar reagendar, entre em contato.\n\nAtenciosamente,\n{{nome_terapeuta}} \N \N \N draft ["nome_paciente", "data_sessao", "hora_sessao", "nome_terapeuta"] 1 t t 2026-03-23 11:27:15.104483+00 2026-03-23 11:27:15.104483+00 \N
|
|
2c5331f9-6728-4cea-b4cc-e9b2659f5362 \N \N session.reminder.sms session sms lembrete_sessao Lembrete: sessao em {{data_sessao}} as {{hora_sessao}} com {{nome_terapeuta}}. Confirme respondendo OK. \N \N \N draft ["data_sessao", "hora_sessao", "nome_terapeuta"] 1 t t 2026-03-23 11:27:15.104483+00 2026-03-23 11:27:15.104483+00 \N
|
|
3e4386ba-2790-41e8-9b92-3b6beab549d8 \N \N session.lembrete.whatsapp session whatsapp lembrete_sessao Olá, {{nome_paciente}}! 👋\n\nLembrete da sua sessão com {{nome_terapeuta}}.\n\n📅 Data: {{data_sessao}}\n🕐 Hora: {{hora_sessao}}\n📍 Modalidade: {{modalidade}}\n\nQualquer dúvida, entre em contato. Até lá! 💚 \N \N \N draft ["nome_paciente", "nome_terapeuta", "data_sessao", "hora_sessao", "modalidade"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
eb218e05-4ea0-4884-acd2-a766d3986d04 \N \N session.lembrete_2h.whatsapp session whatsapp lembrete_sessao Olá, {{nome_paciente}}! Sua sessão com {{nome_terapeuta}} começa em 2 horas.\n\n🕐 Hora: {{hora_sessao}}\n📍 Modalidade: {{modalidade}}\n\nAté já! 😊 \N \N \N draft ["nome_paciente", "nome_terapeuta", "data_sessao", "hora_sessao", "modalidade"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
4574eb97-aeda-4cbb-a7e9-243c8f8c0b17 \N \N session.confirmacao.whatsapp session whatsapp confirmacao_sessao Olá, {{nome_paciente}}! ✅\n\nSua sessão foi confirmada!\n\n📅 Data: {{data_sessao}}\n🕐 Hora: {{hora_sessao}}\n📍 Modalidade: {{modalidade}}\n\nAté lá! 💚 \N \N \N draft ["nome_paciente", "nome_terapeuta", "data_sessao", "hora_sessao", "modalidade", "link_confirmacao"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
b321696c-96e2-4d16-8f8d-aa46d98945b8 \N \N session.cancelamento.whatsapp session whatsapp cancelamento_sessao Olá, {{nome_paciente}}. Infelizmente a sessão do dia {{data_sessao}} às {{hora_sessao}} foi cancelada.\n\nEntre em contato para reagendar. 🙏 \N \N \N draft ["nome_paciente", "nome_terapeuta", "data_sessao", "hora_sessao", "modalidade"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
216c6404-6e6c-4cb6-b5bd-486c8abc3c48 \N \N session.reagendamento.whatsapp session whatsapp reagendamento Olá, {{nome_paciente}}! Sua sessão foi reagendada.\n\n📅 Nova data: {{data_sessao}}\n🕐 Novo horário: {{hora_sessao}}\n📍 Modalidade: {{modalidade}}\n\nAté lá! 😊 \N \N \N draft ["nome_paciente", "nome_terapeuta", "data_sessao", "hora_sessao", "modalidade"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
48a93a15-9675-49a7-a2d7-3b9b589e14f5 \N \N cobranca.pendente.whatsapp billing whatsapp cobranca_pendente Olá, {{nome_paciente}}. Identificamos uma cobrança pendente no valor de {{valor_sessao}} referente à sua sessão do dia {{data_sessao}}.\n\nPor favor, entre em contato para regularizar. 🙏 \N \N \N draft ["nome_paciente", "nome_terapeuta", "data_sessao", "hora_sessao", "modalidade", "valor_sessao"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
26edef88-2d45-4ee2-8496-30f76f35cb77 \N \N sistema.boas_vindas.whatsapp system whatsapp boas_vindas_paciente Olá, {{nome_paciente}}! 🎉\n\nSeja muito bem-vindo(a)! Estamos felizes em ter você aqui.\n\nEm caso de dúvidas, estamos à disposição. Até a nossa primeira sessão! 💚 \N \N \N draft ["nome_paciente", "nome_terapeuta", "data_sessao", "hora_sessao", "modalidade"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
e66ef5f5-ab3a-46c1-8446-25b55487a017 \N \N session.confirmation.sms session sms confirmacao_sessao Sessão confirmada! {{session_date}} às {{session_time}} ({{session_modality}}) com {{therapist_name}}. \N \N \N draft ["patient_name", "session_date", "session_time", "session_modality", "therapist_name"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
aae09094-82cb-406f-8015-c42cd24afded \N \N session.cancellation.sms session sms cancelamento_sessao Sua sessão de {{session_date}} às {{session_time}} foi cancelada. Entre em contato para reagendar. — {{therapist_name}} \N \N \N draft ["patient_name", "session_date", "session_time", "therapist_name"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
c8521ea4-31c0-4015-8923-7ef57b3f8b47 \N \N session.rescheduled.sms session sms reagendamento Sua sessão foi reagendada para {{session_date}} às {{session_time}} ({{session_modality}}). — {{therapist_name}} \N \N \N draft ["patient_name", "session_date", "session_time", "session_modality", "therapist_name"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
ba32ee4e-6548-48de-bf83-b0cb11a00761 \N \N intake.received.sms intake sms intake_recebido Olá {{patient_name}}, recebemos seu cadastro. Em breve entraremos em contato. — {{clinic_name}} \N \N \N draft ["patient_name", "clinic_name"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
7ccd6a04-8b89-4238-bb97-d78b0d56312f \N \N intake.approved.sms intake sms intake_aprovado Olá {{patient_name}}, seu cadastro foi aprovado! Acesse o portal para agendar sua sessão. — {{therapist_name}} \N \N \N draft ["patient_name", "therapist_name"] 1 t t 2026-03-23 12:01:07.120095+00 2026-03-23 12:01:07.120095+00 \N
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: notifications; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.notifications (id, owner_id, tenant_id, type, ref_id, ref_table, payload, read_at, archived, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: owner_users; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.owner_users (owner_id, user_id, role, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: patient_discounts; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.patient_discounts (id, owner_id, tenant_id, patient_id, discount_pct, discount_flat, reason, active, active_from, active_to, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: patient_group_patient; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.patient_group_patient (patient_group_id, patient_id, created_at, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: patient_groups; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.patient_groups (id, nome, descricao, cor, is_active, is_system, owner_id, created_at, updated_at, therapist_id, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: patient_intake_requests; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.patient_intake_requests (id, owner_id, token, consent, status, created_at, converted_patient_id, rejected_reason, updated_at, cpf, rg, cep, nome_completo, email_principal, telefone, pais, cidade, estado, endereco, numero, bairro, complemento, data_nascimento, naturalidade, genero, estado_civil, onde_nos_conheceu, encaminhado_por, observacoes, notas_internas, email_alternativo, telefone_alternativo, profissao, escolaridade, nacionalidade, avatar_url, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: patient_invites; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.patient_invites (id, owner_id, token, active, expires_at, max_uses, uses, created_at, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: patient_patient_tag; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.patient_patient_tag (owner_id, patient_id, tag_id, created_at, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: patient_tags; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.patient_tags (id, owner_id, nome, cor, is_padrao, created_at, updated_at, tenant_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: patients; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.patients (id, nome_completo, email_principal, telefone, created_at, owner_id, avatar_url, status, last_attended_at, is_native, naturalidade, data_nascimento, rg, cpf, identification_color, genero, estado_civil, email_alternativo, pais, cep, cidade, estado, endereco, numero, bairro, complemento, escolaridade, profissao, nome_parente, grau_parentesco, telefone_alternativo, onde_nos_conheceu, encaminhado_por, nome_responsavel, telefone_responsavel, cpf_responsavel, observacao_responsavel, cobranca_no_responsavel, observacoes, notas_internas, updated_at, telefone_parente, tenant_id, responsible_member_id, user_id, patient_scope, therapist_member_id) FROM stdin;
|
|
6449e64b-050b-419f-8845-029b6f10a17d Otto Rank otto.rank.437@example.com 86363331874 2026-03-23 11:33:02.010795+00 aaaaaaaa-0002-0002-0002-000000000002 \N Ativo \N f \N \N \N \N \N \N \N \N Brasil \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N f \N \N 2026-03-23 11:33:02.010795+00 \N bbbbbbbb-0002-0002-0002-000000000002 72be63ef-bc2c-4c8e-8522-0c6d64746bbc \N clinic \N
|
|
7029e350-49dd-444e-924f-f884d645dfa2 Christopher Bollas christopher.bollas.544@example.com 61644344609 2026-03-23 11:33:46.535347+00 aaaaaaaa-0002-0002-0002-000000000002 \N Ativo \N f \N \N \N \N \N \N \N \N Brasil \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N \N f \N \N 2026-03-23 11:33:46.535347+00 \N bbbbbbbb-0002-0002-0002-000000000002 72be63ef-bc2c-4c8e-8522-0c6d64746bbc \N clinic \N
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: payment_settings; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.payment_settings (id, owner_id, tenant_id, pix_ativo, pix_tipo, pix_chave, pix_nome_titular, deposito_ativo, deposito_banco, deposito_agencia, deposito_conta, deposito_tipo_conta, deposito_titular, deposito_cpf_cnpj, dinheiro_ativo, cartao_ativo, cartao_instrucao, convenio_ativo, convenio_lista, observacoes_pagamento, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: plan_features; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.plan_features (plan_id, feature_id, enabled, limits, created_at) FROM stdin;
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 5e539124-630f-4c2a-a9de-7999317085e6 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 a74fef14-c9d9-4884-ba45-f81c60e0783a t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 9b36c65d-b3b3-4bed-b6d5-f7ee8c087c80 t {"max_patients": 9999, "max_therapists": 999} 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 a56482a1-0787-49da-90a7-e1857488734a t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 57f631a1-9ebe-480b-a2cb-144ad32ff5f0 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 4e5bc50b-e339-42fe-9d91-61e8555f83e7 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 53a48c3b-0617-4618-adf8-f3a255c51ee4 t {"sessions_per_month": 9999} 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 5739aa27-b089-4b15-b149-31b13d768825 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 0bfe0b1c-8c3d-4c0c-af29-2ddc24f31bc7 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 b3efa25d-60a4-4974-8153-6ec098b3d477 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 bf133ad1-da8e-4ea9-bd66-21901cb50075 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 a830e45b-3bb4-4b17-812d-fe83777a2377 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 f5d66212-fd73-4472-a306-07928e5deaec t {"reminders_per_month": 9999} 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 8cc81988-d02a-4542-9cb2-ce2ed7c18d60 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 336aeeba-b18e-4e68-8303-d42ba09f4b20 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 30c9cdd5-7c8c-44d9-8c0b-614165bb9496 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 74fc1321-4d17-49c3-b72e-db3a7f4be451 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 c109ad27-0edf-4774-91a7-94dac4faab49 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 90e92108-8124-40ee-88a0-f0ecafb57d76 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 f393178c-284d-422f-b096-8793f85428d5 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 d6f54674-ea8b-484b-af0e-99127a510da2 t \N 2026-03-23 14:18:07.731209+00
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 a5593d96-dd95-46bb-bef0-bd379b56ad50 t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 5e539124-630f-4c2a-a9de-7999317085e6 t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 a74fef14-c9d9-4884-ba45-f81c60e0783a t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 9b36c65d-b3b3-4bed-b6d5-f7ee8c087c80 t {"max_patients": 30, "max_therapists": 5} 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 a56482a1-0787-49da-90a7-e1857488734a t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 57f631a1-9ebe-480b-a2cb-144ad32ff5f0 t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 4e5bc50b-e339-42fe-9d91-61e8555f83e7 t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 53a48c3b-0617-4618-adf8-f3a255c51ee4 t {"sessions_per_month": 40} 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 5739aa27-b089-4b15-b149-31b13d768825 t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 0bfe0b1c-8c3d-4c0c-af29-2ddc24f31bc7 t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 b3efa25d-60a4-4974-8153-6ec098b3d477 t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 bf133ad1-da8e-4ea9-bd66-21901cb50075 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 a830e45b-3bb4-4b17-812d-fe83777a2377 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 f5d66212-fd73-4472-a306-07928e5deaec t {"reminders_per_month": 50} 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 8cc81988-d02a-4542-9cb2-ce2ed7c18d60 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 c109ad27-0edf-4774-91a7-94dac4faab49 t \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 90e92108-8124-40ee-88a0-f0ecafb57d76 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 336aeeba-b18e-4e68-8303-d42ba09f4b20 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 30c9cdd5-7c8c-44d9-8c0b-614165bb9496 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 74fc1321-4d17-49c3-b72e-db3a7f4be451 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 f393178c-284d-422f-b096-8793f85428d5 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 d6f54674-ea8b-484b-af0e-99127a510da2 f \N 2026-03-23 14:18:07.731209+00
|
|
01a5867f-0705-4714-ac97-a23470949157 a5593d96-dd95-46bb-bef0-bd379b56ad50 f \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 5e539124-630f-4c2a-a9de-7999317085e6 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 a74fef14-c9d9-4884-ba45-f81c60e0783a t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 9b36c65d-b3b3-4bed-b6d5-f7ee8c087c80 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 57f631a1-9ebe-480b-a2cb-144ad32ff5f0 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 4e5bc50b-e339-42fe-9d91-61e8555f83e7 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 53a48c3b-0617-4618-adf8-f3a255c51ee4 t {"sessions_per_month": 9999} 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 5739aa27-b089-4b15-b149-31b13d768825 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 0bfe0b1c-8c3d-4c0c-af29-2ddc24f31bc7 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 b3efa25d-60a4-4974-8153-6ec098b3d477 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 bf133ad1-da8e-4ea9-bd66-21901cb50075 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 a830e45b-3bb4-4b17-812d-fe83777a2377 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 f5d66212-fd73-4472-a306-07928e5deaec t {"reminders_per_month": 9999} 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 8cc81988-d02a-4542-9cb2-ce2ed7c18d60 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 336aeeba-b18e-4e68-8303-d42ba09f4b20 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 c109ad27-0edf-4774-91a7-94dac4faab49 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 90e92108-8124-40ee-88a0-f0ecafb57d76 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 f393178c-284d-422f-b096-8793f85428d5 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 d6f54674-ea8b-484b-af0e-99127a510da2 t \N 2026-03-23 14:18:07.731209+00
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 a5593d96-dd95-46bb-bef0-bd379b56ad50 t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a 5e539124-630f-4c2a-a9de-7999317085e6 t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a a74fef14-c9d9-4884-ba45-f81c60e0783a t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a 57f631a1-9ebe-480b-a2cb-144ad32ff5f0 t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a 4e5bc50b-e339-42fe-9d91-61e8555f83e7 t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a 53a48c3b-0617-4618-adf8-f3a255c51ee4 t {"sessions_per_month": 40} 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a 5739aa27-b089-4b15-b149-31b13d768825 t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a 0bfe0b1c-8c3d-4c0c-af29-2ddc24f31bc7 t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a b3efa25d-60a4-4974-8153-6ec098b3d477 t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a bf133ad1-da8e-4ea9-bd66-21901cb50075 f \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a f5d66212-fd73-4472-a306-07928e5deaec t {"reminders_per_month": 50} 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a 8cc81988-d02a-4542-9cb2-ce2ed7c18d60 f \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a c109ad27-0edf-4774-91a7-94dac4faab49 t \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a 90e92108-8124-40ee-88a0-f0ecafb57d76 f \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a f393178c-284d-422f-b096-8793f85428d5 f \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a d6f54674-ea8b-484b-af0e-99127a510da2 f \N 2026-03-23 14:18:07.731209+00
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a a5593d96-dd95-46bb-bef0-bd379b56ad50 f \N 2026-03-23 14:18:07.731209+00
|
|
8c4895a3-e12d-48de-a078-efb8a4ea2eb2 9ab8bdbb-838b-4946-aa5d-fd9cfdd257b3 t \N 2026-03-23 14:18:07.731209+00
|
|
8c4895a3-e12d-48de-a078-efb8a4ea2eb2 1167b54a-0e93-43a2-94d7-c12e64eb56de t \N 2026-03-23 14:18:07.731209+00
|
|
ca28e46c-0687-45d5-9406-0a0f56a5b625 9ab8bdbb-838b-4946-aa5d-fd9cfdd257b3 t \N 2026-03-23 14:18:07.731209+00
|
|
ca28e46c-0687-45d5-9406-0a0f56a5b625 1167b54a-0e93-43a2-94d7-c12e64eb56de t \N 2026-03-23 14:18:07.731209+00
|
|
ca28e46c-0687-45d5-9406-0a0f56a5b625 761e4495-b46a-4791-9519-86ffe48dc47f t \N 2026-03-23 14:18:07.731209+00
|
|
ca28e46c-0687-45d5-9406-0a0f56a5b625 7e82ee01-44f6-4b3f-9861-840c58e13f58 t \N 2026-03-23 14:18:07.731209+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: plan_prices; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.plan_prices (id, plan_id, currency, "interval", amount_cents, is_active, active_from, active_to, source, provider, provider_price_id, created_at) FROM stdin;
|
|
37510504-4617-4421-9979-4249778bd5ae 82067ba7-16f0-4803-b36f-4c4e8919d4b4 BRL month 4900 t 2026-03-01 09:25:03.878498+00 \N manual \N \N 2026-03-01 09:25:03.878498+00
|
|
225afd5a-9f30-46bc-a0df-5eb8f91660cb 82067ba7-16f0-4803-b36f-4c4e8919d4b4 BRL year 49000 t 2026-03-01 09:25:03.878498+00 \N manual \N \N 2026-03-01 09:25:03.878498+00
|
|
124779b4-362d-4890-9631-747021ecc1c0 a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 BRL month 14900 t 2026-03-01 09:30:06.50975+00 \N manual \N \N 2026-03-01 09:30:06.50975+00
|
|
73908784-6299-45c8-b547-e1556b45c292 a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 BRL year 149000 t 2026-03-01 09:30:06.50975+00 \N manual \N \N 2026-03-01 09:30:06.50975+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: plan_public; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.plan_public (plan_id, public_name, public_description, badge, is_featured, is_visible, sort_order, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: plan_public_bullets; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.plan_public_bullets (id, plan_id, text, sort_order, highlight, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: plans; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.plans (id, key, name, description, is_active, created_at, price_cents, currency, billing_interval, target, max_supervisees) FROM stdin;
|
|
984c1f29-a975-4208-93ac-2118ed1039b7 patient_free Paciente Free Plano gratuito para pacientes t 2026-03-03 22:40:11.413107+00 0 BRL month patient \N
|
|
c56fe2a8-2c17-4048-adc7-ff7fbd89461a therapist_free THERAPIST FREE Plano gratuito para terapeutas. t 2026-03-01 09:40:48.439668+00 0 BRL month therapist \N
|
|
82067ba7-16f0-4803-b36f-4c4e8919d4b4 therapist_pro THERAPIST PRO Plano completo para terapeutas. t 2026-03-01 09:25:03.878498+00 4900 BRL month therapist \N
|
|
01a5867f-0705-4714-ac97-a23470949157 clinic_free CLINIC FREE Plano gratuito para clínicas iniciarem. t 2026-03-01 09:25:03.878498+00 0 BRL month clinic \N
|
|
a74bc2d4-88c6-4cc6-b004-ef2bcb1b5145 clinic_pro CLINIC PRO Plano completo para clínicas. t 2026-03-01 09:30:06.50975+00 14900 BRL month clinic \N
|
|
8c4895a3-e12d-48de-a078-efb8a4ea2eb2 supervisor_free Supervisor Free Plano gratuito de supervisão. Até 3 terapeutas supervisionados. t 2026-03-05 00:58:17.218326+00 0 BRL month supervisor 3
|
|
ca28e46c-0687-45d5-9406-0a0f56a5b625 supervisor_pro Supervisor PRO Plano profissional de supervisão. Até 20 terapeutas supervisionados. t 2026-03-05 00:58:17.218326+00 0 BRL month supervisor 20
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: professional_pricing; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.professional_pricing (id, owner_id, tenant_id, determined_commitment_id, price, notes, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: profiles; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.profiles (id, role, full_name, created_at, updated_at, avatar_url, phone, bio, language, timezone, notify_system_email, notify_reminders, notify_news, account_type, platform_roles, nickname, work_description, work_description_other, site_url, social_instagram, social_youtube, social_facebook, social_x, social_custom) FROM stdin;
|
|
aaaaaaaa-0001-0001-0001-000000000001 portal_user Ana Paciente 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N \N pt-BR America/Sao_Paulo t t f patient {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0002-0002-0002-000000000002 tenant_member Bruno Terapeuta 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N \N pt-BR America/Sao_Paulo t t f therapist {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0006-0006-0006-000000000006 saas_admin Admin Plataforma 2026-03-23 10:46:29.876072+00 2026-03-23 10:46:29.876072+00 \N \N \N pt-BR America/Sao_Paulo t t f free {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0007-0007-0007-000000000007 tenant_member Carlos Supervisor 2026-03-23 14:18:05.215881+00 2026-03-23 14:18:05.215881+00 \N \N \N pt-BR America/Sao_Paulo t t f therapist {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0008-0008-0008-000000000008 tenant_member Diana Editora 2026-03-23 14:18:05.215881+00 2026-03-23 14:18:05.215881+00 \N \N \N pt-BR America/Sao_Paulo t t f therapist {editor} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0009-0009-0009-000000000009 tenant_member Eva Terapeuta 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 \N \N \N pt-BR America/Sao_Paulo t t f therapist {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0010-0010-0010-000000000010 tenant_member Felipe Terapeuta 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 \N \N \N pt-BR America/Sao_Paulo t t f therapist {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0011-0011-0011-000000000011 tenant_member Gabriela Secretária 2026-03-23 14:18:06.087973+00 2026-03-23 14:18:06.087973+00 \N \N \N pt-BR America/Sao_Paulo t t f therapist {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0003-0003-0003-000000000003 tenant_member Clínica Espaço Psi 2026-03-23 10:46:29.876072+00 2026-03-23 14:18:43.066684+00 \N \N \N pt-BR America/Sao_Paulo t t f clinic {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0004-0004-0004-000000000004 tenant_member Clínica Mente Sã 2026-03-23 10:46:29.876072+00 2026-03-23 14:18:59.312611+00 \N \N \N pt-BR America/Sao_Paulo t t f clinic {} \N \N \N \N \N \N \N \N []
|
|
aaaaaaaa-0005-0005-0005-000000000005 tenant_member Clínica Bem Estar 2026-03-23 10:46:29.876072+00 2026-03-23 14:21:19.247486+00 \N \N \N pt-BR America/Sao_Paulo t t f clinic {} \N \N \N \N \N \N \N \N []
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: recurrence_exceptions; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.recurrence_exceptions (id, recurrence_id, tenant_id, original_date, type, new_date, new_start_time, new_end_time, modalidade, observacoes, titulo_custom, extra_fields, reason, agenda_evento_id, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: recurrence_rule_services; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.recurrence_rule_services (id, rule_id, service_id, quantity, unit_price, discount_pct, discount_flat, final_price, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: recurrence_rules; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.recurrence_rules (id, 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, created_at, updated_at, price, insurance_plan_id, insurance_guide_number, insurance_value, insurance_plan_service_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: saas_admins; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.saas_admins (user_id, created_at) FROM stdin;
|
|
aaaaaaaa-0006-0006-0006-000000000006 2026-03-23 10:46:29.876072+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: saas_doc_votos; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.saas_doc_votos (id, doc_id, user_id, util, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: saas_docs; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.saas_docs (id, titulo, conteudo, medias, tipo_acesso, pagina_path, docs_relacionados, ativo, ordem, created_at, updated_at, categoria, exibir_no_faq, votos_util, votos_nao_util) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: saas_faq; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.saas_faq (id, pergunta, categoria, publico, votos, titulo, conteudo, tipo_acesso, pagina_path, pagina_label, medias, faqs_relacionados, ativo, ordem, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: saas_faq_itens; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.saas_faq_itens (id, doc_id, pergunta, resposta, ordem, ativo, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: services; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.services (id, owner_id, tenant_id, name, description, price, duration_min, active, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: subscription_events; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.subscription_events (id, subscription_id, owner_id, event_type, old_plan_id, new_plan_id, created_at, created_by, source, reason, metadata, owner_type, owner_ref) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: subscription_intents_legacy; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.subscription_intents_legacy (id, user_id, email, plan_key, "interval", amount_cents, currency, status, source, notes, created_at, paid_at, tenant_id, created_by_user_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: subscription_intents_personal; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY 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, subscription_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: subscription_intents_tenant; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.subscription_intents_tenant (id, user_id, created_by_user_id, email, plan_id, plan_key, "interval", amount_cents, currency, status, source, notes, created_at, paid_at, tenant_id, subscription_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: subscriptions; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.subscriptions (id, user_id, plan_id, status, current_period_start, current_period_end, cancel_at_period_end, provider, provider_customer_id, provider_subscription_id, created_at, updated_at, tenant_id, plan_key, "interval", source, started_at, canceled_at, activated_at, past_due_since, suspended_at, suspended_reason, cancelled_at, cancel_reason, expired_at) FROM stdin;
|
|
61f81f06-c718-4d52-8063-67c38c1c1df9 aaaaaaaa-0001-0001-0001-000000000001 984c1f29-a975-4208-93ac-2118ed1039b7 active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 \N patient_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
6864f71c-c4d4-4d7e-9897-89a644002b6d aaaaaaaa-0002-0002-0002-000000000002 c56fe2a8-2c17-4048-adc7-ff7fbd89461a active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 \N therapist_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
8716fb6d-372f-4560-98a5-68c40aec96dc aaaaaaaa-0007-0007-0007-000000000007 8c4895a3-e12d-48de-a078-efb8a4ea2eb2 active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 \N supervisor_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
3fc090ba-3e9a-47ef-9711-edf9a3fd1795 aaaaaaaa-0008-0008-0008-000000000008 c56fe2a8-2c17-4048-adc7-ff7fbd89461a active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 \N therapist_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
cc4c4eb4-c9e5-4ce7-a705-9f5dc415fcb4 aaaaaaaa-0009-0009-0009-000000000009 c56fe2a8-2c17-4048-adc7-ff7fbd89461a active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 \N therapist_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
d2516bea-712d-453a-a5ed-9e40456f9aca aaaaaaaa-0010-0010-0010-000000000010 c56fe2a8-2c17-4048-adc7-ff7fbd89461a active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 \N therapist_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
bd6dd2c0-9c50-4939-8fc9-41fd67423a3e \N 01a5867f-0705-4714-ac97-a23470949157 active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 bbbbbbbb-0003-0003-0003-000000000003 clinic_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
505d05fa-a6db-46b7-8cbf-bb6b12fb8e2b \N 01a5867f-0705-4714-ac97-a23470949157 active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 bbbbbbbb-0004-0004-0004-000000000004 clinic_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
27eef221-7db2-442a-99f3-989f910cdcb4 \N 01a5867f-0705-4714-ac97-a23470949157 active 2026-03-23 14:18:08.130849+00 2027-03-23 14:18:08.130849+00 f manual \N \N 2026-03-23 14:18:08.130849+00 2026-03-23 14:18:08.130849+00 bbbbbbbb-0005-0005-0005-000000000005 clinic_free month seed 2026-03-23 14:18:08.130849+00 \N 2026-03-23 14:18:08.130849+00 \N \N \N \N \N \N
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: support_sessions; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.support_sessions (id, tenant_id, admin_id, token, expires_at, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: tenant_feature_exceptions_log; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.tenant_feature_exceptions_log (id, tenant_id, feature_key, enabled, reason, created_by, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: tenant_features; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.tenant_features (tenant_id, feature_key, enabled, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: tenant_invites; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.tenant_invites (id, tenant_id, email, role, token, invited_by, created_at, expires_at, accepted_at, accepted_by, revoked_at, revoked_by) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: tenant_members; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.tenant_members (id, tenant_id, user_id, role, status, created_at) FROM stdin;
|
|
72be63ef-bc2c-4c8e-8522-0c6d64746bbc bbbbbbbb-0002-0002-0002-000000000002 aaaaaaaa-0002-0002-0002-000000000002 tenant_admin active 2026-03-23 10:46:29.876072+00
|
|
07974953-677e-4941-b90f-1ae15ffbbbf6 bbbbbbbb-0003-0003-0003-000000000003 aaaaaaaa-0003-0003-0003-000000000003 tenant_admin active 2026-03-23 10:46:29.876072+00
|
|
11417585-46af-4faa-a34a-dc23a36c5704 bbbbbbbb-0004-0004-0004-000000000004 aaaaaaaa-0004-0004-0004-000000000004 tenant_admin active 2026-03-23 10:46:29.876072+00
|
|
cd22a662-2b16-4cfe-a9e6-15ccb8e7d67e bbbbbbbb-0005-0005-0005-000000000005 aaaaaaaa-0005-0005-0005-000000000005 tenant_admin active 2026-03-23 10:46:29.876072+00
|
|
e40559cd-43af-4547-b447-2cc7bbff5ad7 bbbbbbbb-0005-0005-0005-000000000005 aaaaaaaa-0002-0002-0002-000000000002 therapist active 2026-03-23 10:46:29.876072+00
|
|
0ee00481-77f2-4bc0-ab09-3bc441c03b1b bbbbbbbb-0005-0005-0005-000000000005 aaaaaaaa-0007-0007-0007-000000000007 supervisor active 2026-03-23 14:18:05.215881+00
|
|
344a6ae3-379a-4776-9441-8ac9f8733c99 bbbbbbbb-0005-0005-0005-000000000005 aaaaaaaa-0008-0008-0008-000000000008 therapist active 2026-03-23 14:18:05.215881+00
|
|
aac8e805-da4f-4089-b2e1-0b32b679d0dd bbbbbbbb-0009-0009-0009-000000000009 aaaaaaaa-0009-0009-0009-000000000009 tenant_admin active 2026-03-23 14:18:06.087973+00
|
|
2633ed47-76e8-4a30-8e3c-07bec4f7c9cd bbbbbbbb-0010-0010-0010-000000000010 aaaaaaaa-0010-0010-0010-000000000010 tenant_admin active 2026-03-23 14:18:06.087973+00
|
|
a72fa56d-04e4-4e23-853c-fd4926b263c3 bbbbbbbb-0005-0005-0005-000000000005 aaaaaaaa-0009-0009-0009-000000000009 therapist active 2026-03-23 14:18:06.087973+00
|
|
677f130c-06bd-44d7-b283-844351d65c45 bbbbbbbb-0005-0005-0005-000000000005 aaaaaaaa-0010-0010-0010-000000000010 therapist active 2026-03-23 14:18:06.087973+00
|
|
978ce15a-8dc5-4540-8430-f9e1e19d4952 bbbbbbbb-0004-0004-0004-000000000004 aaaaaaaa-0011-0011-0011-000000000011 clinic_admin active 2026-03-23 14:18:06.087973+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: tenant_modules; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.tenant_modules (id, owner_id, module_id, status, settings, provider, provider_item_id, installed_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: tenants; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.tenants (id, name, created_at, kind) FROM stdin;
|
|
bbbbbbbb-0002-0002-0002-000000000002 Bruno Terapeuta 2026-03-23 10:46:29.876072+00 therapist
|
|
bbbbbbbb-0009-0009-0009-000000000009 Eva Terapeuta 2026-03-23 10:47:12.826179+00 therapist
|
|
bbbbbbbb-0010-0010-0010-000000000010 Felipe Terapeuta 2026-03-23 10:47:12.826179+00 therapist
|
|
bbbbbbbb-0003-0003-0003-000000000003 Clínica Espaço Psi 2026-03-23 10:46:29.876072+00 clinic_coworking
|
|
bbbbbbbb-0004-0004-0004-000000000004 Clínica Mente Sã 2026-03-23 10:46:29.876072+00 clinic_reception
|
|
bbbbbbbb-0005-0005-0005-000000000005 Clínica Bem Estar 2026-03-23 10:46:29.876072+00 clinic_full
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: therapist_payout_records; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.therapist_payout_records (payout_id, financial_record_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: therapist_payouts; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.therapist_payouts (id, owner_id, tenant_id, period_start, period_end, total_sessions, gross_amount, clinic_fee_total, net_amount, status, paid_at, notes, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: user_settings; Type: TABLE DATA; Schema: public; Owner: -
|
|
--
|
|
|
|
COPY public.user_settings (user_id, theme_mode, preset, primary_color, surface_color, menu_mode, created_at, updated_at, layout_variant) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: messages_2026_03_20; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.messages_2026_03_20 (topic, extension, payload, event, private, updated_at, inserted_at, id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: messages_2026_03_21; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.messages_2026_03_21 (topic, extension, payload, event, private, updated_at, inserted_at, id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: messages_2026_03_22; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.messages_2026_03_22 (topic, extension, payload, event, private, updated_at, inserted_at, id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: messages_2026_03_23; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.messages_2026_03_23 (topic, extension, payload, event, private, updated_at, inserted_at, id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: messages_2026_03_24; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.messages_2026_03_24 (topic, extension, payload, event, private, updated_at, inserted_at, id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: messages_2026_03_25; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.messages_2026_03_25 (topic, extension, payload, event, private, updated_at, inserted_at, id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: messages_2026_03_26; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.messages_2026_03_26 (topic, extension, payload, event, private, updated_at, inserted_at, id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: schema_migrations; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.schema_migrations (version, inserted_at) FROM stdin;
|
|
20211116024918 2026-03-23 10:13:17
|
|
20211116045059 2026-03-23 10:13:17
|
|
20211116050929 2026-03-23 10:13:17
|
|
20211116051442 2026-03-23 10:13:17
|
|
20211116212300 2026-03-23 10:13:17
|
|
20211116213355 2026-03-23 10:13:17
|
|
20211116213934 2026-03-23 10:13:17
|
|
20211116214523 2026-03-23 10:13:17
|
|
20211122062447 2026-03-23 10:13:17
|
|
20211124070109 2026-03-23 10:13:17
|
|
20211202204204 2026-03-23 10:13:17
|
|
20211202204605 2026-03-23 10:13:17
|
|
20211210212804 2026-03-23 10:13:17
|
|
20211228014915 2026-03-23 10:13:17
|
|
20220107221237 2026-03-23 10:13:17
|
|
20220228202821 2026-03-23 10:13:17
|
|
20220312004840 2026-03-23 10:13:17
|
|
20220603231003 2026-03-23 10:13:17
|
|
20220603232444 2026-03-23 10:13:17
|
|
20220615214548 2026-03-23 10:13:17
|
|
20220712093339 2026-03-23 10:13:17
|
|
20220908172859 2026-03-23 10:13:17
|
|
20220916233421 2026-03-23 10:13:17
|
|
20230119133233 2026-03-23 10:13:17
|
|
20230128025114 2026-03-23 10:13:17
|
|
20230128025212 2026-03-23 10:13:17
|
|
20230227211149 2026-03-23 10:13:17
|
|
20230228184745 2026-03-23 10:13:17
|
|
20230308225145 2026-03-23 10:13:17
|
|
20230328144023 2026-03-23 10:13:17
|
|
20231018144023 2026-03-23 10:13:17
|
|
20231204144023 2026-03-23 10:13:17
|
|
20231204144024 2026-03-23 10:13:17
|
|
20231204144025 2026-03-23 10:13:17
|
|
20240108234812 2026-03-23 10:13:17
|
|
20240109165339 2026-03-23 10:13:17
|
|
20240227174441 2026-03-23 10:13:17
|
|
20240311171622 2026-03-23 10:13:17
|
|
20240321100241 2026-03-23 10:13:17
|
|
20240401105812 2026-03-23 10:13:17
|
|
20240418121054 2026-03-23 10:13:17
|
|
20240523004032 2026-03-23 10:13:17
|
|
20240618124746 2026-03-23 10:13:18
|
|
20240801235015 2026-03-23 10:13:18
|
|
20240805133720 2026-03-23 10:13:18
|
|
20240827160934 2026-03-23 10:13:18
|
|
20240919163303 2026-03-23 10:13:18
|
|
20240919163305 2026-03-23 10:13:18
|
|
20241019105805 2026-03-23 10:13:18
|
|
20241030150047 2026-03-23 10:13:18
|
|
20241108114728 2026-03-23 10:13:18
|
|
20241121104152 2026-03-23 10:13:18
|
|
20241130184212 2026-03-23 10:13:18
|
|
20241220035512 2026-03-23 10:13:18
|
|
20241220123912 2026-03-23 10:13:18
|
|
20241224161212 2026-03-23 10:13:18
|
|
20250107150512 2026-03-23 10:13:18
|
|
20250110162412 2026-03-23 10:13:18
|
|
20250123174212 2026-03-23 10:13:18
|
|
20250128220012 2026-03-23 10:13:18
|
|
20250506224012 2026-03-23 10:13:18
|
|
20250523164012 2026-03-23 10:13:18
|
|
20250714121412 2026-03-23 10:13:18
|
|
20250905041441 2026-03-23 10:13:18
|
|
20251103001201 2026-03-23 10:13:18
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: subscription; Type: TABLE DATA; Schema: realtime; Owner: -
|
|
--
|
|
|
|
COPY realtime.subscription (id, subscription_id, entity, filters, claims, created_at) FROM stdin;
|
|
91 790a21f6-26c3-11f1-869d-1aaac49dc7b4 public.notifications {"(owner_id,eq,aaaaaaaa-0002-0002-0002-000000000002)"} {"aal": "aal1", "amr": [{"method": "password", "timestamp": 1774265408}], "aud": "authenticated", "exp": 1774276201, "iat": 1774272601, "iss": "http://127.0.0.1:54321/auth/v1", "sub": "aaaaaaaa-0002-0002-0002-000000000002", "role": "authenticated", "email": "terapeuta@agenciapsi.com.br", "phone": "", "session_id": "d545b1ef-1cd2-4b5d-8c10-5aaa55b73347", "app_metadata": {"provider": "email", "providers": ["email"]}, "is_anonymous": false, "user_metadata": {"name": "Bruno Terapeuta"}} 2026-03-23 14:20:41.639749
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: buckets; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.buckets (id, name, owner, created_at, updated_at, public, avif_autodetection, file_size_limit, allowed_mime_types, owner_id, type) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: buckets_analytics; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.buckets_analytics (name, type, format, created_at, updated_at, id, deleted_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: buckets_vectors; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.buckets_vectors (id, type, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: iceberg_namespaces; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.iceberg_namespaces (id, bucket_name, name, created_at, updated_at, metadata, catalog_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: iceberg_tables; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.iceberg_tables (id, namespace_id, bucket_name, name, location, created_at, updated_at, remote_table_id, shard_key, shard_id, catalog_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: migrations; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.migrations (id, name, hash, executed_at) FROM stdin;
|
|
0 create-migrations-table e18db593bcde2aca2a408c4d1100f6abba2195df 2026-03-23 10:13:30.796432
|
|
1 initialmigration 6ab16121fbaa08bbd11b712d05f358f9b555d777 2026-03-23 10:13:30.806948
|
|
2 storage-schema f6a1fa2c93cbcd16d4e487b362e45fca157a8dbd 2026-03-23 10:13:30.810381
|
|
3 pathtoken-column 2cb1b0004b817b29d5b0a971af16bafeede4b70d 2026-03-23 10:13:30.829325
|
|
4 add-migrations-rls 427c5b63fe1c5937495d9c635c263ee7a5905058 2026-03-23 10:13:30.844667
|
|
5 add-size-functions 79e081a1455b63666c1294a440f8ad4b1e6a7f84 2026-03-23 10:13:30.849797
|
|
6 change-column-name-in-get-size ded78e2f1b5d7e616117897e6443a925965b30d2 2026-03-23 10:13:30.853961
|
|
7 add-rls-to-buckets e7e7f86adbc51049f341dfe8d30256c1abca17aa 2026-03-23 10:13:30.857966
|
|
8 add-public-to-buckets fd670db39ed65f9d08b01db09d6202503ca2bab3 2026-03-23 10:13:30.86089
|
|
9 fix-search-function af597a1b590c70519b464a4ab3be54490712796b 2026-03-23 10:13:30.865914
|
|
10 search-files-search-function b595f05e92f7e91211af1bbfe9c6a13bb3391e16 2026-03-23 10:13:30.870596
|
|
11 add-trigger-to-auto-update-updated_at-column 7425bdb14366d1739fa8a18c83100636d74dcaa2 2026-03-23 10:13:30.877495
|
|
12 add-automatic-avif-detection-flag 8e92e1266eb29518b6a4c5313ab8f29dd0d08df9 2026-03-23 10:13:30.887175
|
|
13 add-bucket-custom-limits cce962054138135cd9a8c4bcd531598684b25e7d 2026-03-23 10:13:30.894644
|
|
14 use-bytes-for-max-size 941c41b346f9802b411f06f30e972ad4744dad27 2026-03-23 10:13:30.903415
|
|
15 add-can-insert-object-function 934146bc38ead475f4ef4b555c524ee5d66799e5 2026-03-23 10:13:30.921243
|
|
16 add-version 76debf38d3fd07dcfc747ca49096457d95b1221b 2026-03-23 10:13:30.925814
|
|
17 drop-owner-foreign-key f1cbb288f1b7a4c1eb8c38504b80ae2a0153d101 2026-03-23 10:13:30.930594
|
|
18 add_owner_id_column_deprecate_owner e7a511b379110b08e2f214be852c35414749fe66 2026-03-23 10:13:30.935872
|
|
19 alter-default-value-objects-id 02e5e22a78626187e00d173dc45f58fa66a4f043 2026-03-23 10:13:30.945545
|
|
20 list-objects-with-delimiter cd694ae708e51ba82bf012bba00caf4f3b6393b7 2026-03-23 10:13:30.949803
|
|
21 s3-multipart-uploads 8c804d4a566c40cd1e4cc5b3725a664a9303657f 2026-03-23 10:13:30.956077
|
|
22 s3-multipart-uploads-big-ints 9737dc258d2397953c9953d9b86920b8be0cdb73 2026-03-23 10:13:30.986283
|
|
23 optimize-search-function 9d7e604cddc4b56a5422dc68c9313f4a1b6f132c 2026-03-23 10:13:30.995314
|
|
24 operation-function 8312e37c2bf9e76bbe841aa5fda889206d2bf8aa 2026-03-23 10:13:31.001863
|
|
25 custom-metadata d974c6057c3db1c1f847afa0e291e6165693b990 2026-03-23 10:13:31.005106
|
|
26 objects-prefixes 215cabcb7f78121892a5a2037a09fedf9a1ae322 2026-03-23 10:13:31.010242
|
|
27 search-v2 859ba38092ac96eb3964d83bf53ccc0b141663a6 2026-03-23 10:13:31.021533
|
|
28 object-bucket-name-sorting c73a2b5b5d4041e39705814fd3a1b95502d38ce4 2026-03-23 10:13:31.025092
|
|
29 create-prefixes ad2c1207f76703d11a9f9007f821620017a66c21 2026-03-23 10:13:31.028503
|
|
30 update-object-levels 2be814ff05c8252fdfdc7cfb4b7f5c7e17f0bed6 2026-03-23 10:13:31.031493
|
|
31 objects-level-index b40367c14c3440ec75f19bbce2d71e914ddd3da0 2026-03-23 10:13:31.033332
|
|
32 backward-compatible-index-on-objects e0c37182b0f7aee3efd823298fb3c76f1042c0f7 2026-03-23 10:13:31.035585
|
|
33 backward-compatible-index-on-prefixes b480e99ed951e0900f033ec4eb34b5bdcb4e3d49 2026-03-23 10:13:31.043153
|
|
34 optimize-search-function-v1 ca80a3dc7bfef894df17108785ce29a7fc8ee456 2026-03-23 10:13:31.045135
|
|
35 add-insert-trigger-prefixes 458fe0ffd07ec53f5e3ce9df51bfdf4861929ccc 2026-03-23 10:13:31.047011
|
|
36 optimise-existing-functions 6ae5fca6af5c55abe95369cd4f93985d1814ca8f 2026-03-23 10:13:31.049187
|
|
37 add-bucket-name-length-trigger 3944135b4e3e8b22d6d4cbb568fe3b0b51df15c1 2026-03-23 10:13:31.052127
|
|
38 iceberg-catalog-flag-on-buckets 02716b81ceec9705aed84aa1501657095b32e5c5 2026-03-23 10:13:31.056547
|
|
39 add-search-v2-sort-support 6706c5f2928846abee18461279799ad12b279b78 2026-03-23 10:13:31.071273
|
|
40 fix-prefix-race-conditions-optimized 7ad69982ae2d372b21f48fc4829ae9752c518f6b 2026-03-23 10:13:31.073508
|
|
41 add-object-level-update-trigger 07fcf1a22165849b7a029deed059ffcde08d1ae0 2026-03-23 10:13:31.075277
|
|
42 rollback-prefix-triggers 771479077764adc09e2ea2043eb627503c034cd4 2026-03-23 10:13:31.07699
|
|
43 fix-object-level 84b35d6caca9d937478ad8a797491f38b8c2979f 2026-03-23 10:13:31.079645
|
|
44 vector-bucket-type 99c20c0ffd52bb1ff1f32fb992f3b351e3ef8fb3 2026-03-23 10:13:31.081463
|
|
45 vector-buckets 049e27196d77a7cb76497a85afae669d8b230953 2026-03-23 10:13:31.084341
|
|
46 buckets-objects-grants fedeb96d60fefd8e02ab3ded9fbde05632f84aed 2026-03-23 10:13:31.090554
|
|
47 iceberg-table-metadata 649df56855c24d8b36dd4cc1aeb8251aa9ad42c2 2026-03-23 10:13:31.09725
|
|
48 iceberg-catalog-ids e0e8b460c609b9999ccd0df9ad14294613eed939 2026-03-23 10:13:31.106653
|
|
49 buckets-objects-grants-postgres 072b1195d0d5a2f888af6b2302a1938dd94b8b3d 2026-03-23 10:13:31.134859
|
|
50 search-v2-optimised 6323ac4f850aa14e7387eb32102869578b5bd478 2026-03-23 10:13:31.141562
|
|
51 index-backward-compatible-search 2ee395d433f76e38bcd3856debaf6e0e5b674011 2026-03-23 10:13:31.236273
|
|
52 drop-not-used-indexes-and-functions bb0cbc7f2206a5a41113363dd22556cc1afd6327 2026-03-23 10:13:31.237617
|
|
53 drop-index-lower-name d0cb18777d9e2a98ebe0bc5cc7a42e57ebe41854 2026-03-23 10:13:31.243999
|
|
54 drop-index-object-level 6289e048b1472da17c31a7eba1ded625a6457e67 2026-03-23 10:13:31.24577
|
|
55 prevent-direct-deletes 262a4798d5e0f2e7c8970232e03ce8be695d5819 2026-03-23 10:13:31.247132
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: objects; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.objects (id, bucket_id, name, owner, created_at, updated_at, last_accessed_at, metadata, version, owner_id, user_metadata) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: s3_multipart_uploads; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.s3_multipart_uploads (id, in_progress_size, upload_signature, bucket_id, key, version, owner_id, created_at, user_metadata) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: s3_multipart_uploads_parts; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.s3_multipart_uploads_parts (id, upload_id, size, part_number, bucket_id, key, etag, owner_id, version, created_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: vector_indexes; Type: TABLE DATA; Schema: storage; Owner: -
|
|
--
|
|
|
|
COPY storage.vector_indexes (id, name, bucket_id, data_type, dimension, distance_metric, metadata_configuration, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: hooks; Type: TABLE DATA; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
COPY supabase_functions.hooks (id, hook_table_id, hook_name, created_at, request_id) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: migrations; Type: TABLE DATA; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
COPY supabase_functions.migrations (version, inserted_at) FROM stdin;
|
|
initial 2026-03-23 10:13:12.298935+00
|
|
20210809183423_update_grants 2026-03-23 10:13:12.298935+00
|
|
\.
|
|
|
|
|
|
--
|
|
-- Data for Name: secrets; Type: TABLE DATA; Schema: vault; Owner: -
|
|
--
|
|
|
|
COPY vault.secrets (id, name, description, secret, key_id, nonce, created_at, updated_at) FROM stdin;
|
|
\.
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens_id_seq; Type: SEQUENCE SET; Schema: auth; Owner: -
|
|
--
|
|
|
|
SELECT pg_catalog.setval('auth.refresh_tokens_id_seq', 5, true);
|
|
|
|
|
|
--
|
|
-- Name: jobid_seq; Type: SEQUENCE SET; Schema: cron; Owner: -
|
|
--
|
|
|
|
SELECT pg_catalog.setval('cron.jobid_seq', 1, false);
|
|
|
|
|
|
--
|
|
-- Name: runid_seq; Type: SEQUENCE SET; Schema: cron; Owner: -
|
|
--
|
|
|
|
SELECT pg_catalog.setval('cron.runid_seq', 1, false);
|
|
|
|
|
|
--
|
|
-- Name: _db_migrations_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
|
|
--
|
|
|
|
SELECT pg_catalog.setval('public._db_migrations_id_seq', 15, true);
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
|
|
--
|
|
|
|
SELECT pg_catalog.setval('public.agenda_online_slots_id_seq', 1, false);
|
|
|
|
|
|
--
|
|
-- Name: subscription_id_seq; Type: SEQUENCE SET; Schema: realtime; Owner: -
|
|
--
|
|
|
|
SELECT pg_catalog.setval('realtime.subscription_id_seq', 91, true);
|
|
|
|
|
|
--
|
|
-- Name: hooks_id_seq; Type: SEQUENCE SET; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
SELECT pg_catalog.setval('supabase_functions.hooks_id_seq', 1, false);
|
|
|
|
|
|
--
|
|
-- Name: extensions extensions_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY _realtime.extensions
|
|
ADD CONSTRAINT extensions_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY _realtime.schema_migrations
|
|
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
|
|
|
|
|
--
|
|
-- Name: tenants tenants_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY _realtime.tenants
|
|
ADD CONSTRAINT tenants_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: mfa_amr_claims amr_id_pk; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.mfa_amr_claims
|
|
ADD CONSTRAINT amr_id_pk PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: audit_log_entries audit_log_entries_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.audit_log_entries
|
|
ADD CONSTRAINT audit_log_entries_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: flow_state flow_state_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.flow_state
|
|
ADD CONSTRAINT flow_state_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: identities identities_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.identities
|
|
ADD CONSTRAINT identities_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: identities identities_provider_id_provider_unique; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.identities
|
|
ADD CONSTRAINT identities_provider_id_provider_unique UNIQUE (provider_id, provider);
|
|
|
|
|
|
--
|
|
-- Name: instances instances_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.instances
|
|
ADD CONSTRAINT instances_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: mfa_amr_claims mfa_amr_claims_session_id_authentication_method_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.mfa_amr_claims
|
|
ADD CONSTRAINT mfa_amr_claims_session_id_authentication_method_pkey UNIQUE (session_id, authentication_method);
|
|
|
|
|
|
--
|
|
-- Name: mfa_challenges mfa_challenges_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.mfa_challenges
|
|
ADD CONSTRAINT mfa_challenges_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: mfa_factors mfa_factors_last_challenged_at_key; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.mfa_factors
|
|
ADD CONSTRAINT mfa_factors_last_challenged_at_key UNIQUE (last_challenged_at);
|
|
|
|
|
|
--
|
|
-- Name: mfa_factors mfa_factors_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.mfa_factors
|
|
ADD CONSTRAINT mfa_factors_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: oauth_authorizations oauth_authorizations_authorization_code_key; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_authorizations
|
|
ADD CONSTRAINT oauth_authorizations_authorization_code_key UNIQUE (authorization_code);
|
|
|
|
|
|
--
|
|
-- Name: oauth_authorizations oauth_authorizations_authorization_id_key; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_authorizations
|
|
ADD CONSTRAINT oauth_authorizations_authorization_id_key UNIQUE (authorization_id);
|
|
|
|
|
|
--
|
|
-- Name: oauth_authorizations oauth_authorizations_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_authorizations
|
|
ADD CONSTRAINT oauth_authorizations_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: oauth_client_states oauth_client_states_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_client_states
|
|
ADD CONSTRAINT oauth_client_states_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: oauth_clients oauth_clients_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_clients
|
|
ADD CONSTRAINT oauth_clients_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: oauth_consents oauth_consents_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_consents
|
|
ADD CONSTRAINT oauth_consents_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: oauth_consents oauth_consents_user_client_unique; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_consents
|
|
ADD CONSTRAINT oauth_consents_user_client_unique UNIQUE (user_id, client_id);
|
|
|
|
|
|
--
|
|
-- Name: one_time_tokens one_time_tokens_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.one_time_tokens
|
|
ADD CONSTRAINT one_time_tokens_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens refresh_tokens_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.refresh_tokens
|
|
ADD CONSTRAINT refresh_tokens_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens refresh_tokens_token_unique; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.refresh_tokens
|
|
ADD CONSTRAINT refresh_tokens_token_unique UNIQUE (token);
|
|
|
|
|
|
--
|
|
-- Name: saml_providers saml_providers_entity_id_key; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.saml_providers
|
|
ADD CONSTRAINT saml_providers_entity_id_key UNIQUE (entity_id);
|
|
|
|
|
|
--
|
|
-- Name: saml_providers saml_providers_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.saml_providers
|
|
ADD CONSTRAINT saml_providers_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: saml_relay_states saml_relay_states_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.saml_relay_states
|
|
ADD CONSTRAINT saml_relay_states_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.schema_migrations
|
|
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
|
|
|
|
|
--
|
|
-- Name: sessions sessions_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.sessions
|
|
ADD CONSTRAINT sessions_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: sso_domains sso_domains_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.sso_domains
|
|
ADD CONSTRAINT sso_domains_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: sso_providers sso_providers_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.sso_providers
|
|
ADD CONSTRAINT sso_providers_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: users users_phone_key; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.users
|
|
ADD CONSTRAINT users_phone_key UNIQUE (phone);
|
|
|
|
|
|
--
|
|
-- Name: users users_pkey; Type: CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.users
|
|
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: _db_migrations _db_migrations_filename_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public._db_migrations
|
|
ADD CONSTRAINT _db_migrations_filename_key UNIQUE (filename);
|
|
|
|
|
|
--
|
|
-- Name: _db_migrations _db_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public._db_migrations
|
|
ADD CONSTRAINT _db_migrations_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: addon_credits addon_credits_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_credits
|
|
ADD CONSTRAINT addon_credits_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: addon_products addon_products_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_products
|
|
ADD CONSTRAINT addon_products_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: addon_products addon_products_slug_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_products
|
|
ADD CONSTRAINT addon_products_slug_key UNIQUE (slug);
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions addon_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_transactions
|
|
ADD CONSTRAINT addon_transactions_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios agenda_bloqueios_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_bloqueios
|
|
ADD CONSTRAINT agenda_bloqueios_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes agenda_configuracoes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_configuracoes
|
|
ADD CONSTRAINT agenda_configuracoes_pkey PRIMARY KEY (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_eventos
|
|
ADD CONSTRAINT agenda_eventos_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_sem_sobreposicao; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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 &&);
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes agenda_excecoes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_excecoes
|
|
ADD CONSTRAINT agenda_excecoes_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots agenda_online_slots_owner_id_weekday_time_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_online_slots
|
|
ADD CONSTRAINT agenda_online_slots_owner_id_weekday_time_key UNIQUE (owner_id, weekday, "time");
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots agenda_online_slots_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_online_slots
|
|
ADD CONSTRAINT agenda_online_slots_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais agenda_regras_semanais_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_regras_semanais
|
|
ADD CONSTRAINT agenda_regras_semanais_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais agenda_regras_semanais_unique; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_regras_semanais
|
|
ADD CONSTRAINT agenda_regras_semanais_unique UNIQUE (owner_id, dia_semana, hora_inicio, hora_fim, modalidade);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais agenda_slots_bloqueados_seman_owner_id_dia_semana_hora_inic_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais agenda_slots_bloqueados_semanais_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_slots_bloqueados_semanais
|
|
ADD CONSTRAINT agenda_slots_bloqueados_semanais_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_regras agenda_slots_regras_owner_id_dia_semana_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_slots_regras
|
|
ADD CONSTRAINT agenda_slots_regras_owner_id_dia_semana_key UNIQUE (owner_id, dia_semana);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_regras agenda_slots_regras_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_slots_regras
|
|
ADD CONSTRAINT agenda_slots_regras_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes agendador_configuracoes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agendador_configuracoes
|
|
ADD CONSTRAINT agendador_configuracoes_pkey PRIMARY KEY (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes agendador_solicitacoes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agendador_solicitacoes
|
|
ADD CONSTRAINT agendador_solicitacoes_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: billing_contracts billing_contracts_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.billing_contracts
|
|
ADD CONSTRAINT billing_contracts_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: commitment_services commitment_services_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.commitment_services
|
|
ADD CONSTRAINT commitment_services_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs commitment_time_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.commitment_time_logs
|
|
ADD CONSTRAINT commitment_time_logs_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: company_profiles company_profiles_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.company_profiles
|
|
ADD CONSTRAINT company_profiles_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: company_profiles company_profiles_tenant_id_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.company_profiles
|
|
ADD CONSTRAINT company_profiles_tenant_id_key UNIQUE (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields determined_commitment_fields_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.determined_commitment_fields
|
|
ADD CONSTRAINT determined_commitment_fields_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments determined_commitments_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.determined_commitments
|
|
ADD CONSTRAINT determined_commitments_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments determined_commitments_tenant_native_key_uq; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.determined_commitments
|
|
ADD CONSTRAINT determined_commitments_tenant_native_key_uq UNIQUE (tenant_id, native_key);
|
|
|
|
|
|
--
|
|
-- Name: dev_user_credentials dev_user_credentials_email_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.dev_user_credentials
|
|
ADD CONSTRAINT dev_user_credentials_email_key UNIQUE (email);
|
|
|
|
|
|
--
|
|
-- Name: dev_user_credentials dev_user_credentials_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.dev_user_credentials
|
|
ADD CONSTRAINT dev_user_credentials_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: email_layout_config email_layout_config_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_layout_config
|
|
ADD CONSTRAINT email_layout_config_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: email_layout_config email_layout_config_tenant_id_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_layout_config
|
|
ADD CONSTRAINT email_layout_config_tenant_id_key UNIQUE (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: email_templates_global email_templates_global_key_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_templates_global
|
|
ADD CONSTRAINT email_templates_global_key_key UNIQUE (key);
|
|
|
|
|
|
--
|
|
-- Name: email_templates_global email_templates_global_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_templates_global
|
|
ADD CONSTRAINT email_templates_global_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: email_templates_tenant email_templates_tenant_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_templates_tenant
|
|
ADD CONSTRAINT email_templates_tenant_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: email_templates_tenant email_templates_tenant_tenant_id_owner_id_template_key_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_templates_tenant
|
|
ADD CONSTRAINT email_templates_tenant_tenant_id_owner_id_template_key_key UNIQUE (tenant_id, owner_id, template_key);
|
|
|
|
|
|
--
|
|
-- Name: entitlements_invalidation entitlements_invalidation_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.entitlements_invalidation
|
|
ADD CONSTRAINT entitlements_invalidation_pkey PRIMARY KEY (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: features features_key_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.features
|
|
ADD CONSTRAINT features_key_key UNIQUE (key);
|
|
|
|
|
|
--
|
|
-- Name: features features_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.features
|
|
ADD CONSTRAINT features_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.feriados
|
|
ADD CONSTRAINT feriados_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_tenant_id_data_nome_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.feriados
|
|
ADD CONSTRAINT feriados_tenant_id_data_nome_key UNIQUE (tenant_id, data, nome);
|
|
|
|
|
|
--
|
|
-- Name: financial_categories financial_categories_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_categories
|
|
ADD CONSTRAINT financial_categories_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: financial_exceptions financial_exceptions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_exceptions
|
|
ADD CONSTRAINT financial_exceptions_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_records
|
|
ADD CONSTRAINT financial_records_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: global_notices global_notices_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.global_notices
|
|
ADD CONSTRAINT global_notices_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: insurance_plan_services insurance_plan_services_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.insurance_plan_services
|
|
ADD CONSTRAINT insurance_plan_services_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: insurance_plans insurance_plans_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.insurance_plans
|
|
ADD CONSTRAINT insurance_plans_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: login_carousel_slides login_carousel_slides_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.login_carousel_slides
|
|
ADD CONSTRAINT login_carousel_slides_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: module_features module_features_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.module_features
|
|
ADD CONSTRAINT module_features_pkey PRIMARY KEY (module_id, feature_id);
|
|
|
|
|
|
--
|
|
-- Name: modules modules_key_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.modules
|
|
ADD CONSTRAINT modules_key_key UNIQUE (key);
|
|
|
|
|
|
--
|
|
-- Name: modules modules_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.modules
|
|
ADD CONSTRAINT modules_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: notice_dismissals notice_dismissals_notice_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notice_dismissals
|
|
ADD CONSTRAINT notice_dismissals_notice_id_user_id_key UNIQUE (notice_id, user_id);
|
|
|
|
|
|
--
|
|
-- Name: notice_dismissals notice_dismissals_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notice_dismissals
|
|
ADD CONSTRAINT notice_dismissals_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: notification_channels notification_channels_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_channels
|
|
ADD CONSTRAINT notification_channels_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: notification_logs notification_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_logs
|
|
ADD CONSTRAINT notification_logs_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: notification_preferences notification_preferences_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_preferences
|
|
ADD CONSTRAINT notification_preferences_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: notification_queue notification_queue_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_queue
|
|
ADD CONSTRAINT notification_queue_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: notification_schedules notification_schedules_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_schedules
|
|
ADD CONSTRAINT notification_schedules_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: notification_templates notification_templates_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_templates
|
|
ADD CONSTRAINT notification_templates_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: notifications notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notifications
|
|
ADD CONSTRAINT notifications_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: owner_users owner_users_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.owner_users
|
|
ADD CONSTRAINT owner_users_pkey PRIMARY KEY (owner_id, user_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_discounts patient_discounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_discounts
|
|
ADD CONSTRAINT patient_discounts_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: patient_group_patient patient_group_patient_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_group_patient
|
|
ADD CONSTRAINT patient_group_patient_pkey PRIMARY KEY (patient_group_id, patient_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_groups patient_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_groups
|
|
ADD CONSTRAINT patient_groups_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests patient_intake_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_intake_requests
|
|
ADD CONSTRAINT patient_intake_requests_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: patient_invites patient_invites_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_invites
|
|
ADD CONSTRAINT patient_invites_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: patient_invites patient_invites_token_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_invites
|
|
ADD CONSTRAINT patient_invites_token_key UNIQUE (token);
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag patient_patient_tag_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_patient_tag
|
|
ADD CONSTRAINT patient_patient_tag_pkey PRIMARY KEY (patient_id, tag_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_tags patient_tags_owner_name_uniq; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_tags
|
|
ADD CONSTRAINT patient_tags_owner_name_uniq UNIQUE (owner_id, nome);
|
|
|
|
|
|
--
|
|
-- Name: patient_tags patient_tags_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_tags
|
|
ADD CONSTRAINT patient_tags_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: patients patients_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patients
|
|
ADD CONSTRAINT patients_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: payment_settings payment_settings_owner_id_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.payment_settings
|
|
ADD CONSTRAINT payment_settings_owner_id_key UNIQUE (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: payment_settings payment_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.payment_settings
|
|
ADD CONSTRAINT payment_settings_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: plan_features plan_features_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plan_features
|
|
ADD CONSTRAINT plan_features_pkey PRIMARY KEY (plan_id, feature_id);
|
|
|
|
|
|
--
|
|
-- Name: plan_prices plan_prices_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plan_prices
|
|
ADD CONSTRAINT plan_prices_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: plan_public_bullets plan_public_bullets_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plan_public_bullets
|
|
ADD CONSTRAINT plan_public_bullets_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: plan_public plan_public_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plan_public
|
|
ADD CONSTRAINT plan_public_pkey PRIMARY KEY (plan_id);
|
|
|
|
|
|
--
|
|
-- Name: plans plans_key_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plans
|
|
ADD CONSTRAINT plans_key_key UNIQUE (key);
|
|
|
|
|
|
--
|
|
-- Name: plans plans_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plans
|
|
ADD CONSTRAINT plans_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: professional_pricing professional_pricing_owner_commitment_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.professional_pricing
|
|
ADD CONSTRAINT professional_pricing_owner_commitment_key UNIQUE (owner_id, determined_commitment_id);
|
|
|
|
|
|
--
|
|
-- Name: professional_pricing professional_pricing_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.professional_pricing
|
|
ADD CONSTRAINT professional_pricing_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: profiles profiles_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.profiles
|
|
ADD CONSTRAINT profiles_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exceptions recurrence_exceptions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.recurrence_exceptions
|
|
ADD CONSTRAINT recurrence_exceptions_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exceptions recurrence_exceptions_unique; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.recurrence_exceptions
|
|
ADD CONSTRAINT recurrence_exceptions_unique UNIQUE (recurrence_id, original_date);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services recurrence_rule_services_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.recurrence_rule_services
|
|
ADD CONSTRAINT recurrence_rule_services_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules recurrence_rules_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.recurrence_rules
|
|
ADD CONSTRAINT recurrence_rules_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: saas_admins saas_admins_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.saas_admins
|
|
ADD CONSTRAINT saas_admins_pkey PRIMARY KEY (user_id);
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos saas_doc_votos_doc_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.saas_doc_votos
|
|
ADD CONSTRAINT saas_doc_votos_doc_id_user_id_key UNIQUE (doc_id, user_id);
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos saas_doc_votos_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.saas_doc_votos
|
|
ADD CONSTRAINT saas_doc_votos_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: saas_docs saas_docs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.saas_docs
|
|
ADD CONSTRAINT saas_docs_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_itens saas_faq_itens_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.saas_faq_itens
|
|
ADD CONSTRAINT saas_faq_itens_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq saas_faq_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.saas_faq
|
|
ADD CONSTRAINT saas_faq_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: services services_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.services
|
|
ADD CONSTRAINT services_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: subscription_events subscription_events_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.subscription_events
|
|
ADD CONSTRAINT subscription_events_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_personal subscription_intents_personal_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.subscription_intents_personal
|
|
ADD CONSTRAINT subscription_intents_personal_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_legacy subscription_intents_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.subscription_intents_legacy
|
|
ADD CONSTRAINT subscription_intents_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_tenant subscription_intents_tenant_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.subscription_intents_tenant
|
|
ADD CONSTRAINT subscription_intents_tenant_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.subscriptions
|
|
ADD CONSTRAINT subscriptions_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: support_sessions support_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.support_sessions
|
|
ADD CONSTRAINT support_sessions_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: support_sessions support_sessions_token_unique; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.support_sessions
|
|
ADD CONSTRAINT support_sessions_token_unique UNIQUE (token);
|
|
|
|
|
|
--
|
|
-- Name: tenant_feature_exceptions_log tenant_feature_exceptions_log_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_feature_exceptions_log
|
|
ADD CONSTRAINT tenant_feature_exceptions_log_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: tenant_features tenant_features_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_features
|
|
ADD CONSTRAINT tenant_features_pkey PRIMARY KEY (tenant_id, feature_key);
|
|
|
|
|
|
--
|
|
-- Name: tenant_invites tenant_invites_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_invites
|
|
ADD CONSTRAINT tenant_invites_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: tenant_members tenant_members_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_members
|
|
ADD CONSTRAINT tenant_members_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: tenant_members tenant_members_tenant_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_members
|
|
ADD CONSTRAINT tenant_members_tenant_id_user_id_key UNIQUE (tenant_id, user_id);
|
|
|
|
|
|
--
|
|
-- Name: tenant_modules tenant_modules_owner_id_module_id_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_modules
|
|
ADD CONSTRAINT tenant_modules_owner_id_module_id_key UNIQUE (owner_id, module_id);
|
|
|
|
|
|
--
|
|
-- Name: tenant_modules tenant_modules_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_modules
|
|
ADD CONSTRAINT tenant_modules_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: tenants tenants_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenants
|
|
ADD CONSTRAINT tenants_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: therapist_payout_records therapist_payout_records_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.therapist_payout_records
|
|
ADD CONSTRAINT therapist_payout_records_pkey PRIMARY KEY (payout_id, financial_record_id);
|
|
|
|
|
|
--
|
|
-- Name: therapist_payouts therapist_payouts_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.therapist_payouts
|
|
ADD CONSTRAINT therapist_payouts_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: addon_credits uq_addon_credits_tenant_type; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_credits
|
|
ADD CONSTRAINT uq_addon_credits_tenant_type UNIQUE (tenant_id, addon_type);
|
|
|
|
|
|
--
|
|
-- Name: notification_channels uq_channel_per_owner; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_channels
|
|
ADD CONSTRAINT uq_channel_per_owner UNIQUE NULLS NOT DISTINCT (owner_id, channel, deleted_at);
|
|
|
|
|
|
--
|
|
-- Name: notification_preferences uq_notif_prefs_patient_owner; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_preferences
|
|
ADD CONSTRAINT uq_notif_prefs_patient_owner UNIQUE NULLS NOT DISTINCT (owner_id, patient_id, deleted_at);
|
|
|
|
|
|
--
|
|
-- Name: notification_queue uq_notif_queue_idempotency; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_queue
|
|
ADD CONSTRAINT uq_notif_queue_idempotency UNIQUE (idempotency_key);
|
|
|
|
|
|
--
|
|
-- Name: notification_schedules uq_notif_schedule_owner; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_schedules
|
|
ADD CONSTRAINT uq_notif_schedule_owner UNIQUE NULLS NOT DISTINCT (owner_id, schedule_key, deleted_at);
|
|
|
|
|
|
--
|
|
-- Name: notification_templates uq_notif_template_key; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_templates
|
|
ADD CONSTRAINT uq_notif_template_key UNIQUE NULLS NOT DISTINCT (tenant_id, owner_id, key, deleted_at);
|
|
|
|
|
|
--
|
|
-- Name: user_settings user_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.user_settings
|
|
ADD CONSTRAINT user_settings_pkey PRIMARY KEY (user_id);
|
|
|
|
|
|
--
|
|
-- Name: messages messages_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages
|
|
ADD CONSTRAINT messages_pkey PRIMARY KEY (id, inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_20 messages_2026_03_20_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages_2026_03_20
|
|
ADD CONSTRAINT messages_2026_03_20_pkey PRIMARY KEY (id, inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_21 messages_2026_03_21_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages_2026_03_21
|
|
ADD CONSTRAINT messages_2026_03_21_pkey PRIMARY KEY (id, inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_22 messages_2026_03_22_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages_2026_03_22
|
|
ADD CONSTRAINT messages_2026_03_22_pkey PRIMARY KEY (id, inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_23 messages_2026_03_23_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages_2026_03_23
|
|
ADD CONSTRAINT messages_2026_03_23_pkey PRIMARY KEY (id, inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_24 messages_2026_03_24_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages_2026_03_24
|
|
ADD CONSTRAINT messages_2026_03_24_pkey PRIMARY KEY (id, inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_25 messages_2026_03_25_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages_2026_03_25
|
|
ADD CONSTRAINT messages_2026_03_25_pkey PRIMARY KEY (id, inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_26 messages_2026_03_26_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.messages_2026_03_26
|
|
ADD CONSTRAINT messages_2026_03_26_pkey PRIMARY KEY (id, inserted_at);
|
|
|
|
|
|
--
|
|
-- Name: subscription pk_subscription; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.subscription
|
|
ADD CONSTRAINT pk_subscription PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY realtime.schema_migrations
|
|
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
|
|
|
|
|
--
|
|
-- Name: buckets_analytics buckets_analytics_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.buckets_analytics
|
|
ADD CONSTRAINT buckets_analytics_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: buckets buckets_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.buckets
|
|
ADD CONSTRAINT buckets_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: buckets_vectors buckets_vectors_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.buckets_vectors
|
|
ADD CONSTRAINT buckets_vectors_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: iceberg_namespaces iceberg_namespaces_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.iceberg_namespaces
|
|
ADD CONSTRAINT iceberg_namespaces_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: iceberg_tables iceberg_tables_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.iceberg_tables
|
|
ADD CONSTRAINT iceberg_tables_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: migrations migrations_name_key; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.migrations
|
|
ADD CONSTRAINT migrations_name_key UNIQUE (name);
|
|
|
|
|
|
--
|
|
-- Name: migrations migrations_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.migrations
|
|
ADD CONSTRAINT migrations_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: objects objects_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.objects
|
|
ADD CONSTRAINT objects_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads_parts s3_multipart_uploads_parts_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.s3_multipart_uploads_parts
|
|
ADD CONSTRAINT s3_multipart_uploads_parts_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads s3_multipart_uploads_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.s3_multipart_uploads
|
|
ADD CONSTRAINT s3_multipart_uploads_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: vector_indexes vector_indexes_pkey; Type: CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.vector_indexes
|
|
ADD CONSTRAINT vector_indexes_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: hooks hooks_pkey; Type: CONSTRAINT; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY supabase_functions.hooks
|
|
ADD CONSTRAINT hooks_pkey PRIMARY KEY (id);
|
|
|
|
|
|
--
|
|
-- Name: migrations migrations_pkey; Type: CONSTRAINT; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY supabase_functions.migrations
|
|
ADD CONSTRAINT migrations_pkey PRIMARY KEY (version);
|
|
|
|
|
|
--
|
|
-- Name: extensions_tenant_external_id_index; Type: INDEX; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX extensions_tenant_external_id_index ON _realtime.extensions USING btree (tenant_external_id);
|
|
|
|
|
|
--
|
|
-- Name: extensions_tenant_external_id_type_index; Type: INDEX; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX extensions_tenant_external_id_type_index ON _realtime.extensions USING btree (tenant_external_id, type);
|
|
|
|
|
|
--
|
|
-- Name: tenants_external_id_index; Type: INDEX; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX tenants_external_id_index ON _realtime.tenants USING btree (external_id);
|
|
|
|
|
|
--
|
|
-- Name: audit_logs_instance_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX audit_logs_instance_id_idx ON auth.audit_log_entries USING btree (instance_id);
|
|
|
|
|
|
--
|
|
-- Name: confirmation_token_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX confirmation_token_idx ON auth.users USING btree (confirmation_token) WHERE ((confirmation_token)::text !~ '^[0-9 ]*$'::text);
|
|
|
|
|
|
--
|
|
-- Name: email_change_token_current_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX email_change_token_current_idx ON auth.users USING btree (email_change_token_current) WHERE ((email_change_token_current)::text !~ '^[0-9 ]*$'::text);
|
|
|
|
|
|
--
|
|
-- Name: email_change_token_new_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX email_change_token_new_idx ON auth.users USING btree (email_change_token_new) WHERE ((email_change_token_new)::text !~ '^[0-9 ]*$'::text);
|
|
|
|
|
|
--
|
|
-- Name: factor_id_created_at_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX factor_id_created_at_idx ON auth.mfa_factors USING btree (user_id, created_at);
|
|
|
|
|
|
--
|
|
-- Name: flow_state_created_at_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX flow_state_created_at_idx ON auth.flow_state USING btree (created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: identities_email_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX identities_email_idx ON auth.identities USING btree (email text_pattern_ops);
|
|
|
|
|
|
--
|
|
-- Name: INDEX identities_email_idx; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON INDEX auth.identities_email_idx IS 'Auth: Ensures indexed queries on the email column';
|
|
|
|
|
|
--
|
|
-- Name: identities_user_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX identities_user_id_idx ON auth.identities USING btree (user_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_auth_code; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_auth_code ON auth.flow_state USING btree (auth_code);
|
|
|
|
|
|
--
|
|
-- Name: idx_oauth_client_states_created_at; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_oauth_client_states_created_at ON auth.oauth_client_states USING btree (created_at);
|
|
|
|
|
|
--
|
|
-- Name: idx_user_id_auth_method; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_user_id_auth_method ON auth.flow_state USING btree (user_id, authentication_method);
|
|
|
|
|
|
--
|
|
-- Name: mfa_challenge_created_at_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX mfa_challenge_created_at_idx ON auth.mfa_challenges USING btree (created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: mfa_factors_user_friendly_name_unique; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX mfa_factors_user_friendly_name_unique ON auth.mfa_factors USING btree (friendly_name, user_id) WHERE (TRIM(BOTH FROM friendly_name) <> ''::text);
|
|
|
|
|
|
--
|
|
-- Name: mfa_factors_user_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX mfa_factors_user_id_idx ON auth.mfa_factors USING btree (user_id);
|
|
|
|
|
|
--
|
|
-- Name: oauth_auth_pending_exp_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX oauth_auth_pending_exp_idx ON auth.oauth_authorizations USING btree (expires_at) WHERE (status = 'pending'::auth.oauth_authorization_status);
|
|
|
|
|
|
--
|
|
-- Name: oauth_clients_deleted_at_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX oauth_clients_deleted_at_idx ON auth.oauth_clients USING btree (deleted_at);
|
|
|
|
|
|
--
|
|
-- Name: oauth_consents_active_client_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX oauth_consents_active_client_idx ON auth.oauth_consents USING btree (client_id) WHERE (revoked_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: oauth_consents_active_user_client_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX oauth_consents_active_user_client_idx ON auth.oauth_consents USING btree (user_id, client_id) WHERE (revoked_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: oauth_consents_user_order_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX oauth_consents_user_order_idx ON auth.oauth_consents USING btree (user_id, granted_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: one_time_tokens_relates_to_hash_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX one_time_tokens_relates_to_hash_idx ON auth.one_time_tokens USING hash (relates_to);
|
|
|
|
|
|
--
|
|
-- Name: one_time_tokens_token_hash_hash_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX one_time_tokens_token_hash_hash_idx ON auth.one_time_tokens USING hash (token_hash);
|
|
|
|
|
|
--
|
|
-- Name: one_time_tokens_user_id_token_type_key; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX one_time_tokens_user_id_token_type_key ON auth.one_time_tokens USING btree (user_id, token_type);
|
|
|
|
|
|
--
|
|
-- Name: reauthentication_token_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX reauthentication_token_idx ON auth.users USING btree (reauthentication_token) WHERE ((reauthentication_token)::text !~ '^[0-9 ]*$'::text);
|
|
|
|
|
|
--
|
|
-- Name: recovery_token_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX recovery_token_idx ON auth.users USING btree (recovery_token) WHERE ((recovery_token)::text !~ '^[0-9 ]*$'::text);
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens_instance_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX refresh_tokens_instance_id_idx ON auth.refresh_tokens USING btree (instance_id);
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens_instance_id_user_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX refresh_tokens_instance_id_user_id_idx ON auth.refresh_tokens USING btree (instance_id, user_id);
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens_parent_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX refresh_tokens_parent_idx ON auth.refresh_tokens USING btree (parent);
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens_session_id_revoked_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX refresh_tokens_session_id_revoked_idx ON auth.refresh_tokens USING btree (session_id, revoked);
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens_updated_at_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX refresh_tokens_updated_at_idx ON auth.refresh_tokens USING btree (updated_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: saml_providers_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saml_providers_sso_provider_id_idx ON auth.saml_providers USING btree (sso_provider_id);
|
|
|
|
|
|
--
|
|
-- Name: saml_relay_states_created_at_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saml_relay_states_created_at_idx ON auth.saml_relay_states USING btree (created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: saml_relay_states_for_email_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saml_relay_states_for_email_idx ON auth.saml_relay_states USING btree (for_email);
|
|
|
|
|
|
--
|
|
-- Name: saml_relay_states_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saml_relay_states_sso_provider_id_idx ON auth.saml_relay_states USING btree (sso_provider_id);
|
|
|
|
|
|
--
|
|
-- Name: sessions_not_after_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sessions_not_after_idx ON auth.sessions USING btree (not_after DESC);
|
|
|
|
|
|
--
|
|
-- Name: sessions_oauth_client_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sessions_oauth_client_id_idx ON auth.sessions USING btree (oauth_client_id);
|
|
|
|
|
|
--
|
|
-- Name: sessions_user_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sessions_user_id_idx ON auth.sessions USING btree (user_id);
|
|
|
|
|
|
--
|
|
-- Name: sso_domains_domain_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX sso_domains_domain_idx ON auth.sso_domains USING btree (lower(domain));
|
|
|
|
|
|
--
|
|
-- Name: sso_domains_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sso_domains_sso_provider_id_idx ON auth.sso_domains USING btree (sso_provider_id);
|
|
|
|
|
|
--
|
|
-- Name: sso_providers_resource_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX sso_providers_resource_id_idx ON auth.sso_providers USING btree (lower(resource_id));
|
|
|
|
|
|
--
|
|
-- Name: sso_providers_resource_id_pattern_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sso_providers_resource_id_pattern_idx ON auth.sso_providers USING btree (resource_id text_pattern_ops);
|
|
|
|
|
|
--
|
|
-- Name: unique_phone_factor_per_user; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX unique_phone_factor_per_user ON auth.mfa_factors USING btree (user_id, phone);
|
|
|
|
|
|
--
|
|
-- Name: user_id_created_at_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX user_id_created_at_idx ON auth.sessions USING btree (user_id, created_at);
|
|
|
|
|
|
--
|
|
-- Name: users_email_partial_key; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX users_email_partial_key ON auth.users USING btree (email) WHERE (is_sso_user = false);
|
|
|
|
|
|
--
|
|
-- Name: INDEX users_email_partial_key; Type: COMMENT; Schema: auth; Owner: -
|
|
--
|
|
|
|
COMMENT ON INDEX auth.users_email_partial_key IS 'Auth: A partial unique index that applies only when is_sso_user is false';
|
|
|
|
|
|
--
|
|
-- Name: users_instance_id_email_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX users_instance_id_email_idx ON auth.users USING btree (instance_id, lower((email)::text));
|
|
|
|
|
|
--
|
|
-- Name: users_instance_id_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX users_instance_id_idx ON auth.users USING btree (instance_id);
|
|
|
|
|
|
--
|
|
-- Name: users_is_anonymous_idx; Type: INDEX; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE INDEX users_is_anonymous_idx ON auth.users USING btree (is_anonymous);
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios_owner_data_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_bloqueios_owner_data_idx ON public.agenda_bloqueios USING btree (owner_id, data_inicio, data_fim);
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios_owner_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_bloqueios_owner_id_idx ON public.agenda_bloqueios USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios_recorrente_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_bloqueios_recorrente_idx ON public.agenda_bloqueios USING btree (owner_id, dia_semana) WHERE (recorrente = true);
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios_tenant_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_bloqueios_tenant_id_idx ON public.agenda_bloqueios USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_configuracoes_tenant_idx ON public.agenda_configuracoes USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes_tenant_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_configuracoes_tenant_owner_idx ON public.agenda_configuracoes USING btree (tenant_id, owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos_billing_contract_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_eventos_billing_contract_idx ON public.agenda_eventos USING btree (billing_contract_id) WHERE (billing_contract_id IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos_insurance_plan_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_eventos_insurance_plan_idx ON public.agenda_eventos USING btree (insurance_plan_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos_owner_inicio_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_eventos_owner_inicio_idx ON public.agenda_eventos USING btree (owner_id, inicio_em);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos_owner_terapeuta_inicio_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_eventos_owner_terapeuta_inicio_idx ON public.agenda_eventos USING btree (owner_id, terapeuta_id, inicio_em);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos_recurrence_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_eventos_recurrence_idx ON public.agenda_eventos USING btree (recurrence_id) WHERE (recurrence_id IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos_tenant_inicio_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_eventos_tenant_inicio_idx ON public.agenda_eventos USING btree (tenant_id, inicio_em);
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos_tenant_owner_inicio_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_eventos_tenant_owner_inicio_idx ON public.agenda_eventos USING btree (tenant_id, owner_id, inicio_em);
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes_owner_data_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_excecoes_owner_data_idx ON public.agenda_excecoes USING btree (owner_id, data);
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_excecoes_tenant_idx ON public.agenda_excecoes USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes_tenant_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_excecoes_tenant_owner_idx ON public.agenda_excecoes USING btree (tenant_id, owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots_owner_weekday_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_online_slots_owner_weekday_idx ON public.agenda_online_slots USING btree (owner_id, weekday);
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_online_slots_tenant_idx ON public.agenda_online_slots USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots_tenant_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_online_slots_tenant_owner_idx ON public.agenda_online_slots USING btree (tenant_id, owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais_owner_dia_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_regras_semanais_owner_dia_idx ON public.agenda_regras_semanais USING btree (owner_id, dia_semana);
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_regras_semanais_tenant_idx ON public.agenda_regras_semanais USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais_tenant_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_regras_semanais_tenant_owner_idx ON public.agenda_regras_semanais USING btree (tenant_id, owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_slots_bloqueados_semanais_tenant_idx ON public.agenda_slots_bloqueados_semanais USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais_tenant_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_slots_bloqueados_semanais_tenant_owner_idx ON public.agenda_slots_bloqueados_semanais USING btree (tenant_id, owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_regras_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_slots_regras_tenant_idx ON public.agenda_slots_regras USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_regras_tenant_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agenda_slots_regras_tenant_owner_idx ON public.agenda_slots_regras USING btree (tenant_id, owner_id);
|
|
|
|
|
|
--
|
|
-- Name: agendador_cfg_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agendador_cfg_tenant_idx ON public.agendador_configuracoes USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: agendador_sol_data_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agendador_sol_data_idx ON public.agendador_solicitacoes USING btree (data_solicitada, hora_solicitada);
|
|
|
|
|
|
--
|
|
-- Name: agendador_sol_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agendador_sol_owner_idx ON public.agendador_solicitacoes USING btree (owner_id, status);
|
|
|
|
|
|
--
|
|
-- Name: agendador_sol_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX agendador_sol_tenant_idx ON public.agendador_solicitacoes USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: billing_contracts_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX billing_contracts_owner_idx ON public.billing_contracts USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: billing_contracts_patient_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX billing_contracts_patient_idx ON public.billing_contracts USING btree (patient_id);
|
|
|
|
|
|
--
|
|
-- Name: billing_contracts_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX billing_contracts_tenant_idx ON public.billing_contracts USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: commitment_services_commitment_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX commitment_services_commitment_idx ON public.commitment_services USING btree (commitment_id);
|
|
|
|
|
|
--
|
|
-- Name: commitment_services_service_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX commitment_services_service_idx ON public.commitment_services USING btree (service_id);
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs_calendar_event_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX commitment_time_logs_calendar_event_idx ON public.commitment_time_logs USING btree (calendar_event_id);
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs_commitment_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX commitment_time_logs_commitment_idx ON public.commitment_time_logs USING btree (commitment_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX commitment_time_logs_tenant_idx ON public.commitment_time_logs USING btree (tenant_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields_commitment_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX determined_commitment_fields_commitment_idx ON public.determined_commitment_fields USING btree (commitment_id, sort_order);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields_key_uniq; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX determined_commitment_fields_key_uniq ON public.determined_commitment_fields USING btree (commitment_id, key);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX determined_commitment_fields_tenant_idx ON public.determined_commitment_fields USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments_active_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX determined_commitments_active_idx ON public.determined_commitments USING btree (tenant_id, active);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX determined_commitments_tenant_idx ON public.determined_commitments USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments_tenant_name_uniq; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX determined_commitments_tenant_name_uniq ON public.determined_commitments USING btree (tenant_id, lower(name));
|
|
|
|
|
|
--
|
|
-- Name: feriados_global_unique; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX feriados_global_unique ON public.feriados USING btree (data, nome) WHERE (tenant_id IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: financial_exceptions_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX financial_exceptions_owner_idx ON public.financial_exceptions USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: financial_exceptions_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX financial_exceptions_tenant_idx ON public.financial_exceptions USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_addon_credits_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_addon_credits_tenant ON public.addon_credits USING btree (tenant_id) WHERE (is_active = true);
|
|
|
|
|
|
--
|
|
-- Name: idx_addon_credits_type; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_addon_credits_type ON public.addon_credits USING btree (addon_type) WHERE (is_active = true);
|
|
|
|
|
|
--
|
|
-- Name: idx_addon_products_active; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_addon_products_active ON public.addon_products USING btree (is_active, is_visible) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_addon_products_type; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_addon_products_type ON public.addon_products USING btree (addon_type) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_addon_tx_created; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_addon_tx_created ON public.addon_transactions USING btree (created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_addon_tx_queue; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_addon_tx_queue ON public.addon_transactions USING btree (queue_id) WHERE (queue_id IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_addon_tx_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_addon_tx_tenant ON public.addon_transactions USING btree (tenant_id, addon_type);
|
|
|
|
|
|
--
|
|
-- Name: idx_addon_tx_type; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_addon_tx_type ON public.addon_transactions USING btree (type);
|
|
|
|
|
|
--
|
|
-- Name: idx_agenda_eventos_determined_commitment_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_agenda_eventos_determined_commitment_id ON public.agenda_eventos USING btree (determined_commitment_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_agenda_excecoes_owner_data; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_agenda_excecoes_owner_data ON public.agenda_excecoes USING btree (owner_id, data);
|
|
|
|
|
|
--
|
|
-- Name: idx_agenda_slots_regras_owner_dia; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_agenda_slots_regras_owner_dia ON public.agenda_slots_regras USING btree (owner_id, dia_semana);
|
|
|
|
|
|
--
|
|
-- Name: idx_email_templates_global_domain; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_email_templates_global_domain ON public.email_templates_global USING btree (domain) WHERE (is_active = true);
|
|
|
|
|
|
--
|
|
-- Name: idx_email_templates_global_key; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_email_templates_global_key ON public.email_templates_global USING btree (key) WHERE (is_active = true);
|
|
|
|
|
|
--
|
|
-- Name: idx_email_templates_tenant_lookup; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_email_templates_tenant_lookup ON public.email_templates_tenant USING btree (tenant_id, template_key) WHERE (enabled = true);
|
|
|
|
|
|
--
|
|
-- Name: idx_email_templates_tenant_owner; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_email_templates_tenant_owner ON public.email_templates_tenant USING btree (owner_id, template_key) WHERE ((enabled = true) AND (owner_id IS NOT NULL));
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_categories_user_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_categories_user_id ON public.financial_categories USING btree (user_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_active; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_active ON public.financial_records USING btree (owner_id, paid_at DESC) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_agenda_evento_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_agenda_evento_id ON public.financial_records USING btree (agenda_evento_id) WHERE (agenda_evento_id IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_category_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_category_id ON public.financial_records USING btree (category_id) WHERE (category_id IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_due_date; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_due_date ON public.financial_records USING btree (due_date);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_installment_group; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_installment_group ON public.financial_records USING btree (installment_group) WHERE (installment_group IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_owner_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_owner_id ON public.financial_records USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_paid_at; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_paid_at ON public.financial_records USING btree (paid_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_patient_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_patient_id ON public.financial_records USING btree (patient_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_status; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_status ON public.financial_records USING btree (status) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_tenant_active; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_tenant_active ON public.financial_records USING btree (tenant_id, paid_at DESC) WHERE ((deleted_at IS NULL) AND (tenant_id IS NOT NULL));
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_tenant_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_tenant_id ON public.financial_records USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_financial_records_type_status; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_financial_records_type_status ON public.financial_records USING btree (type, status);
|
|
|
|
|
|
--
|
|
-- Name: idx_global_notices_active_priority; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_global_notices_active_priority ON public.global_notices USING btree (is_active, priority DESC, starts_at, ends_at);
|
|
|
|
|
|
--
|
|
-- Name: idx_intakes_converted_patient_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_intakes_converted_patient_id ON public.patient_intake_requests USING btree (converted_patient_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_intakes_owner_cpf; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_intakes_owner_cpf ON public.patient_intake_requests USING btree (owner_id, cpf);
|
|
|
|
|
|
--
|
|
-- Name: idx_intakes_owner_created; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_intakes_owner_created ON public.patient_intake_requests USING btree (owner_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_intakes_owner_status_created; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_intakes_owner_status_created ON public.patient_intake_requests USING btree (owner_id, status, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_intakes_status_created; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_intakes_status_created ON public.patient_intake_requests USING btree (status, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_notice_dismissals_user; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notice_dismissals_user ON public.notice_dismissals USING btree (user_id, notice_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_channels_owner_active; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_channels_owner_active ON public.notification_channels USING btree (owner_id, channel) WHERE ((is_active = true) AND (deleted_at IS NULL));
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_channels_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_channels_tenant ON public.notification_channels USING btree (tenant_id) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_logs_owner_date; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_logs_owner_date ON public.notification_logs USING btree (owner_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_logs_patient; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_logs_patient ON public.notification_logs USING btree (patient_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_logs_provider_msg; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_logs_provider_msg ON public.notification_logs USING btree (provider_message_id) WHERE (provider_message_id IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_logs_status; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_logs_status ON public.notification_logs USING btree (status, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_logs_tenant_date; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_logs_tenant_date ON public.notification_logs USING btree (tenant_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_prefs_owner; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_prefs_owner ON public.notification_preferences USING btree (owner_id) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_prefs_patient; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_prefs_patient ON public.notification_preferences USING btree (patient_id) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_prefs_whatsapp_active; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_prefs_whatsapp_active ON public.notification_preferences USING btree (owner_id, patient_id) WHERE ((whatsapp_opt_in = true) AND (deleted_at IS NULL));
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_queue_evento; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_queue_evento ON public.notification_queue USING btree (agenda_evento_id) WHERE (status = ANY (ARRAY['pendente'::text, 'processando'::text]));
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_queue_patient; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_queue_patient ON public.notification_queue USING btree (patient_id, channel) WHERE (status = 'pendente'::text);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_queue_pending; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_queue_pending ON public.notification_queue USING btree (scheduled_at) WHERE (status = 'pendente'::text);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_queue_processing; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_queue_processing ON public.notification_queue USING btree (status, updated_at) WHERE (status = 'processando'::text);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_queue_retry; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_queue_retry ON public.notification_queue USING btree (next_retry_at) WHERE ((status = 'pendente'::text) AND (attempts > 0));
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_queue_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_queue_tenant ON public.notification_queue USING btree (tenant_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_schedules_owner_active; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_schedules_owner_active ON public.notification_schedules USING btree (owner_id, event_type) WHERE ((is_active = true) AND (deleted_at IS NULL));
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_templates_default; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_templates_default ON public.notification_templates USING btree (channel, event_type) WHERE ((is_default = true) AND (deleted_at IS NULL) AND (tenant_id IS NULL));
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_templates_lookup; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_templates_lookup ON public.notification_templates USING btree (channel, event_type, is_active) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_notif_templates_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_notif_templates_tenant ON public.notification_templates USING btree (tenant_id, channel, event_type) WHERE ((deleted_at IS NULL) AND (is_active = true));
|
|
|
|
|
|
--
|
|
-- Name: idx_patient_group_patient_group_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patient_group_patient_group_id ON public.patient_group_patient USING btree (patient_group_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_patient_groups_owner; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patient_groups_owner ON public.patient_groups USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_patient_groups_owner_system_nome; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patient_groups_owner_system_nome ON public.patient_groups USING btree (owner_id, is_system, nome);
|
|
|
|
|
|
--
|
|
-- Name: idx_patient_tags_owner; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patient_tags_owner ON public.patient_tags USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_created_at; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_created_at ON public.patients USING btree (created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_last_attended; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_last_attended ON public.patients USING btree (last_attended_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_owner_email_principal; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_owner_email_principal ON public.patients USING btree (owner_id, email_principal);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_owner_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_owner_id ON public.patients USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_owner_nome; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_owner_nome ON public.patients USING btree (owner_id, nome_completo);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_responsible_member; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_responsible_member ON public.patients USING btree (responsible_member_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_status; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_status ON public.patients USING btree (status);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_tenant ON public.patients USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_patients_tenant_email_norm; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_patients_tenant_email_norm ON public.patients USING btree (tenant_id, lower(TRIM(BOTH FROM email_principal)));
|
|
|
|
|
|
--
|
|
-- Name: idx_pgp_group; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_pgp_group ON public.patient_group_patient USING btree (patient_group_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_pgp_patient; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_pgp_patient ON public.patient_group_patient USING btree (patient_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_ppt_patient; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_ppt_patient ON public.patient_patient_tag USING btree (patient_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_ppt_tag; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_ppt_tag ON public.patient_patient_tag USING btree (tag_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_slots_bloq_owner_dia; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_slots_bloq_owner_dia ON public.agenda_slots_bloqueados_semanais USING btree (owner_id, dia_semana);
|
|
|
|
|
|
--
|
|
-- Name: idx_subscription_intents_plan_interval; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_subscription_intents_plan_interval ON public.subscription_intents_legacy USING btree (plan_key, "interval");
|
|
|
|
|
|
--
|
|
-- Name: idx_subscription_intents_status; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_subscription_intents_status ON public.subscription_intents_legacy USING btree (status);
|
|
|
|
|
|
--
|
|
-- Name: idx_subscription_intents_user_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_subscription_intents_user_id ON public.subscription_intents_legacy USING btree (user_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_tenant_features_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_tenant_features_tenant ON public.tenant_features USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_tenant_invites_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_tenant_invites_tenant ON public.tenant_invites USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_tenant_invites_token; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_tenant_invites_token ON public.tenant_invites USING btree (token);
|
|
|
|
|
|
--
|
|
-- Name: idx_therapist_payout_records_financial_record_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_therapist_payout_records_financial_record_id ON public.therapist_payout_records USING btree (financial_record_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_therapist_payouts_owner_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_therapist_payouts_owner_id ON public.therapist_payouts USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: idx_therapist_payouts_period; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_therapist_payouts_period ON public.therapist_payouts USING btree (period_start, period_end);
|
|
|
|
|
|
--
|
|
-- Name: idx_therapist_payouts_status; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_therapist_payouts_status ON public.therapist_payouts USING btree (status) WHERE (status = 'pending'::text);
|
|
|
|
|
|
--
|
|
-- Name: idx_therapist_payouts_tenant_id; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_therapist_payouts_tenant_id ON public.therapist_payouts USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: insurance_plans_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX insurance_plans_owner_idx ON public.insurance_plans USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: insurance_plans_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX insurance_plans_tenant_idx ON public.insurance_plans USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: ix_plan_prices_plan; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX ix_plan_prices_plan ON public.plan_prices USING btree (plan_id);
|
|
|
|
|
|
--
|
|
-- Name: ix_plan_public_bullets_plan; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX ix_plan_public_bullets_plan ON public.plan_public_bullets USING btree (plan_id);
|
|
|
|
|
|
--
|
|
-- Name: ix_plan_public_sort; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX ix_plan_public_sort ON public.plan_public USING btree (sort_order);
|
|
|
|
|
|
--
|
|
-- Name: notifications_owner_created; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX notifications_owner_created ON public.notifications USING btree (owner_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: notifications_owner_unread; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX notifications_owner_unread ON public.notifications USING btree (owner_id, read_at) WHERE (read_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: patient_discounts_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_discounts_owner_idx ON public.patient_discounts USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_discounts_patient_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_discounts_patient_idx ON public.patient_discounts USING btree (patient_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_discounts_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_discounts_tenant_idx ON public.patient_discounts USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_group_patient_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_group_patient_tenant_idx ON public.patient_group_patient USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_groups_owner_nome_uniq; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX patient_groups_owner_nome_uniq ON public.patient_groups USING btree (owner_id, nome);
|
|
|
|
|
|
--
|
|
-- Name: patient_groups_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_groups_tenant_idx ON public.patient_groups USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_owner_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_intake_owner_id_idx ON public.patient_intake_requests USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_intake_requests_tenant_idx ON public.patient_intake_requests USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_status_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_intake_status_idx ON public.patient_intake_requests USING btree (status);
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_token_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_intake_token_idx ON public.patient_intake_requests USING btree (token);
|
|
|
|
|
|
--
|
|
-- Name: patient_invites_one_active_per_owner; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX patient_invites_one_active_per_owner ON public.patient_invites USING btree (owner_id) WHERE (active = true);
|
|
|
|
|
|
--
|
|
-- Name: patient_invites_owner_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_invites_owner_id_idx ON public.patient_invites USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_invites_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_invites_tenant_idx ON public.patient_invites USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_invites_token_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_invites_token_idx ON public.patient_invites USING btree (token);
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_patient_tag_tenant_idx ON public.patient_patient_tag USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: patient_tags_owner_name_uq; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX patient_tags_owner_name_uq ON public.patient_tags USING btree (owner_id, lower(nome));
|
|
|
|
|
|
--
|
|
-- Name: patient_tags_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX patient_tags_tenant_idx ON public.patient_tags USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: payment_settings_tenant_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX payment_settings_tenant_id_idx ON public.payment_settings USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: ppt_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX ppt_owner_idx ON public.patient_patient_tag USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: ppt_patient_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX ppt_patient_idx ON public.patient_patient_tag USING btree (patient_id);
|
|
|
|
|
|
--
|
|
-- Name: ppt_tag_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX ppt_tag_idx ON public.patient_patient_tag USING btree (tag_id);
|
|
|
|
|
|
--
|
|
-- Name: professional_pricing_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX professional_pricing_tenant_idx ON public.professional_pricing USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: profiles_work_description_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX profiles_work_description_idx ON public.profiles USING btree (work_description) WHERE (work_description IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exceptions_rule_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX recurrence_exceptions_rule_idx ON public.recurrence_exceptions USING btree (recurrence_id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exceptions_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX recurrence_exceptions_tenant_idx ON public.recurrence_exceptions USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services_rule_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX recurrence_rule_services_rule_idx ON public.recurrence_rule_services USING btree (rule_id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services_service_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX recurrence_rule_services_service_idx ON public.recurrence_rule_services USING btree (service_id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules_active_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX recurrence_rules_active_idx ON public.recurrence_rules USING btree (owner_id, status) WHERE (status = 'ativo'::text);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX recurrence_rules_owner_idx ON public.recurrence_rules USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules_patient_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX recurrence_rules_patient_idx ON public.recurrence_rules USING btree (patient_id);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX recurrence_rules_tenant_idx ON public.recurrence_rules USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos_doc_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_doc_votos_doc_id_idx ON public.saas_doc_votos USING btree (doc_id);
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos_user_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_doc_votos_user_id_idx ON public.saas_doc_votos USING btree (user_id);
|
|
|
|
|
|
--
|
|
-- Name: saas_docs_categoria_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_docs_categoria_idx ON public.saas_docs USING btree (categoria);
|
|
|
|
|
|
--
|
|
-- Name: saas_docs_exibir_no_faq_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_docs_exibir_no_faq_idx ON public.saas_docs USING btree (exibir_no_faq) WHERE (exibir_no_faq = true);
|
|
|
|
|
|
--
|
|
-- Name: saas_docs_path_ativo_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_docs_path_ativo_idx ON public.saas_docs USING btree (pagina_path, ativo);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_ativo_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_faq_ativo_idx ON public.saas_faq USING btree (ativo);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_categoria_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_faq_categoria_idx ON public.saas_faq USING btree (categoria);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_fts_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_faq_fts_idx ON public.saas_faq USING gin (to_tsvector('portuguese'::regconfig, ((COALESCE(pergunta, ''::text) || ' '::text) || COALESCE(conteudo, ''::text))));
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_itens_ativo_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_faq_itens_ativo_idx ON public.saas_faq_itens USING btree (ativo);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_itens_doc_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_faq_itens_doc_id_idx ON public.saas_faq_itens USING btree (doc_id);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_pagina_path_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_faq_pagina_path_idx ON public.saas_faq USING btree (pagina_path);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_publico_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_faq_publico_idx ON public.saas_faq USING btree (publico);
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_votos_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX saas_faq_votos_idx ON public.saas_faq USING btree (votos DESC);
|
|
|
|
|
|
--
|
|
-- Name: services_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX services_owner_idx ON public.services USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: services_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX services_tenant_idx ON public.services USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: sint_personal_created_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sint_personal_created_idx ON public.subscription_intents_personal USING btree (created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: sint_personal_status_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sint_personal_status_idx ON public.subscription_intents_personal USING btree (status);
|
|
|
|
|
|
--
|
|
-- Name: sint_tenant_created_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sint_tenant_created_idx ON public.subscription_intents_tenant USING btree (created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: sint_tenant_status_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sint_tenant_status_idx ON public.subscription_intents_tenant USING btree (status);
|
|
|
|
|
|
--
|
|
-- Name: sint_tenant_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX sint_tenant_tenant_idx ON public.subscription_intents_tenant USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: subscription_events_created_at_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscription_events_created_at_idx ON public.subscription_events USING btree (created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: subscription_events_owner_ref_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscription_events_owner_ref_idx ON public.subscription_events USING btree (owner_type, owner_ref);
|
|
|
|
|
|
--
|
|
-- Name: subscription_events_sub_created_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscription_events_sub_created_idx ON public.subscription_events USING btree (subscription_id, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: subscription_events_subscription_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscription_events_subscription_id_idx ON public.subscription_events USING btree (subscription_id);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_one_active_per_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX subscriptions_one_active_per_tenant ON public.subscriptions USING btree (tenant_id) WHERE (status = 'active'::text);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_one_active_per_user; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX subscriptions_one_active_per_user ON public.subscriptions USING btree (user_id) WHERE (status = 'active'::text);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_one_active_per_user_personal; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
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));
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscriptions_owner_idx ON public.subscriptions USING btree (user_id);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_plan_key_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscriptions_plan_key_idx ON public.subscriptions USING btree (plan_key);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_status_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscriptions_status_idx ON public.subscriptions USING btree (status);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_tenant_id_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscriptions_tenant_id_idx ON public.subscriptions USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_tenant_period_end_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscriptions_tenant_period_end_idx ON public.subscriptions USING btree (tenant_id, current_period_end);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_tenant_status_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscriptions_tenant_status_idx ON public.subscriptions USING btree (tenant_id, status);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions_user_status_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX subscriptions_user_status_idx ON public.subscriptions USING btree (user_id, status, created_at DESC);
|
|
|
|
|
|
--
|
|
-- Name: support_sessions_expires_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX support_sessions_expires_idx ON public.support_sessions USING btree (expires_at);
|
|
|
|
|
|
--
|
|
-- Name: support_sessions_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX support_sessions_tenant_idx ON public.support_sessions USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: support_sessions_token_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX support_sessions_token_idx ON public.support_sessions USING btree (token);
|
|
|
|
|
|
--
|
|
-- Name: tenant_members_tenant_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX tenant_members_tenant_idx ON public.tenant_members USING btree (tenant_id);
|
|
|
|
|
|
--
|
|
-- Name: tenant_members_user_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX tenant_members_user_idx ON public.tenant_members USING btree (user_id);
|
|
|
|
|
|
--
|
|
-- Name: tenant_modules_owner_idx; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE INDEX tenant_modules_owner_idx ON public.tenant_modules USING btree (owner_id);
|
|
|
|
|
|
--
|
|
-- Name: unique_member_per_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX unique_member_per_tenant ON public.tenant_members USING btree (tenant_id, user_id);
|
|
|
|
|
|
--
|
|
-- Name: uq_patients_tenant_user; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX uq_patients_tenant_user ON public.patients USING btree (tenant_id, user_id) WHERE (user_id IS NOT NULL);
|
|
|
|
|
|
--
|
|
-- Name: uq_plan_price_active; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
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));
|
|
|
|
|
|
--
|
|
-- Name: uq_plan_prices_active; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX uq_plan_prices_active ON public.plan_prices USING btree (plan_id, "interval") WHERE (is_active = true);
|
|
|
|
|
|
--
|
|
-- Name: uq_subscriptions_active_by_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
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));
|
|
|
|
|
|
--
|
|
-- Name: uq_subscriptions_active_personal_by_user; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
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));
|
|
|
|
|
|
--
|
|
-- Name: uq_tenant_invites_pending; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
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));
|
|
|
|
|
|
--
|
|
-- Name: uq_tenant_members_tenant_user; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX uq_tenant_members_tenant_user ON public.tenant_members USING btree (tenant_id, user_id);
|
|
|
|
|
|
--
|
|
-- Name: ux_subscriptions_active_per_personal_user; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
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));
|
|
|
|
|
|
--
|
|
-- Name: ux_subscriptions_active_per_tenant; Type: INDEX; Schema: public; Owner: -
|
|
--
|
|
|
|
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));
|
|
|
|
|
|
--
|
|
-- Name: ix_realtime_subscription_entity; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX ix_realtime_subscription_entity ON realtime.subscription USING btree (entity);
|
|
|
|
|
|
--
|
|
-- Name: messages_inserted_at_topic_index; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX messages_inserted_at_topic_index ON ONLY realtime.messages USING btree (inserted_at DESC, topic) WHERE ((extension = 'broadcast'::text) AND (private IS TRUE));
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_20_inserted_at_topic_idx; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX messages_2026_03_20_inserted_at_topic_idx ON realtime.messages_2026_03_20 USING btree (inserted_at DESC, topic) WHERE ((extension = 'broadcast'::text) AND (private IS TRUE));
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_21_inserted_at_topic_idx; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX messages_2026_03_21_inserted_at_topic_idx ON realtime.messages_2026_03_21 USING btree (inserted_at DESC, topic) WHERE ((extension = 'broadcast'::text) AND (private IS TRUE));
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_22_inserted_at_topic_idx; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX messages_2026_03_22_inserted_at_topic_idx ON realtime.messages_2026_03_22 USING btree (inserted_at DESC, topic) WHERE ((extension = 'broadcast'::text) AND (private IS TRUE));
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_23_inserted_at_topic_idx; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX messages_2026_03_23_inserted_at_topic_idx ON realtime.messages_2026_03_23 USING btree (inserted_at DESC, topic) WHERE ((extension = 'broadcast'::text) AND (private IS TRUE));
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_24_inserted_at_topic_idx; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX messages_2026_03_24_inserted_at_topic_idx ON realtime.messages_2026_03_24 USING btree (inserted_at DESC, topic) WHERE ((extension = 'broadcast'::text) AND (private IS TRUE));
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_25_inserted_at_topic_idx; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX messages_2026_03_25_inserted_at_topic_idx ON realtime.messages_2026_03_25 USING btree (inserted_at DESC, topic) WHERE ((extension = 'broadcast'::text) AND (private IS TRUE));
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_26_inserted_at_topic_idx; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE INDEX messages_2026_03_26_inserted_at_topic_idx ON realtime.messages_2026_03_26 USING btree (inserted_at DESC, topic) WHERE ((extension = 'broadcast'::text) AND (private IS TRUE));
|
|
|
|
|
|
--
|
|
-- Name: subscription_subscription_id_entity_filters_key; Type: INDEX; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX subscription_subscription_id_entity_filters_key ON realtime.subscription USING btree (subscription_id, entity, filters);
|
|
|
|
|
|
--
|
|
-- Name: bname; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX bname ON storage.buckets USING btree (name);
|
|
|
|
|
|
--
|
|
-- Name: bucketid_objname; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX bucketid_objname ON storage.objects USING btree (bucket_id, name);
|
|
|
|
|
|
--
|
|
-- Name: buckets_analytics_unique_name_idx; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX buckets_analytics_unique_name_idx ON storage.buckets_analytics USING btree (name) WHERE (deleted_at IS NULL);
|
|
|
|
|
|
--
|
|
-- Name: idx_iceberg_namespaces_bucket_id; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX idx_iceberg_namespaces_bucket_id ON storage.iceberg_namespaces USING btree (catalog_id, name);
|
|
|
|
|
|
--
|
|
-- Name: idx_iceberg_tables_location; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX idx_iceberg_tables_location ON storage.iceberg_tables USING btree (location);
|
|
|
|
|
|
--
|
|
-- Name: idx_iceberg_tables_namespace_id; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX idx_iceberg_tables_namespace_id ON storage.iceberg_tables USING btree (catalog_id, namespace_id, name);
|
|
|
|
|
|
--
|
|
-- Name: idx_multipart_uploads_list; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_multipart_uploads_list ON storage.s3_multipart_uploads USING btree (bucket_id, key, created_at);
|
|
|
|
|
|
--
|
|
-- Name: idx_objects_bucket_id_name; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_objects_bucket_id_name ON storage.objects USING btree (bucket_id, name COLLATE "C");
|
|
|
|
|
|
--
|
|
-- Name: idx_objects_bucket_id_name_lower; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE INDEX idx_objects_bucket_id_name_lower ON storage.objects USING btree (bucket_id, lower(name) COLLATE "C");
|
|
|
|
|
|
--
|
|
-- Name: name_prefix_search; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE INDEX name_prefix_search ON storage.objects USING btree (name text_pattern_ops);
|
|
|
|
|
|
--
|
|
-- Name: vector_indexes_name_bucket_id_idx; Type: INDEX; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE UNIQUE INDEX vector_indexes_name_bucket_id_idx ON storage.vector_indexes USING btree (name, bucket_id);
|
|
|
|
|
|
--
|
|
-- Name: supabase_functions_hooks_h_table_id_h_name_idx; Type: INDEX; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
CREATE INDEX supabase_functions_hooks_h_table_id_h_name_idx ON supabase_functions.hooks USING btree (hook_table_id, hook_name);
|
|
|
|
|
|
--
|
|
-- Name: supabase_functions_hooks_request_id_idx; Type: INDEX; Schema: supabase_functions; Owner: -
|
|
--
|
|
|
|
CREATE INDEX supabase_functions_hooks_request_id_idx ON supabase_functions.hooks USING btree (request_id);
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_20_inserted_at_topic_idx; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_inserted_at_topic_index ATTACH PARTITION realtime.messages_2026_03_20_inserted_at_topic_idx;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_20_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2026_03_20_pkey;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_21_inserted_at_topic_idx; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_inserted_at_topic_index ATTACH PARTITION realtime.messages_2026_03_21_inserted_at_topic_idx;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_21_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2026_03_21_pkey;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_22_inserted_at_topic_idx; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_inserted_at_topic_index ATTACH PARTITION realtime.messages_2026_03_22_inserted_at_topic_idx;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_22_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2026_03_22_pkey;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_23_inserted_at_topic_idx; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_inserted_at_topic_index ATTACH PARTITION realtime.messages_2026_03_23_inserted_at_topic_idx;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_23_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2026_03_23_pkey;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_24_inserted_at_topic_idx; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_inserted_at_topic_index ATTACH PARTITION realtime.messages_2026_03_24_inserted_at_topic_idx;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_24_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2026_03_24_pkey;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_25_inserted_at_topic_idx; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_inserted_at_topic_index ATTACH PARTITION realtime.messages_2026_03_25_inserted_at_topic_idx;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_25_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2026_03_25_pkey;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_26_inserted_at_topic_idx; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_inserted_at_topic_index ATTACH PARTITION realtime.messages_2026_03_26_inserted_at_topic_idx;
|
|
|
|
|
|
--
|
|
-- Name: messages_2026_03_26_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2026_03_26_pkey;
|
|
|
|
|
|
--
|
|
-- Name: users on_auth_user_created; Type: TRIGGER; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
|
|
|
|
|
|
--
|
|
-- Name: users trg_seed_patient_groups; Type: TRIGGER; Schema: auth; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_seed_patient_groups AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION public.on_new_user_seed_patient_groups();
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios agenda_bloqueios_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER agenda_bloqueios_updated_at BEFORE UPDATE ON public.agenda_bloqueios FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes agendador_slug_trigger; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER agendador_slug_trigger BEFORE INSERT OR UPDATE ON public.agendador_configuracoes FOR EACH ROW EXECUTE FUNCTION public.agendador_gerar_slug();
|
|
|
|
|
|
--
|
|
-- Name: tenant_members prevent_saas_membership_trigger; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER prevent_saas_membership_trigger BEFORE INSERT ON public.tenant_members FOR EACH ROW EXECUTE FUNCTION public.prevent_saas_membership();
|
|
|
|
|
|
--
|
|
-- Name: insurance_plan_services set_insurance_plan_services_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER set_insurance_plan_services_updated_at BEFORE UPDATE ON public.insurance_plan_services FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: user_settings t_user_settings_set_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER t_user_settings_set_updated_at BEFORE UPDATE ON public.user_settings FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes tg_agenda_configuracoes_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER tg_agenda_configuracoes_updated_at BEFORE UPDATE ON public.agenda_configuracoes FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos tg_agenda_eventos_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER tg_agenda_eventos_updated_at BEFORE UPDATE ON public.agenda_eventos FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes tg_agenda_excecoes_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER tg_agenda_excecoes_updated_at BEFORE UPDATE ON public.agenda_excecoes FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais tg_agenda_regras_semanais_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER tg_agenda_regras_semanais_updated_at BEFORE UPDATE ON public.agenda_regras_semanais FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules tg_recurrence_rules_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER tg_recurrence_rules_updated_at BEFORE UPDATE ON public.recurrence_rules FOR EACH ROW EXECUTE FUNCTION public.set_updated_at_recurrence();
|
|
|
|
|
|
--
|
|
-- Name: plan_public tr_plan_public_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER tr_plan_public_updated_at BEFORE UPDATE ON public.plan_public FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: profiles trg_account_type_immutable; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_account_type_immutable BEFORE UPDATE OF account_type ON public.profiles FOR EACH ROW EXECUTE FUNCTION public.guard_account_type_immutable();
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes trg_agenda_cfg_sync; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_agenda_cfg_sync BEFORE INSERT OR UPDATE ON public.agenda_configuracoes FOR EACH ROW EXECUTE FUNCTION public.agenda_cfg_sync();
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos trg_agenda_eventos_busy_mirror_del; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos trg_agenda_eventos_busy_mirror_ins; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos trg_agenda_eventos_busy_mirror_upd; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais trg_agenda_regras_semanais_no_overlap; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos trg_auto_financial_from_session; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_auto_financial_from_session AFTER UPDATE OF status ON public.agenda_eventos FOR EACH ROW EXECUTE FUNCTION public.auto_create_financial_record_from_session();
|
|
|
|
|
|
--
|
|
-- Name: notification_preferences trg_cancel_notifs_on_opt_out; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_cancel_notifs_on_opt_out AFTER UPDATE ON public.notification_preferences FOR EACH ROW EXECUTE FUNCTION public.cancel_notifications_on_opt_out();
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos trg_cancel_notifs_on_session_cancel; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_cancel_notifs_on_session_cancel AFTER UPDATE ON public.agenda_eventos FOR EACH ROW WHEN ((new.status IS DISTINCT FROM old.status)) EXECUTE FUNCTION public.cancel_notifications_on_session_cancel();
|
|
|
|
|
|
--
|
|
-- Name: company_profiles trg_company_profiles_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_company_profiles_updated_at BEFORE UPDATE ON public.company_profiles FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields trg_determined_commitment_fields_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_determined_commitment_fields_updated_at BEFORE UPDATE ON public.determined_commitment_fields FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments trg_determined_commitments_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_determined_commitments_updated_at BEFORE UPDATE ON public.determined_commitments FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: email_layout_config trg_email_layout_config_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_email_layout_config_updated_at BEFORE UPDATE ON public.email_layout_config FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: email_templates_global trg_email_templates_global_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_email_templates_global_updated_at BEFORE UPDATE ON public.email_templates_global FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: email_templates_tenant trg_email_templates_tenant_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_email_templates_tenant_updated_at BEFORE UPDATE ON public.email_templates_tenant FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: financial_exceptions trg_financial_exceptions_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_financial_exceptions_updated_at BEFORE UPDATE ON public.financial_exceptions FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: financial_records trg_financial_records_auto_overdue; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_financial_records_auto_overdue BEFORE UPDATE ON public.financial_records FOR EACH ROW EXECUTE FUNCTION public.trg_fn_financial_records_auto_overdue();
|
|
|
|
|
|
--
|
|
-- Name: financial_records trg_financial_records_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_financial_records_updated_at BEFORE UPDATE ON public.financial_records FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: global_notices trg_global_notices_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_global_notices_updated_at BEFORE UPDATE ON public.global_notices FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: insurance_plans trg_insurance_plans_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_insurance_plans_updated_at BEFORE UPDATE ON public.insurance_plans FOR EACH ROW EXECUTE FUNCTION public.set_insurance_plans_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: plans trg_no_change_core_plan_key; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_no_change_core_plan_key BEFORE UPDATE ON public.plans FOR EACH ROW EXECUTE FUNCTION public.guard_no_change_core_plan_key();
|
|
|
|
|
|
--
|
|
-- Name: plans trg_no_change_plan_target; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_no_change_plan_target BEFORE UPDATE ON public.plans FOR EACH ROW EXECUTE FUNCTION public.guard_no_change_plan_target();
|
|
|
|
|
|
--
|
|
-- Name: plans trg_no_delete_core_plans; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_no_delete_core_plans BEFORE DELETE ON public.plans FOR EACH ROW EXECUTE FUNCTION public.guard_no_delete_core_plans();
|
|
|
|
|
|
--
|
|
-- Name: notification_channels trg_notification_channels_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notification_channels_updated_at BEFORE UPDATE ON public.notification_channels FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: notification_logs trg_notification_logs_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notification_logs_updated_at BEFORE UPDATE ON public.notification_logs FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: notification_preferences trg_notification_preferences_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notification_preferences_updated_at BEFORE UPDATE ON public.notification_preferences FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: notification_queue trg_notification_queue_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notification_queue_updated_at BEFORE UPDATE ON public.notification_queue FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: notification_schedules trg_notification_schedules_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notification_schedules_updated_at BEFORE UPDATE ON public.notification_schedules FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: notification_templates trg_notification_templates_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notification_templates_updated_at BEFORE UPDATE ON public.notification_templates FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests trg_notify_on_intake; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notify_on_intake AFTER INSERT ON public.patient_intake_requests FOR EACH ROW EXECUTE FUNCTION public.notify_on_intake();
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes trg_notify_on_scheduling; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notify_on_scheduling AFTER INSERT ON public.agendador_solicitacoes FOR EACH ROW EXECUTE FUNCTION public.notify_on_scheduling();
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos trg_notify_on_session_status; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_notify_on_session_status AFTER UPDATE OF status ON public.agenda_eventos FOR EACH ROW EXECUTE FUNCTION public.notify_on_session_status();
|
|
|
|
|
|
--
|
|
-- Name: tenant_members trg_patient_cannot_own_tenant; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
|
|
|
|
--
|
|
-- Name: patient_groups trg_patient_groups_set_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_patient_groups_set_updated_at BEFORE UPDATE ON public.patient_groups FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests trg_patient_intake_requests_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_patient_intake_requests_updated_at BEFORE UPDATE ON public.patient_intake_requests FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: patient_tags trg_patient_tags_set_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_patient_tags_set_updated_at BEFORE UPDATE ON public.patient_tags FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: patients trg_patients_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_patients_updated_at BEFORE UPDATE ON public.patients FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: patients trg_patients_validate_members; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
|
|
|
|
--
|
|
-- Name: payment_settings trg_payment_settings_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_payment_settings_updated_at BEFORE UPDATE ON public.payment_settings FOR EACH ROW EXECUTE FUNCTION public.update_payment_settings_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: patient_groups trg_prevent_promoting_to_system; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_prevent_promoting_to_system BEFORE UPDATE ON public.patient_groups FOR EACH ROW EXECUTE FUNCTION public.prevent_promoting_to_system();
|
|
|
|
|
|
--
|
|
-- Name: patient_groups trg_prevent_system_group_changes; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_prevent_system_group_changes BEFORE DELETE OR UPDATE ON public.patient_groups FOR EACH ROW EXECUTE FUNCTION public.prevent_system_group_changes();
|
|
|
|
|
|
--
|
|
-- Name: professional_pricing trg_professional_pricing_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_professional_pricing_updated_at BEFORE UPDATE ON public.professional_pricing FOR EACH ROW EXECUTE FUNCTION public.update_professional_pricing_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: profiles trg_profiles_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_profiles_updated_at BEFORE UPDATE ON public.profiles FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: services trg_services_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_services_updated_at BEFORE UPDATE ON public.services FOR EACH ROW EXECUTE FUNCTION public.set_services_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents trg_subscription_intents_view_insert; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_subscription_intents_view_insert INSTEAD OF INSERT ON public.subscription_intents FOR EACH ROW EXECUTE FUNCTION public.subscription_intents_view_insert();
|
|
|
|
|
|
--
|
|
-- Name: subscriptions trg_subscriptions_validate_scope; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_subscriptions_validate_scope BEFORE INSERT OR UPDATE ON public.subscriptions FOR EACH ROW EXECUTE FUNCTION public.subscriptions_validate_scope();
|
|
|
|
|
|
--
|
|
-- Name: tenant_features trg_tenant_features_guard_with_plan; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE 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();
|
|
|
|
|
|
--
|
|
-- Name: tenant_features trg_tenant_features_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_tenant_features_updated_at BEFORE UPDATE ON public.tenant_features FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: tenants trg_tenant_kind_immutable; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_tenant_kind_immutable BEFORE UPDATE OF kind ON public.tenants FOR EACH ROW EXECUTE FUNCTION public.guard_tenant_kind_immutable();
|
|
|
|
|
|
--
|
|
-- Name: therapist_payouts trg_therapist_payouts_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_therapist_payouts_updated_at BEFORE UPDATE ON public.therapist_payouts FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: user_settings trg_user_settings_updated_at; Type: TRIGGER; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER trg_user_settings_updated_at BEFORE UPDATE ON public.user_settings FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
|
|
|
|
--
|
|
-- Name: subscription tr_check_filters; Type: TRIGGER; Schema: realtime; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER tr_check_filters BEFORE INSERT OR UPDATE ON realtime.subscription FOR EACH ROW EXECUTE FUNCTION realtime.subscription_check_filters();
|
|
|
|
|
|
--
|
|
-- Name: buckets enforce_bucket_name_length_trigger; Type: TRIGGER; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER enforce_bucket_name_length_trigger BEFORE INSERT OR UPDATE OF name ON storage.buckets FOR EACH ROW EXECUTE FUNCTION storage.enforce_bucket_name_length();
|
|
|
|
|
|
--
|
|
-- Name: buckets protect_buckets_delete; Type: TRIGGER; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER protect_buckets_delete BEFORE DELETE ON storage.buckets FOR EACH STATEMENT EXECUTE FUNCTION storage.protect_delete();
|
|
|
|
|
|
--
|
|
-- Name: objects protect_objects_delete; Type: TRIGGER; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER protect_objects_delete BEFORE DELETE ON storage.objects FOR EACH STATEMENT EXECUTE FUNCTION storage.protect_delete();
|
|
|
|
|
|
--
|
|
-- Name: objects update_objects_updated_at; Type: TRIGGER; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE TRIGGER update_objects_updated_at BEFORE UPDATE ON storage.objects FOR EACH ROW EXECUTE FUNCTION storage.update_updated_at_column();
|
|
|
|
|
|
--
|
|
-- Name: extensions extensions_tenant_external_id_fkey; Type: FK CONSTRAINT; Schema: _realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY _realtime.extensions
|
|
ADD CONSTRAINT extensions_tenant_external_id_fkey FOREIGN KEY (tenant_external_id) REFERENCES _realtime.tenants(external_id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: identities identities_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.identities
|
|
ADD CONSTRAINT identities_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: mfa_amr_claims mfa_amr_claims_session_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.mfa_amr_claims
|
|
ADD CONSTRAINT mfa_amr_claims_session_id_fkey FOREIGN KEY (session_id) REFERENCES auth.sessions(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: mfa_challenges mfa_challenges_auth_factor_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.mfa_challenges
|
|
ADD CONSTRAINT mfa_challenges_auth_factor_id_fkey FOREIGN KEY (factor_id) REFERENCES auth.mfa_factors(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: mfa_factors mfa_factors_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.mfa_factors
|
|
ADD CONSTRAINT mfa_factors_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: oauth_authorizations oauth_authorizations_client_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_authorizations
|
|
ADD CONSTRAINT oauth_authorizations_client_id_fkey FOREIGN KEY (client_id) REFERENCES auth.oauth_clients(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: oauth_authorizations oauth_authorizations_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_authorizations
|
|
ADD CONSTRAINT oauth_authorizations_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: oauth_consents oauth_consents_client_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_consents
|
|
ADD CONSTRAINT oauth_consents_client_id_fkey FOREIGN KEY (client_id) REFERENCES auth.oauth_clients(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: oauth_consents oauth_consents_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.oauth_consents
|
|
ADD CONSTRAINT oauth_consents_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: one_time_tokens one_time_tokens_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.one_time_tokens
|
|
ADD CONSTRAINT one_time_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: refresh_tokens refresh_tokens_session_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.refresh_tokens
|
|
ADD CONSTRAINT refresh_tokens_session_id_fkey FOREIGN KEY (session_id) REFERENCES auth.sessions(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: saml_providers saml_providers_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.saml_providers
|
|
ADD CONSTRAINT saml_providers_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: saml_relay_states saml_relay_states_flow_state_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.saml_relay_states
|
|
ADD CONSTRAINT saml_relay_states_flow_state_id_fkey FOREIGN KEY (flow_state_id) REFERENCES auth.flow_state(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: saml_relay_states saml_relay_states_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.saml_relay_states
|
|
ADD CONSTRAINT saml_relay_states_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: sessions sessions_oauth_client_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.sessions
|
|
ADD CONSTRAINT sessions_oauth_client_id_fkey FOREIGN KEY (oauth_client_id) REFERENCES auth.oauth_clients(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: sessions sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.sessions
|
|
ADD CONSTRAINT sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: sso_domains sso_domains_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY auth.sso_domains
|
|
ADD CONSTRAINT sso_domains_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: addon_credits addon_credits_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_credits
|
|
ADD CONSTRAINT addon_credits_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id);
|
|
|
|
|
|
--
|
|
-- Name: addon_credits addon_credits_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_credits
|
|
ADD CONSTRAINT addon_credits_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id);
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions addon_transactions_admin_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_transactions
|
|
ADD CONSTRAINT addon_transactions_admin_user_id_fkey FOREIGN KEY (admin_user_id) REFERENCES auth.users(id);
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions addon_transactions_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_transactions
|
|
ADD CONSTRAINT addon_transactions_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id);
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions addon_transactions_product_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_transactions
|
|
ADD CONSTRAINT addon_transactions_product_id_fkey FOREIGN KEY (product_id) REFERENCES public.addon_products(id);
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions addon_transactions_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.addon_transactions
|
|
ADD CONSTRAINT addon_transactions_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id);
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios agenda_bloqueios_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_bloqueios
|
|
ADD CONSTRAINT agenda_bloqueios_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios agenda_bloqueios_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes agenda_configuracoes_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_configuracoes
|
|
ADD CONSTRAINT agenda_configuracoes_tenant_fk FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_billing_contract_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_eventos
|
|
ADD CONSTRAINT agenda_eventos_billing_contract_id_fkey FOREIGN KEY (billing_contract_id) REFERENCES public.billing_contracts(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_determined_commitment_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_insurance_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_eventos
|
|
ADD CONSTRAINT agenda_eventos_insurance_plan_id_fkey FOREIGN KEY (insurance_plan_id) REFERENCES public.insurance_plans(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_insurance_plan_service_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_eventos
|
|
ADD CONSTRAINT agenda_eventos_insurance_plan_service_id_fkey FOREIGN KEY (insurance_plan_service_id) REFERENCES public.insurance_plan_services(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_patient_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_recurrence_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_terapeuta_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_eventos
|
|
ADD CONSTRAINT agenda_eventos_terapeuta_fk FOREIGN KEY (terapeuta_id) REFERENCES auth.users(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes agenda_excecoes_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agenda_excecoes
|
|
ADD CONSTRAINT agenda_excecoes_tenant_fk FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots agenda_online_slots_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots agenda_online_slots_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais agenda_regras_semanais_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais agenda_slots_bloqueados_semanais_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_regras agenda_slots_regras_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes agendador_configuracoes_owner_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agendador_configuracoes
|
|
ADD CONSTRAINT agendador_configuracoes_owner_fk FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes agendador_configuracoes_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agendador_configuracoes
|
|
ADD CONSTRAINT agendador_configuracoes_tenant_fk FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes agendador_sol_owner_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agendador_solicitacoes
|
|
ADD CONSTRAINT agendador_sol_owner_fk FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes agendador_sol_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.agendador_solicitacoes
|
|
ADD CONSTRAINT agendador_sol_tenant_fk FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: billing_contracts billing_contracts_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.billing_contracts
|
|
ADD CONSTRAINT billing_contracts_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: billing_contracts billing_contracts_patient_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.billing_contracts
|
|
ADD CONSTRAINT billing_contracts_patient_id_fkey FOREIGN KEY (patient_id) REFERENCES public.patients(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: commitment_services commitment_services_commitment_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.commitment_services
|
|
ADD CONSTRAINT commitment_services_commitment_id_fkey FOREIGN KEY (commitment_id) REFERENCES public.agenda_eventos(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: commitment_services commitment_services_service_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.commitment_services
|
|
ADD CONSTRAINT commitment_services_service_id_fkey FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE RESTRICT;
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs commitment_time_logs_calendar_event_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs commitment_time_logs_commitment_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs commitment_time_logs_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: company_profiles company_profiles_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.company_profiles
|
|
ADD CONSTRAINT company_profiles_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields determined_commitment_fields_commitment_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields determined_commitment_fields_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments determined_commitments_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.determined_commitments
|
|
ADD CONSTRAINT determined_commitments_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: email_layout_config email_layout_config_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_layout_config
|
|
ADD CONSTRAINT email_layout_config_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: email_templates_tenant email_templates_tenant_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_templates_tenant
|
|
ADD CONSTRAINT email_templates_tenant_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: email_templates_tenant email_templates_tenant_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.email_templates_tenant
|
|
ADD CONSTRAINT email_templates_tenant_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.feriados
|
|
ADD CONSTRAINT feriados_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.feriados
|
|
ADD CONSTRAINT feriados_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: financial_categories financial_categories_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_categories
|
|
ADD CONSTRAINT financial_categories_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: financial_exceptions financial_exceptions_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_exceptions
|
|
ADD CONSTRAINT financial_exceptions_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_agenda_evento_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_records
|
|
ADD CONSTRAINT financial_records_agenda_evento_id_fkey FOREIGN KEY (agenda_evento_id) REFERENCES public.agenda_eventos(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_category_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_records
|
|
ADD CONSTRAINT financial_records_category_id_fkey FOREIGN KEY (category_id) REFERENCES public.financial_categories(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_insurance_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_records
|
|
ADD CONSTRAINT financial_records_insurance_plan_id_fkey FOREIGN KEY (insurance_plan_id) REFERENCES public.insurance_plans(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_patient_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_records
|
|
ADD CONSTRAINT financial_records_patient_id_fkey FOREIGN KEY (patient_id) REFERENCES public.patients(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_records
|
|
ADD CONSTRAINT financial_records_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.financial_records
|
|
ADD CONSTRAINT financial_records_user_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: global_notices global_notices_created_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.global_notices
|
|
ADD CONSTRAINT global_notices_created_by_fkey FOREIGN KEY (created_by) REFERENCES auth.users(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: insurance_plan_services insurance_plan_services_plan_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.insurance_plan_services
|
|
ADD CONSTRAINT insurance_plan_services_plan_fkey FOREIGN KEY (insurance_plan_id) REFERENCES public.insurance_plans(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: insurance_plans insurance_plans_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.insurance_plans
|
|
ADD CONSTRAINT insurance_plans_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: module_features module_features_feature_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.module_features
|
|
ADD CONSTRAINT module_features_feature_id_fkey FOREIGN KEY (feature_id) REFERENCES public.features(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: module_features module_features_module_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.module_features
|
|
ADD CONSTRAINT module_features_module_id_fkey FOREIGN KEY (module_id) REFERENCES public.modules(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: notice_dismissals notice_dismissals_notice_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notice_dismissals
|
|
ADD CONSTRAINT notice_dismissals_notice_id_fkey FOREIGN KEY (notice_id) REFERENCES public.global_notices(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: notice_dismissals notice_dismissals_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notice_dismissals
|
|
ADD CONSTRAINT notice_dismissals_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: notification_channels notification_channels_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_channels
|
|
ADD CONSTRAINT notification_channels_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: notification_logs notification_logs_queue_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_logs
|
|
ADD CONSTRAINT notification_logs_queue_id_fkey FOREIGN KEY (queue_id) REFERENCES public.notification_queue(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: notification_schedules notification_schedules_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_schedules
|
|
ADD CONSTRAINT notification_schedules_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: notification_templates notification_templates_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notification_templates
|
|
ADD CONSTRAINT notification_templates_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: notifications notifications_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.notifications
|
|
ADD CONSTRAINT notifications_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patient_discounts patient_discounts_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_discounts
|
|
ADD CONSTRAINT patient_discounts_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patient_discounts patient_discounts_patient_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_discounts
|
|
ADD CONSTRAINT patient_discounts_patient_id_fkey FOREIGN KEY (patient_id) REFERENCES public.patients(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patient_group_patient patient_group_patient_patient_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: patient_group_patient patient_group_patient_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: patient_groups patient_groups_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_groups
|
|
ADD CONSTRAINT patient_groups_tenant_fk FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests patient_intake_requests_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: patient_invites patient_invites_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_invites
|
|
ADD CONSTRAINT patient_invites_tenant_fk FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag patient_patient_tag_tag_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag patient_patient_tag_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: patient_tags patient_tags_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_tags
|
|
ADD CONSTRAINT patient_tags_tenant_fk FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patients patients_responsible_member_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: patients patients_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patients
|
|
ADD CONSTRAINT patients_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patients patients_therapist_member_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patients
|
|
ADD CONSTRAINT patients_therapist_member_id_fkey FOREIGN KEY (therapist_member_id) REFERENCES public.tenant_members(id);
|
|
|
|
|
|
--
|
|
-- Name: patients patients_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patients
|
|
ADD CONSTRAINT patients_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: payment_settings payment_settings_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.payment_settings
|
|
ADD CONSTRAINT payment_settings_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: payment_settings payment_settings_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.payment_settings
|
|
ADD CONSTRAINT payment_settings_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: plan_features plan_features_feature_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plan_features
|
|
ADD CONSTRAINT plan_features_feature_id_fkey FOREIGN KEY (feature_id) REFERENCES public.features(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: plan_features plan_features_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plan_features
|
|
ADD CONSTRAINT plan_features_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: plan_prices plan_prices_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plan_prices
|
|
ADD CONSTRAINT plan_prices_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: plan_public_bullets plan_public_bullets_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: plan_public plan_public_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.plan_public
|
|
ADD CONSTRAINT plan_public_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag ppt_patient_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_patient_tag
|
|
ADD CONSTRAINT ppt_patient_fk FOREIGN KEY (patient_id) REFERENCES public.patients(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag ppt_tag_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.patient_patient_tag
|
|
ADD CONSTRAINT ppt_tag_fk FOREIGN KEY (tag_id) REFERENCES public.patient_tags(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: professional_pricing professional_pricing_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.professional_pricing
|
|
ADD CONSTRAINT professional_pricing_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: profiles profiles_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.profiles
|
|
ADD CONSTRAINT profiles_id_fkey FOREIGN KEY (id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exceptions recurrence_exceptions_agenda_evento_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exceptions recurrence_exceptions_recurrence_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services recurrence_rule_services_rule_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.recurrence_rule_services
|
|
ADD CONSTRAINT recurrence_rule_services_rule_id_fkey FOREIGN KEY (rule_id) REFERENCES public.recurrence_rules(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services recurrence_rule_services_service_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.recurrence_rule_services
|
|
ADD CONSTRAINT recurrence_rule_services_service_id_fkey FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE RESTRICT;
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules recurrence_rules_insurance_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.recurrence_rules
|
|
ADD CONSTRAINT recurrence_rules_insurance_plan_id_fkey FOREIGN KEY (insurance_plan_id) REFERENCES public.insurance_plans(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules recurrence_rules_insurance_plan_service_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.recurrence_rules
|
|
ADD CONSTRAINT recurrence_rules_insurance_plan_service_id_fkey FOREIGN KEY (insurance_plan_service_id) REFERENCES public.insurance_plan_services(id) ON DELETE SET NULL;
|
|
|
|
|
|
--
|
|
-- Name: saas_admins saas_admins_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.saas_admins
|
|
ADD CONSTRAINT saas_admins_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos saas_doc_votos_doc_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos saas_doc_votos_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_itens saas_faq_itens_doc_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: services services_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.services
|
|
ADD CONSTRAINT services_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_personal sint_personal_subscription_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_tenant sint_tenant_subscription_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: subscription_events subscription_events_subscription_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.subscription_events
|
|
ADD CONSTRAINT subscription_events_subscription_id_fkey FOREIGN KEY (subscription_id) REFERENCES public.subscriptions(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_personal subscription_intents_personal_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_tenant subscription_intents_tenant_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_legacy subscription_intents_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.subscriptions
|
|
ADD CONSTRAINT subscriptions_owner_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.subscriptions
|
|
ADD CONSTRAINT subscriptions_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE RESTRICT;
|
|
|
|
|
|
--
|
|
-- Name: support_sessions support_sessions_admin_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.support_sessions
|
|
ADD CONSTRAINT support_sessions_admin_fk FOREIGN KEY (admin_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: support_sessions support_sessions_tenant_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.support_sessions
|
|
ADD CONSTRAINT support_sessions_tenant_fk FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: tenant_features tenant_features_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_features
|
|
ADD CONSTRAINT tenant_features_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: tenant_invites tenant_invites_accepted_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: tenant_invites tenant_invites_invited_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: tenant_invites tenant_invites_revoked_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
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;
|
|
|
|
|
|
--
|
|
-- Name: tenant_invites tenant_invites_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_invites
|
|
ADD CONSTRAINT tenant_invites_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: tenant_members tenant_members_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_members
|
|
ADD CONSTRAINT tenant_members_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: tenant_members tenant_members_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_members
|
|
ADD CONSTRAINT tenant_members_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: tenant_modules tenant_modules_module_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_modules
|
|
ADD CONSTRAINT tenant_modules_module_id_fkey FOREIGN KEY (module_id) REFERENCES public.modules(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: tenant_modules tenant_modules_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.tenant_modules
|
|
ADD CONSTRAINT tenant_modules_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: therapist_payout_records therapist_payout_records_financial_record_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.therapist_payout_records
|
|
ADD CONSTRAINT therapist_payout_records_financial_record_id_fkey FOREIGN KEY (financial_record_id) REFERENCES public.financial_records(id) ON DELETE RESTRICT;
|
|
|
|
|
|
--
|
|
-- Name: therapist_payout_records therapist_payout_records_payout_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.therapist_payout_records
|
|
ADD CONSTRAINT therapist_payout_records_payout_id_fkey FOREIGN KEY (payout_id) REFERENCES public.therapist_payouts(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: therapist_payouts therapist_payouts_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.therapist_payouts
|
|
ADD CONSTRAINT therapist_payouts_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: therapist_payouts therapist_payouts_tenant_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.therapist_payouts
|
|
ADD CONSTRAINT therapist_payouts_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: user_settings user_settings_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY public.user_settings
|
|
ADD CONSTRAINT user_settings_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: iceberg_namespaces iceberg_namespaces_catalog_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.iceberg_namespaces
|
|
ADD CONSTRAINT iceberg_namespaces_catalog_id_fkey FOREIGN KEY (catalog_id) REFERENCES storage.buckets_analytics(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: iceberg_tables iceberg_tables_catalog_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.iceberg_tables
|
|
ADD CONSTRAINT iceberg_tables_catalog_id_fkey FOREIGN KEY (catalog_id) REFERENCES storage.buckets_analytics(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: iceberg_tables iceberg_tables_namespace_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.iceberg_tables
|
|
ADD CONSTRAINT iceberg_tables_namespace_id_fkey FOREIGN KEY (namespace_id) REFERENCES storage.iceberg_namespaces(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: objects objects_bucketId_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.objects
|
|
ADD CONSTRAINT "objects_bucketId_fkey" FOREIGN KEY (bucket_id) REFERENCES storage.buckets(id);
|
|
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads s3_multipart_uploads_bucket_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.s3_multipart_uploads
|
|
ADD CONSTRAINT s3_multipart_uploads_bucket_id_fkey FOREIGN KEY (bucket_id) REFERENCES storage.buckets(id);
|
|
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads_parts s3_multipart_uploads_parts_bucket_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.s3_multipart_uploads_parts
|
|
ADD CONSTRAINT s3_multipart_uploads_parts_bucket_id_fkey FOREIGN KEY (bucket_id) REFERENCES storage.buckets(id);
|
|
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads_parts s3_multipart_uploads_parts_upload_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.s3_multipart_uploads_parts
|
|
ADD CONSTRAINT s3_multipart_uploads_parts_upload_id_fkey FOREIGN KEY (upload_id) REFERENCES storage.s3_multipart_uploads(id) ON DELETE CASCADE;
|
|
|
|
|
|
--
|
|
-- Name: vector_indexes vector_indexes_bucket_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE ONLY storage.vector_indexes
|
|
ADD CONSTRAINT vector_indexes_bucket_id_fkey FOREIGN KEY (bucket_id) REFERENCES storage.buckets_vectors(id);
|
|
|
|
|
|
--
|
|
-- Name: audit_log_entries; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.audit_log_entries ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: flow_state; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.flow_state ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: identities; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.identities ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: instances; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.instances ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: mfa_amr_claims; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.mfa_amr_claims ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: mfa_challenges; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.mfa_challenges ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: mfa_factors; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.mfa_factors ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: one_time_tokens; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.one_time_tokens ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: refresh_tokens; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.refresh_tokens ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: saml_providers; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.saml_providers ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: saml_relay_states; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.saml_relay_states ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: schema_migrations; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.schema_migrations ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: sessions; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.sessions ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: sso_domains; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.sso_domains ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: sso_providers; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.sso_providers ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: users; Type: ROW SECURITY; Schema: auth; Owner: -
|
|
--
|
|
|
|
ALTER TABLE auth.users ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: addon_credits; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.addon_credits ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: addon_credits addon_credits_admin_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY addon_credits_admin_select ON public.addon_credits FOR SELECT TO authenticated USING ((EXISTS ( SELECT 1
|
|
FROM public.saas_admins
|
|
WHERE (saas_admins.user_id = auth.uid()))));
|
|
|
|
|
|
--
|
|
-- Name: addon_credits addon_credits_admin_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY addon_credits_admin_write ON public.addon_credits 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()))));
|
|
|
|
|
|
--
|
|
-- Name: addon_credits addon_credits_select_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY addon_credits_select_own ON public.addon_credits FOR SELECT TO authenticated USING ((public.is_tenant_member(tenant_id) OR (owner_id = auth.uid())));
|
|
|
|
|
|
--
|
|
-- Name: addon_products; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.addon_products ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: addon_products addon_products_admin_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY addon_products_admin_all ON public.addon_products 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()))));
|
|
|
|
|
|
--
|
|
-- Name: addon_products addon_products_select_authenticated; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY addon_products_select_authenticated ON public.addon_products FOR SELECT TO authenticated USING (((deleted_at IS NULL) AND (is_active = true) AND (is_visible = true)));
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.addon_transactions ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: addon_transactions addon_transactions_admin_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY addon_transactions_admin_insert ON public.addon_transactions FOR INSERT TO authenticated WITH CHECK ((EXISTS ( SELECT 1
|
|
FROM public.saas_admins
|
|
WHERE (saas_admins.user_id = auth.uid()))));
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions addon_transactions_admin_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY addon_transactions_admin_select ON public.addon_transactions FOR SELECT TO authenticated USING ((EXISTS ( SELECT 1
|
|
FROM public.saas_admins
|
|
WHERE (saas_admins.user_id = auth.uid()))));
|
|
|
|
|
|
--
|
|
-- Name: addon_transactions addon_transactions_select_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY addon_transactions_select_own ON public.addon_transactions FOR SELECT TO authenticated USING ((public.is_tenant_member(tenant_id) OR (owner_id = auth.uid())));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agenda_bloqueios ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_configuracoes; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agenda_configuracoes ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_configuracoes agenda_configuracoes_clinic_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes agenda_configuracoes_clinic_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_configuracoes agenda_configuracoes_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agenda_configuracoes_owner ON public.agenda_configuracoes USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agenda_eventos ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_delete; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_owner_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agenda_eventos_owner_all ON public.agenda_eventos TO authenticated USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_eventos agenda_eventos_update; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agenda_excecoes ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_excecoes agenda_excecoes_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agenda_excecoes_owner ON public.agenda_excecoes USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes agenda_excecoes_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_excecoes agenda_excecoes_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agenda_online_slots ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_online_slots agenda_online_slots_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agenda_online_slots_owner ON public.agenda_online_slots USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots agenda_online_slots_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_online_slots agenda_online_slots_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agenda_regras_semanais ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais agenda_regras_semanais_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agenda_regras_semanais_owner ON public.agenda_regras_semanais USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais agenda_regras_semanais_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_regras_semanais agenda_regras_semanais_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agenda_slots_bloqueados_semanais ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais agenda_slots_bloqueados_semanais_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_bloqueados_semanais agenda_slots_bloqueados_semanais_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_regras; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agenda_slots_regras ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_slots_regras agenda_slots_regras_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agenda_slots_regras agenda_slots_regras_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes agendador_cfg_public_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_cfg_public_read ON public.agendador_configuracoes FOR SELECT TO anon USING (((ativo = true) AND (link_slug IS NOT NULL)));
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes agendador_cfg_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_cfg_select ON public.agendador_configuracoes FOR SELECT USING ((auth.uid() = owner_id));
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes agendador_cfg_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_cfg_write ON public.agendador_configuracoes USING ((auth.uid() = owner_id)) WITH CHECK ((auth.uid() = owner_id));
|
|
|
|
|
|
--
|
|
-- Name: agendador_configuracoes; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agendador_configuracoes ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes agendador_sol_owner_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_sol_owner_select ON public.agendador_solicitacoes FOR SELECT USING ((auth.uid() = owner_id));
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes agendador_sol_owner_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_sol_owner_write ON public.agendador_solicitacoes USING ((auth.uid() = owner_id)) WITH CHECK ((auth.uid() = owner_id));
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes agendador_sol_patient_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_sol_patient_read ON public.agendador_solicitacoes FOR SELECT TO authenticated USING (((auth.uid() = user_id) OR (auth.uid() = owner_id)));
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes agendador_sol_public_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_sol_public_insert ON public.agendador_solicitacoes FOR INSERT TO anon WITH CHECK (true);
|
|
|
|
|
|
--
|
|
-- Name: agendador_solicitacoes; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.agendador_solicitacoes ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: billing_contracts; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.billing_contracts ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: billing_contracts billing_contracts: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "billing_contracts: owner full access" ON public.billing_contracts USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios bloqueios_delete; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY bloqueios_delete ON public.agenda_bloqueios FOR DELETE TO authenticated USING ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios bloqueios_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY bloqueios_insert ON public.agenda_bloqueios FOR INSERT TO authenticated WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios bloqueios_select_clinic; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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]))))));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios bloqueios_select_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY bloqueios_select_own ON public.agenda_bloqueios FOR SELECT TO authenticated USING ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios bloqueios_update; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY bloqueios_update ON public.agenda_bloqueios FOR UPDATE TO authenticated USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: saas_docs clinic_admin_read_all_docs; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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])))))));
|
|
|
|
|
|
--
|
|
-- Name: commitment_services; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.commitment_services ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: commitment_services commitment_services: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "commitment_services: owner full access" ON public.commitment_services USING ((EXISTS ( SELECT 1
|
|
FROM public.services s
|
|
WHERE ((s.id = commitment_services.service_id) AND (s.owner_id = auth.uid()))))) WITH CHECK ((EXISTS ( SELECT 1
|
|
FROM public.services s
|
|
WHERE ((s.id = commitment_services.service_id) AND (s.owner_id = auth.uid())))));
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.commitment_time_logs ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: company_profiles; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.company_profiles ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: company_profiles company_profiles_delete; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY company_profiles_delete ON public.company_profiles FOR DELETE USING ((tenant_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: company_profiles company_profiles_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY company_profiles_insert ON public.company_profiles FOR INSERT WITH CHECK ((tenant_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: company_profiles company_profiles_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY company_profiles_select ON public.company_profiles FOR SELECT USING ((tenant_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: company_profiles company_profiles_update; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY company_profiles_update ON public.company_profiles FOR UPDATE USING ((tenant_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs ctl_delete_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs ctl_insert_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs ctl_select_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: commitment_time_logs ctl_update_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments dc_delete_custom_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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))))));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments dc_insert_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments dc_select_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitments dc_update_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields dcf_delete_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields dcf_insert_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields dcf_select_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields dcf_update_for_active_member; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios delete own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "delete own" ON public.agenda_bloqueios FOR DELETE USING ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: determined_commitment_fields; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.determined_commitment_fields ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: determined_commitments; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.determined_commitments ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: dev_user_credentials dev_creds_select_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: dev_user_credentials dev_creds_write_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)))));
|
|
|
|
|
|
--
|
|
-- Name: dev_user_credentials; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.dev_user_credentials ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: email_layout_config; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.email_layout_config ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: email_templates_global; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.email_templates_global ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: email_templates_tenant; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.email_templates_tenant ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: entitlements_invalidation ent_inv_select_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY ent_inv_select_own ON public.entitlements_invalidation FOR SELECT USING (((owner_id = auth.uid()) OR public.is_saas_admin()));
|
|
|
|
|
|
--
|
|
-- Name: entitlements_invalidation ent_inv_update_saas; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY ent_inv_update_saas ON public.entitlements_invalidation FOR UPDATE USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: entitlements_invalidation ent_inv_write_saas; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY ent_inv_write_saas ON public.entitlements_invalidation FOR INSERT WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: entitlements_invalidation; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.entitlements_invalidation ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: saas_faq faq_admin_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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]))))));
|
|
|
|
|
|
--
|
|
-- Name: saas_faq faq_auth_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY faq_auth_read ON public.saas_faq FOR SELECT TO authenticated USING ((ativo = true));
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_itens faq_itens_admin_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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]))))));
|
|
|
|
|
|
--
|
|
-- Name: saas_faq_itens faq_itens_auth_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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))))));
|
|
|
|
|
|
--
|
|
-- Name: saas_faq faq_public_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY faq_public_read ON public.saas_faq FOR SELECT USING (((publico = true) AND (ativo = true)));
|
|
|
|
|
|
--
|
|
-- Name: features; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.features ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: features features_read_authenticated; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY features_read_authenticated ON public.features FOR SELECT TO authenticated USING (true);
|
|
|
|
|
|
--
|
|
-- Name: features features_write_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY features_write_saas_admin ON public.features TO authenticated USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: feriados; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.feriados ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: feriados feriados_delete; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY feriados_delete ON public.feriados FOR DELETE USING ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_global_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY feriados_global_select ON public.feriados FOR SELECT USING ((tenant_id IS NULL));
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_saas_delete; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_saas_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_saas_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: feriados feriados_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: financial_categories; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.financial_categories ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: financial_categories financial_categories_self; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY financial_categories_self ON public.financial_categories USING ((auth.uid() = user_id)) WITH CHECK ((auth.uid() = user_id));
|
|
|
|
|
|
--
|
|
-- Name: financial_exceptions; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.financial_exceptions ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: financial_exceptions financial_exceptions: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "financial_exceptions: owner full access" ON public.financial_exceptions USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: financial_exceptions financial_exceptions: tenant members read clinic rules; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "financial_exceptions: tenant members read clinic rules" ON public.financial_exceptions FOR SELECT USING (((owner_id IS NULL) AND (EXISTS ( SELECT 1
|
|
FROM public.owner_users ou
|
|
WHERE ((ou.owner_id = financial_exceptions.tenant_id) AND (ou.user_id = auth.uid()))))));
|
|
|
|
|
|
--
|
|
-- Name: financial_records; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.financial_records ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: financial_records financial_records_self; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY financial_records_self ON public.financial_records USING ((auth.uid() = owner_id)) WITH CHECK ((auth.uid() = owner_id));
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_tenant_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY financial_records_tenant_admin ON public.financial_records FOR SELECT USING (((tenant_id IS NOT NULL) AND public.is_tenant_admin(tenant_id)));
|
|
|
|
|
|
--
|
|
-- Name: financial_records financial_records_tenant_member_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY financial_records_tenant_member_read ON public.financial_records FOR SELECT USING (((tenant_id IS NOT NULL) AND (EXISTS ( SELECT 1
|
|
FROM public.tenant_members tm
|
|
WHERE ((tm.tenant_id = financial_records.tenant_id) AND (tm.user_id = auth.uid()) AND (tm.status = 'active'::text))))));
|
|
|
|
|
|
--
|
|
-- Name: email_templates_global global templates readable by authenticated; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "global templates readable by authenticated" ON public.email_templates_global FOR SELECT USING ((auth.role() = 'authenticated'::text));
|
|
|
|
|
|
--
|
|
-- Name: global_notices; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.global_notices ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: global_notices global_notices_saas_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY global_notices_saas_all ON public.global_notices TO authenticated USING ((EXISTS ( SELECT 1
|
|
FROM public.saas_admins
|
|
WHERE (saas_admins.user_id = auth.uid()))));
|
|
|
|
|
|
--
|
|
-- Name: global_notices global_notices_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY global_notices_select ON public.global_notices FOR SELECT TO authenticated USING ((is_active = true));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios insert own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "insert own" ON public.agenda_bloqueios FOR INSERT WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: insurance_plan_services; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.insurance_plan_services ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: insurance_plan_services insurance_plan_services_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY insurance_plan_services_owner ON public.insurance_plan_services USING ((EXISTS ( SELECT 1
|
|
FROM public.insurance_plans ip
|
|
WHERE ((ip.id = insurance_plan_services.insurance_plan_id) AND (ip.owner_id = auth.uid()))))) WITH CHECK ((EXISTS ( SELECT 1
|
|
FROM public.insurance_plans ip
|
|
WHERE ((ip.id = insurance_plan_services.insurance_plan_id) AND (ip.owner_id = auth.uid())))));
|
|
|
|
|
|
--
|
|
-- Name: insurance_plans; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.insurance_plans ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: insurance_plans insurance_plans: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "insurance_plans: owner full access" ON public.insurance_plans USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: login_carousel_slides; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.login_carousel_slides ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: module_features; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.module_features ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: module_features module_features_read_authenticated; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY module_features_read_authenticated ON public.module_features FOR SELECT TO authenticated USING (true);
|
|
|
|
|
|
--
|
|
-- Name: module_features module_features_write_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY module_features_write_saas_admin ON public.module_features TO authenticated USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: modules; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.modules ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: modules modules_read_authenticated; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY modules_read_authenticated ON public.modules FOR SELECT TO authenticated USING (true);
|
|
|
|
|
|
--
|
|
-- Name: modules modules_write_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY modules_write_saas_admin ON public.modules TO authenticated USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: notice_dismissals; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.notice_dismissals ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: notice_dismissals notice_dismissals_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notice_dismissals_own ON public.notice_dismissals TO authenticated USING ((user_id = auth.uid())) WITH CHECK ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: notification_logs notif_logs_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notif_logs_owner ON public.notification_logs FOR SELECT USING ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: notification_preferences notif_prefs_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notif_prefs_owner ON public.notification_preferences USING (((owner_id = auth.uid()) AND (deleted_at IS NULL))) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: notification_queue notif_queue_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notif_queue_owner ON public.notification_queue FOR SELECT USING ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: notification_schedules notif_schedules_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notif_schedules_owner ON public.notification_schedules USING (((owner_id = auth.uid()) AND (deleted_at IS NULL))) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: notification_templates notif_templates_admin_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notif_templates_admin_all ON public.notification_templates 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()))));
|
|
|
|
|
|
--
|
|
-- Name: notification_templates notif_templates_read_global; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notif_templates_read_global ON public.notification_templates FOR SELECT TO authenticated USING (((deleted_at IS NULL) AND (((tenant_id IS NULL) AND (is_default = true)) OR (owner_id = auth.uid()) OR public.is_tenant_member(tenant_id))));
|
|
|
|
|
|
--
|
|
-- Name: notification_templates notif_templates_write_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notif_templates_write_owner ON public.notification_templates TO authenticated USING (((owner_id = auth.uid()) OR public.is_tenant_member(tenant_id))) WITH CHECK (((owner_id = auth.uid()) OR public.is_tenant_member(tenant_id)));
|
|
|
|
|
|
--
|
|
-- Name: notification_channels; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.notification_channels ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: notification_channels notification_channels_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY notification_channels_owner ON public.notification_channels USING (((owner_id = auth.uid()) AND (deleted_at IS NULL))) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: notification_logs; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.notification_logs ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: notification_preferences; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.notification_preferences ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: notification_queue; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.notification_queue ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: notification_schedules; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.notification_schedules ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: notification_templates; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.notification_templates ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: notifications; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.notifications ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: notifications owner only; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "owner only" ON public.notifications USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: owner_users; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.owner_users ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: owner_users owner_users: user can read own links; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "owner_users: user can read own links" ON public.owner_users FOR SELECT TO authenticated USING ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: patient_discounts; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.patient_discounts ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: patient_discounts patient_discounts: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "patient_discounts: owner full access" ON public.patient_discounts USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: patient_group_patient; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.patient_group_patient ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: patient_group_patient patient_group_patient_owner_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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())))));
|
|
|
|
|
|
--
|
|
-- Name: patient_group_patient patient_group_patient_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_group_patient patient_group_patient_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_groups; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.patient_groups ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: patient_groups patient_groups_owner_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY patient_groups_owner_all ON public.patient_groups TO authenticated USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: patient_groups patient_groups_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_groups patient_groups_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.patient_intake_requests ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: patient_intake_requests patient_intake_requests_owner_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()));
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests patient_intake_requests_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_intake_requests patient_intake_requests_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_invites; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.patient_invites ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: patient_invites patient_invites_owner_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY patient_invites_owner_all ON public.patient_invites TO authenticated USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: patient_invites patient_invites_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_invites patient_invites_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.patient_patient_tag ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: patient_patient_tag patient_patient_tag_owner_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()));
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag patient_patient_tag_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_patient_tag patient_patient_tag_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_tags; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.patient_tags ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: patient_tags patient_tags_owner_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY patient_tags_owner_all ON public.patient_tags TO authenticated USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: patient_tags patient_tags_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patient_tags patient_tags_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patients; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.patients ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: patients patients_delete; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patients patients_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patients patients_owner_all; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY patients_owner_all ON public.patients TO authenticated USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: patients patients_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: patients patients_update; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: payment_settings; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.payment_settings ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: payment_settings payment_settings: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "payment_settings: owner full access" ON public.payment_settings USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: plan_features; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.plan_features ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: plan_features plan_features_read_authenticated; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY plan_features_read_authenticated ON public.plan_features FOR SELECT TO authenticated USING (true);
|
|
|
|
|
|
--
|
|
-- Name: plan_features plan_features_write_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY plan_features_write_saas_admin ON public.plan_features TO authenticated USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: plans; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.plans ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: plans plans_read_authenticated; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY plans_read_authenticated ON public.plans FOR SELECT TO authenticated USING (true);
|
|
|
|
|
|
--
|
|
-- Name: plans plans_write_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY plans_write_saas_admin ON public.plans TO authenticated USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: professional_pricing; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.professional_pricing ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: professional_pricing professional_pricing: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "professional_pricing: owner full access" ON public.professional_pricing USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: profiles; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: profiles profiles_insert_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY profiles_insert_own ON public.profiles FOR INSERT WITH CHECK ((id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: profiles profiles_read_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY profiles_read_saas_admin ON public.profiles FOR SELECT USING (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: profiles profiles_select_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY profiles_select_own ON public.profiles FOR SELECT USING ((id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: profiles profiles_update_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY profiles_update_own ON public.profiles FOR UPDATE USING ((id = auth.uid())) WITH CHECK ((id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: login_carousel_slides public_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY public_read ON public.login_carousel_slides FOR SELECT USING ((ativo = true));
|
|
|
|
|
|
--
|
|
-- Name: features read features (auth); Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "read features (auth)" ON public.features FOR SELECT TO authenticated USING (true);
|
|
|
|
|
|
--
|
|
-- Name: plan_features read plan_features (auth); Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "read plan_features (auth)" ON public.plan_features FOR SELECT TO authenticated USING (true);
|
|
|
|
|
|
--
|
|
-- Name: plans read plans (auth); Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "read plans (auth)" ON public.plans FOR SELECT TO authenticated USING (true);
|
|
|
|
|
|
--
|
|
-- Name: recurrence_exceptions; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.recurrence_exceptions ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: recurrence_exceptions recurrence_exceptions_tenant; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.recurrence_rule_services ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: recurrence_rule_services recurrence_rule_services: clinic read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "recurrence_rule_services: clinic read" ON public.recurrence_rule_services FOR SELECT USING ((EXISTS ( SELECT 1
|
|
FROM public.recurrence_rules r
|
|
WHERE ((r.id = recurrence_rule_services.rule_id) AND public.is_clinic_tenant(r.tenant_id) AND public.is_tenant_member(r.tenant_id) AND public.tenant_has_feature(r.tenant_id, 'agenda.view'::text)))));
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services recurrence_rule_services: clinic write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "recurrence_rule_services: clinic write" ON public.recurrence_rule_services USING ((EXISTS ( SELECT 1
|
|
FROM public.recurrence_rules r
|
|
WHERE ((r.id = recurrence_rule_services.rule_id) AND public.is_clinic_tenant(r.tenant_id) AND public.is_tenant_member(r.tenant_id) AND public.tenant_has_feature(r.tenant_id, 'agenda.edit'::text))))) WITH CHECK ((EXISTS ( SELECT 1
|
|
FROM public.recurrence_rules r
|
|
WHERE ((r.id = recurrence_rule_services.rule_id) AND public.is_clinic_tenant(r.tenant_id) AND public.is_tenant_member(r.tenant_id) AND public.tenant_has_feature(r.tenant_id, 'agenda.edit'::text)))));
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rule_services recurrence_rule_services: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "recurrence_rule_services: owner full access" ON public.recurrence_rule_services TO authenticated USING ((EXISTS ( SELECT 1
|
|
FROM public.recurrence_rules r
|
|
WHERE ((r.id = recurrence_rule_services.rule_id) AND (r.owner_id = auth.uid()))))) WITH CHECK ((EXISTS ( SELECT 1
|
|
FROM public.recurrence_rules r
|
|
WHERE ((r.id = recurrence_rule_services.rule_id) AND (r.owner_id = auth.uid())))));
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.recurrence_rules ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: recurrence_rules recurrence_rules_clinic_read; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules recurrence_rules_clinic_write; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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)));
|
|
|
|
|
|
--
|
|
-- Name: recurrence_rules recurrence_rules_owner; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY recurrence_rules_owner ON public.recurrence_rules TO authenticated USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_legacy saas_admin can read subscription_intents; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_legacy saas_admin can update subscription_intents; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: login_carousel_slides saas_admin_full; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY saas_admin_full ON public.login_carousel_slides USING ((EXISTS ( SELECT 1
|
|
FROM public.profiles
|
|
WHERE ((profiles.id = auth.uid()) AND (profiles.role = 'saas_admin'::text)))));
|
|
|
|
|
|
--
|
|
-- Name: saas_docs saas_admin_full_access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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()))));
|
|
|
|
|
|
--
|
|
-- Name: saas_admins; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.saas_admins ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: saas_admins saas_admins_select_self; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY saas_admins_select_self ON public.saas_admins FOR SELECT TO authenticated USING ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.saas_doc_votos ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: saas_docs; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.saas_docs ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: saas_faq; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.saas_faq ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: saas_faq_itens; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.saas_faq_itens ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: agenda_bloqueios select own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "select own" ON public.agenda_bloqueios FOR SELECT USING ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: services; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.services ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: services services: owner full access; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "services: owner full access" ON public.services USING ((owner_id = auth.uid())) WITH CHECK ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: subscription_events; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.subscription_events ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: subscription_events subscription_events_read_saas; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY subscription_events_read_saas ON public.subscription_events FOR SELECT USING (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: subscription_events subscription_events_write_saas; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY subscription_events_write_saas ON public.subscription_events FOR INSERT WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_legacy subscription_intents_insert_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY subscription_intents_insert_own ON public.subscription_intents_legacy FOR INSERT TO authenticated WITH CHECK ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: subscription_intents_legacy; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.subscription_intents_legacy ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: subscription_intents_legacy subscription_intents_select_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY subscription_intents_select_own ON public.subscription_intents_legacy FOR SELECT TO authenticated USING ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: subscriptions; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.subscriptions ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions read own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "subscriptions read own" ON public.subscriptions FOR SELECT TO authenticated USING ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions: read if linked owner_users; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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())))));
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_insert_own_personal; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY subscriptions_insert_own_personal ON public.subscriptions FOR INSERT TO authenticated WITH CHECK (((user_id = auth.uid()) AND (tenant_id IS NULL)));
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_no_direct_update; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY subscriptions_no_direct_update ON public.subscriptions FOR UPDATE TO authenticated USING (false) WITH CHECK (false);
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_read_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY subscriptions_read_own ON public.subscriptions FOR SELECT TO authenticated USING (((user_id = auth.uid()) OR public.is_saas_admin()));
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_select_for_tenant_members; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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))))));
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_select_own_personal; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY subscriptions_select_own_personal ON public.subscriptions FOR SELECT TO authenticated USING (((user_id = auth.uid()) AND (tenant_id IS NULL)));
|
|
|
|
|
|
--
|
|
-- Name: subscriptions subscriptions_update_only_saas_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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());
|
|
|
|
|
|
--
|
|
-- Name: support_sessions; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.support_sessions ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: support_sessions support_sessions_saas_delete; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY support_sessions_saas_delete ON public.support_sessions FOR DELETE USING (((auth.uid() = admin_id) AND (EXISTS ( SELECT 1
|
|
FROM public.profiles
|
|
WHERE ((profiles.id = auth.uid()) AND (profiles.role = 'saas_admin'::text))))));
|
|
|
|
|
|
--
|
|
-- Name: support_sessions support_sessions_saas_insert; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY support_sessions_saas_insert ON public.support_sessions FOR INSERT WITH CHECK (((auth.uid() = admin_id) AND (EXISTS ( SELECT 1
|
|
FROM public.profiles
|
|
WHERE ((profiles.id = auth.uid()) AND (profiles.role = 'saas_admin'::text))))));
|
|
|
|
|
|
--
|
|
-- Name: support_sessions support_sessions_saas_select; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY support_sessions_saas_select ON public.support_sessions FOR SELECT USING (((auth.uid() = admin_id) AND (EXISTS ( SELECT 1
|
|
FROM public.profiles
|
|
WHERE ((profiles.id = auth.uid()) AND (profiles.role = 'saas_admin'::text))))));
|
|
|
|
|
|
--
|
|
-- Name: email_templates_tenant tenant manages own overrides; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "tenant manages own overrides" ON public.email_templates_tenant USING ((tenant_id = auth.uid())) WITH CHECK ((tenant_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: email_layout_config tenant owns email layout config; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "tenant owns email layout config" ON public.email_layout_config USING ((tenant_id = auth.uid())) WITH CHECK ((tenant_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: tenant_members; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.tenant_members ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: tenant_members tenant_members_write_saas; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY tenant_members_write_saas ON public.tenant_members TO authenticated USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: tenant_modules; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.tenant_modules ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: tenant_modules tenant_modules_read_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY tenant_modules_read_own ON public.tenant_modules FOR SELECT TO authenticated USING (((owner_id = auth.uid()) OR public.is_saas_admin()));
|
|
|
|
|
|
--
|
|
-- Name: tenant_modules tenant_modules_write_saas; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY tenant_modules_write_saas ON public.tenant_modules TO authenticated USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: tenants; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.tenants ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: tenants tenants_read_members; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
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))))));
|
|
|
|
|
|
--
|
|
-- Name: tenants tenants_write_saas; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY tenants_write_saas ON public.tenants TO authenticated USING (public.is_saas_admin()) WITH CHECK (public.is_saas_admin());
|
|
|
|
|
|
--
|
|
-- Name: therapist_payout_records; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.therapist_payout_records ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: therapist_payout_records therapist_payout_records_self; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY therapist_payout_records_self ON public.therapist_payout_records USING ((EXISTS ( SELECT 1
|
|
FROM public.therapist_payouts tp
|
|
WHERE ((tp.id = therapist_payout_records.payout_id) AND (tp.owner_id = auth.uid()))))) WITH CHECK ((EXISTS ( SELECT 1
|
|
FROM public.therapist_payouts tp
|
|
WHERE ((tp.id = therapist_payout_records.payout_id) AND (tp.owner_id = auth.uid())))));
|
|
|
|
|
|
--
|
|
-- Name: therapist_payout_records therapist_payout_records_tenant_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY therapist_payout_records_tenant_admin ON public.therapist_payout_records FOR SELECT USING ((EXISTS ( SELECT 1
|
|
FROM public.therapist_payouts tp
|
|
WHERE ((tp.id = therapist_payout_records.payout_id) AND public.is_tenant_admin(tp.tenant_id)))));
|
|
|
|
|
|
--
|
|
-- Name: therapist_payouts; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.therapist_payouts ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: therapist_payouts therapist_payouts_self; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY therapist_payouts_self ON public.therapist_payouts USING ((auth.uid() = owner_id)) WITH CHECK ((auth.uid() = owner_id));
|
|
|
|
|
|
--
|
|
-- Name: therapist_payouts therapist_payouts_tenant_admin; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY therapist_payouts_tenant_admin ON public.therapist_payouts FOR SELECT USING (((tenant_id IS NOT NULL) AND public.is_tenant_admin(tenant_id)));
|
|
|
|
|
|
--
|
|
-- Name: tenant_members tm_select_admin_all_members; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY tm_select_admin_all_members ON public.tenant_members FOR SELECT TO authenticated USING (public.is_tenant_admin(tenant_id));
|
|
|
|
|
|
--
|
|
-- Name: tenant_members tm_select_own_membership; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY tm_select_own_membership ON public.tenant_members FOR SELECT TO authenticated USING ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: agenda_bloqueios update own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "update own" ON public.agenda_bloqueios FOR UPDATE USING ((owner_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: user_settings; Type: ROW SECURITY; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER TABLE public.user_settings ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: user_settings user_settings_insert_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY user_settings_insert_own ON public.user_settings FOR INSERT WITH CHECK ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: user_settings user_settings_select_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY user_settings_select_own ON public.user_settings FOR SELECT USING ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: user_settings user_settings_update_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY user_settings_update_own ON public.user_settings FOR UPDATE USING ((user_id = auth.uid())) WITH CHECK ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: saas_docs users_read_usuario_docs; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY users_read_usuario_docs ON public.saas_docs FOR SELECT TO authenticated USING (((ativo = true) AND (tipo_acesso = 'usuario'::text)));
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos votos_select_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY votos_select_own ON public.saas_doc_votos FOR SELECT TO authenticated USING ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: saas_doc_votos votos_upsert_own; Type: POLICY; Schema: public; Owner: -
|
|
--
|
|
|
|
CREATE POLICY votos_upsert_own ON public.saas_doc_votos TO authenticated USING ((user_id = auth.uid())) WITH CHECK ((user_id = auth.uid()));
|
|
|
|
|
|
--
|
|
-- Name: messages; Type: ROW SECURITY; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER TABLE realtime.messages ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: objects agendador_storage_owner_delete; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_storage_owner_delete ON storage.objects FOR DELETE TO authenticated USING (((bucket_id = 'agendador'::text) AND ((storage.foldername(name))[1] = (auth.uid())::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects agendador_storage_owner_insert; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_storage_owner_insert ON storage.objects FOR INSERT TO authenticated WITH CHECK (((bucket_id = 'agendador'::text) AND ((storage.foldername(name))[1] = (auth.uid())::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects agendador_storage_owner_update; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_storage_owner_update ON storage.objects FOR UPDATE TO authenticated USING (((bucket_id = 'agendador'::text) AND ((storage.foldername(name))[1] = (auth.uid())::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects agendador_storage_public_read; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY agendador_storage_public_read ON storage.objects FOR SELECT USING ((bucket_id = 'agendador'::text));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars authenticated upload; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "avatars authenticated upload" ON storage.objects FOR INSERT WITH CHECK (((bucket_id = 'avatars'::text) AND (auth.role() = 'authenticated'::text) AND ((storage.foldername(name))[1] = (auth.uid())::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars owner delete; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "avatars owner delete" ON storage.objects FOR DELETE USING (((bucket_id = 'avatars'::text) AND ((storage.foldername(name))[1] = (auth.uid())::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars owner update; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "avatars owner update" ON storage.objects FOR UPDATE USING (((bucket_id = 'avatars'::text) AND ((storage.foldername(name))[1] = (auth.uid())::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars public read; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY "avatars public read" ON storage.objects FOR SELECT USING ((bucket_id = 'avatars'::text));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars_delete_own; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY avatars_delete_own ON storage.objects FOR DELETE TO authenticated USING (((bucket_id = 'avatars'::text) AND (name ~~ ((auth.uid())::text || '/%'::text))));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars_delete_own_folder; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY avatars_delete_own_folder ON storage.objects FOR DELETE USING (((bucket_id = 'avatars'::text) AND (auth.role() = 'authenticated'::text) AND (name ~~ (('owners/'::text || auth.uid()) || '/%'::text))));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars_insert_own; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY avatars_insert_own ON storage.objects FOR INSERT TO authenticated WITH CHECK (((bucket_id = 'avatars'::text) AND (name ~~ ((auth.uid())::text || '/%'::text))));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars_insert_own_folder; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY avatars_insert_own_folder ON storage.objects FOR INSERT WITH CHECK (((bucket_id = 'avatars'::text) AND (auth.role() = 'authenticated'::text) AND (name ~~ (('owners/'::text || auth.uid()) || '/%'::text))));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars_read; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY avatars_read ON storage.objects FOR SELECT USING ((bucket_id = 'avatars'::text));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars_select_own; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY avatars_select_own ON storage.objects FOR SELECT TO authenticated USING (((bucket_id = 'avatars'::text) AND (name ~~ ((auth.uid())::text || '/%'::text))));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars_update_own; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY avatars_update_own ON storage.objects FOR UPDATE TO authenticated USING (((bucket_id = 'avatars'::text) AND (name ~~ ((auth.uid())::text || '/%'::text)))) WITH CHECK (((bucket_id = 'avatars'::text) AND (name ~~ ((auth.uid())::text || '/%'::text))));
|
|
|
|
|
|
--
|
|
-- Name: objects avatars_update_own_folder; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY avatars_update_own_folder ON storage.objects FOR UPDATE USING (((bucket_id = 'avatars'::text) AND (auth.role() = 'authenticated'::text) AND (name ~~ (('owners/'::text || auth.uid()) || '/%'::text)))) WITH CHECK (((bucket_id = 'avatars'::text) AND (auth.role() = 'authenticated'::text) AND (name ~~ (('owners/'::text || auth.uid()) || '/%'::text))));
|
|
|
|
|
|
--
|
|
-- Name: buckets; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.buckets ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: buckets_analytics; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.buckets_analytics ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: buckets_vectors; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.buckets_vectors ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: iceberg_namespaces; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.iceberg_namespaces ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: iceberg_tables; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.iceberg_tables ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: objects intake_read_anon; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY intake_read_anon ON storage.objects FOR SELECT TO anon USING (((bucket_id = 'avatars'::text) AND (name ~~ 'intakes/%'::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects intake_read_public; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY intake_read_public ON storage.objects FOR SELECT USING (((bucket_id = 'avatars'::text) AND (name ~~ 'intakes/%'::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects intake_upload_anon; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY intake_upload_anon ON storage.objects FOR INSERT TO anon WITH CHECK (((bucket_id = 'avatars'::text) AND (name ~~ 'intakes/%'::text)));
|
|
|
|
|
|
--
|
|
-- Name: objects intake_upload_public; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY intake_upload_public ON storage.objects FOR INSERT WITH CHECK (((bucket_id = 'avatars'::text) AND (name ~~ 'intakes/%'::text)));
|
|
|
|
|
|
--
|
|
-- Name: migrations; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.migrations ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: objects; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.objects ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: objects public_read; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY public_read ON storage.objects FOR SELECT USING ((bucket_id = 'saas-docs'::text));
|
|
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.s3_multipart_uploads ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: s3_multipart_uploads_parts; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.s3_multipart_uploads_parts ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: objects saas_admin_delete; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY saas_admin_delete ON storage.objects FOR DELETE TO authenticated USING (((bucket_id = 'saas-docs'::text) AND (EXISTS ( SELECT 1
|
|
FROM public.saas_admins
|
|
WHERE (saas_admins.user_id = auth.uid())))));
|
|
|
|
|
|
--
|
|
-- Name: objects saas_admin_upload; Type: POLICY; Schema: storage; Owner: -
|
|
--
|
|
|
|
CREATE POLICY saas_admin_upload ON storage.objects FOR INSERT TO authenticated WITH CHECK (((bucket_id = 'saas-docs'::text) AND (EXISTS ( SELECT 1
|
|
FROM public.saas_admins
|
|
WHERE (saas_admins.user_id = auth.uid())))));
|
|
|
|
|
|
--
|
|
-- Name: vector_indexes; Type: ROW SECURITY; Schema: storage; Owner: -
|
|
--
|
|
|
|
ALTER TABLE storage.vector_indexes ENABLE ROW LEVEL SECURITY;
|
|
|
|
--
|
|
-- Name: supabase_realtime; Type: PUBLICATION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE PUBLICATION supabase_realtime WITH (publish = 'insert, update, delete, truncate');
|
|
|
|
|
|
--
|
|
-- Name: supabase_realtime_messages_publication; Type: PUBLICATION; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE PUBLICATION supabase_realtime_messages_publication WITH (publish = 'insert, update, delete, truncate');
|
|
|
|
|
|
--
|
|
-- Name: supabase_realtime notifications; Type: PUBLICATION TABLE; Schema: public; Owner: -
|
|
--
|
|
|
|
ALTER PUBLICATION supabase_realtime ADD TABLE ONLY public.notifications;
|
|
|
|
|
|
--
|
|
-- Name: supabase_realtime_messages_publication messages; Type: PUBLICATION TABLE; Schema: realtime; Owner: -
|
|
--
|
|
|
|
ALTER PUBLICATION supabase_realtime_messages_publication ADD TABLE ONLY realtime.messages;
|
|
|
|
|
|
--
|
|
-- Name: issue_graphql_placeholder; Type: EVENT TRIGGER; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EVENT TRIGGER issue_graphql_placeholder ON sql_drop
|
|
WHEN TAG IN ('DROP EXTENSION')
|
|
EXECUTE FUNCTION extensions.set_graphql_placeholder();
|
|
|
|
|
|
--
|
|
-- Name: issue_pg_cron_access; Type: EVENT TRIGGER; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EVENT TRIGGER issue_pg_cron_access ON ddl_command_end
|
|
WHEN TAG IN ('CREATE EXTENSION')
|
|
EXECUTE FUNCTION extensions.grant_pg_cron_access();
|
|
|
|
|
|
--
|
|
-- Name: issue_pg_graphql_access; Type: EVENT TRIGGER; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EVENT TRIGGER issue_pg_graphql_access ON ddl_command_end
|
|
WHEN TAG IN ('CREATE FUNCTION')
|
|
EXECUTE FUNCTION extensions.grant_pg_graphql_access();
|
|
|
|
|
|
--
|
|
-- Name: issue_pg_net_access; Type: EVENT TRIGGER; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EVENT TRIGGER issue_pg_net_access ON ddl_command_end
|
|
WHEN TAG IN ('CREATE EXTENSION')
|
|
EXECUTE FUNCTION extensions.grant_pg_net_access();
|
|
|
|
|
|
--
|
|
-- Name: pgrst_ddl_watch; Type: EVENT TRIGGER; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EVENT TRIGGER pgrst_ddl_watch ON ddl_command_end
|
|
EXECUTE FUNCTION extensions.pgrst_ddl_watch();
|
|
|
|
|
|
--
|
|
-- Name: pgrst_drop_watch; Type: EVENT TRIGGER; Schema: -; Owner: -
|
|
--
|
|
|
|
CREATE EVENT TRIGGER pgrst_drop_watch ON sql_drop
|
|
EXECUTE FUNCTION extensions.pgrst_drop_watch();
|
|
|
|
|
|
--
|
|
-- PostgreSQL database dump complete
|
|
--
|
|
|
|
\unrestrict bF1wUs8GdUoGkTriiI6ANM1G5CWmXBDmeY0qMLRMwq4O6xbnSjM03LBj5DO29ct
|
|
|