feat: actualizar Tablero CDC con administracion de listas
This commit is contained in:
@@ -0,0 +1,572 @@
|
||||
-- =============================================================
|
||||
-- TABLERO CDC — Bandeja de revisión de CDC Brief
|
||||
-- Fecha: 2026-08-12
|
||||
--
|
||||
-- Objetivo:
|
||||
-- 1) Recibir automáticamente briefs creados por CDC Brief.
|
||||
-- 2) Mantenerlos fuera de tablero_cdc_projects mientras están en revisión.
|
||||
-- 3) Aprobarlos de forma transaccional como proyectos Activos.
|
||||
-- 4) Mover los descartados a "No aprobados" sin crear proyecto.
|
||||
-- 5) Mantener un contador de briefs no vistos independiente por usuario.
|
||||
--
|
||||
-- Este script NO altera la lógica existente de proyectos, tarifarios,
|
||||
-- tiempos, Google Sheet ni Banco Fulgencio.
|
||||
-- =============================================================
|
||||
|
||||
begin;
|
||||
|
||||
create extension if not exists pgcrypto;
|
||||
|
||||
create table if not exists public.tablero_cdc_brief_inbox (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
brief_id text not null unique,
|
||||
source_created_at timestamptz,
|
||||
title text not null default '',
|
||||
client text not null default '',
|
||||
brand text not null default '',
|
||||
country text not null default '',
|
||||
requested_by text not null default '',
|
||||
requested_by_email text not null default '',
|
||||
delivery_date text not null default '',
|
||||
brief_link text not null default '',
|
||||
document_link text not null default '',
|
||||
summary text not null default '',
|
||||
request_type text not null default '',
|
||||
deliverable_type text not null default '',
|
||||
raw_fields jsonb not null default '{}'::jsonb,
|
||||
review_status text not null default 'new',
|
||||
rejection_reason text,
|
||||
approved_project_id uuid references public.tablero_cdc_projects(id) on delete set null,
|
||||
reviewed_by uuid references auth.users(id) on delete set null,
|
||||
reviewed_by_name text,
|
||||
reviewed_by_email text,
|
||||
reviewed_at timestamptz,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
-- Compatibilidad idempotente si el script se vuelve a ejecutar tras una instalación parcial.
|
||||
alter table public.tablero_cdc_brief_inbox
|
||||
add column if not exists source_created_at timestamptz,
|
||||
add column if not exists title text not null default '',
|
||||
add column if not exists client text not null default '',
|
||||
add column if not exists brand text not null default '',
|
||||
add column if not exists country text not null default '',
|
||||
add column if not exists requested_by text not null default '',
|
||||
add column if not exists requested_by_email text not null default '',
|
||||
add column if not exists delivery_date text not null default '',
|
||||
add column if not exists brief_link text not null default '',
|
||||
add column if not exists document_link text not null default '',
|
||||
add column if not exists summary text not null default '',
|
||||
add column if not exists request_type text not null default '',
|
||||
add column if not exists deliverable_type text not null default '',
|
||||
add column if not exists raw_fields jsonb not null default '{}'::jsonb,
|
||||
add column if not exists review_status text not null default 'new',
|
||||
add column if not exists rejection_reason text,
|
||||
add column if not exists approved_project_id uuid references public.tablero_cdc_projects(id) on delete set null,
|
||||
add column if not exists reviewed_by uuid references auth.users(id) on delete set null,
|
||||
add column if not exists reviewed_by_name text,
|
||||
add column if not exists reviewed_by_email text,
|
||||
add column if not exists reviewed_at timestamptz,
|
||||
add column if not exists created_at timestamptz not null default now(),
|
||||
add column if not exists updated_at timestamptz not null default now();
|
||||
|
||||
do $$
|
||||
begin
|
||||
if not exists (
|
||||
select 1
|
||||
from pg_constraint
|
||||
where conname = 'tablero_cdc_brief_inbox_review_status_check'
|
||||
and conrelid = 'public.tablero_cdc_brief_inbox'::regclass
|
||||
) then
|
||||
alter table public.tablero_cdc_brief_inbox
|
||||
add constraint tablero_cdc_brief_inbox_review_status_check
|
||||
check (review_status in ('new', 'approved', 'rejected'));
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
create index if not exists tablero_cdc_brief_inbox_status_created_idx
|
||||
on public.tablero_cdc_brief_inbox (review_status, created_at desc);
|
||||
|
||||
create index if not exists tablero_cdc_brief_inbox_source_created_idx
|
||||
on public.tablero_cdc_brief_inbox (source_created_at desc);
|
||||
|
||||
create index if not exists tablero_cdc_brief_inbox_approved_project_idx
|
||||
on public.tablero_cdc_brief_inbox (approved_project_id)
|
||||
where approved_project_id is not null;
|
||||
|
||||
create or replace function public.tablero_cdc_brief_inbox_touch_updated_at()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
new.updated_at = now();
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists tablero_cdc_brief_inbox_touch_updated_at
|
||||
on public.tablero_cdc_brief_inbox;
|
||||
|
||||
create trigger tablero_cdc_brief_inbox_touch_updated_at
|
||||
before update on public.tablero_cdc_brief_inbox
|
||||
for each row
|
||||
execute function public.tablero_cdc_brief_inbox_touch_updated_at();
|
||||
|
||||
-- Verifica que la sesión corresponda a un usuario activo del Tablero CDC.
|
||||
create or replace function public.tablero_cdc_is_active_allowed_user()
|
||||
returns boolean
|
||||
language sql
|
||||
stable
|
||||
security definer
|
||||
set search_path = public, auth
|
||||
as $$
|
||||
select exists (
|
||||
select 1
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where lower(trim(u.email)) = lower(trim(coalesce(auth.jwt() ->> 'email', '')))
|
||||
and u.is_active = true
|
||||
);
|
||||
$$;
|
||||
|
||||
revoke all on function public.tablero_cdc_is_active_allowed_user() from public;
|
||||
grant execute on function public.tablero_cdc_is_active_allowed_user() to authenticated;
|
||||
|
||||
alter table public.tablero_cdc_brief_inbox enable row level security;
|
||||
|
||||
drop policy if exists "tablero_cdc_brief_inbox_select_allowed"
|
||||
on public.tablero_cdc_brief_inbox;
|
||||
|
||||
create policy "tablero_cdc_brief_inbox_select_allowed"
|
||||
on public.tablero_cdc_brief_inbox
|
||||
for select
|
||||
to authenticated
|
||||
using (public.tablero_cdc_is_active_allowed_user());
|
||||
|
||||
-- El frontend solo necesita SELECT directo. Las decisiones se realizan por RPC
|
||||
-- para que aprobar + crear proyecto sea una sola transacción.
|
||||
revoke insert, update, delete on public.tablero_cdc_brief_inbox from authenticated;
|
||||
grant select on public.tablero_cdc_brief_inbox to authenticated;
|
||||
grant all on public.tablero_cdc_brief_inbox to service_role;
|
||||
|
||||
-- =============================================================
|
||||
-- NOTIFICACIONES PERSONALES DE "NUEVOS"
|
||||
-- =============================================================
|
||||
-- Cada usuario conserva su propio estado de lectura. Se registra la pareja
|
||||
-- (usuario, brief) en vez de un timestamp global para evitar carreras: un brief
|
||||
-- que llegue después de que alguien abrió "Nuevos" seguirá siendo no leído.
|
||||
create table if not exists public.tablero_cdc_brief_inbox_seen (
|
||||
user_id uuid not null references auth.users(id) on delete cascade,
|
||||
inbox_id uuid not null references public.tablero_cdc_brief_inbox(id) on delete cascade,
|
||||
seen_at timestamptz not null default now(),
|
||||
primary key (user_id, inbox_id)
|
||||
);
|
||||
|
||||
create index if not exists tablero_cdc_brief_inbox_seen_inbox_idx
|
||||
on public.tablero_cdc_brief_inbox_seen (inbox_id);
|
||||
|
||||
alter table public.tablero_cdc_brief_inbox_seen enable row level security;
|
||||
|
||||
drop policy if exists "tablero_cdc_brief_inbox_seen_select_own"
|
||||
on public.tablero_cdc_brief_inbox_seen;
|
||||
|
||||
create policy "tablero_cdc_brief_inbox_seen_select_own"
|
||||
on public.tablero_cdc_brief_inbox_seen
|
||||
for select
|
||||
to authenticated
|
||||
using (
|
||||
user_id = auth.uid()
|
||||
and public.tablero_cdc_is_active_allowed_user()
|
||||
);
|
||||
|
||||
-- La aplicación lee el contador mediante RPC y marca vistos mediante RPC.
|
||||
-- No concedemos escritura directa a authenticated.
|
||||
revoke insert, update, delete on public.tablero_cdc_brief_inbox_seen from authenticated;
|
||||
grant select on public.tablero_cdc_brief_inbox_seen to authenticated;
|
||||
grant all on public.tablero_cdc_brief_inbox_seen to service_role;
|
||||
|
||||
create or replace function public.tablero_cdc_get_unseen_brief_count()
|
||||
returns integer
|
||||
language plpgsql
|
||||
stable
|
||||
security definer
|
||||
set search_path = public, auth
|
||||
as $$
|
||||
declare
|
||||
v_count integer;
|
||||
begin
|
||||
if auth.uid() is null or not public.tablero_cdc_is_active_allowed_user() then
|
||||
raise exception 'No tienes permiso para consultar notificaciones de briefs.';
|
||||
end if;
|
||||
|
||||
select count(*)::integer
|
||||
into v_count
|
||||
from public.tablero_cdc_brief_inbox i
|
||||
where i.review_status = 'new'
|
||||
and not exists (
|
||||
select 1
|
||||
from public.tablero_cdc_brief_inbox_seen s
|
||||
where s.user_id = auth.uid()
|
||||
and s.inbox_id = i.id
|
||||
);
|
||||
|
||||
return coalesce(v_count, 0);
|
||||
end;
|
||||
$$;
|
||||
|
||||
revoke all on function public.tablero_cdc_get_unseen_brief_count() from public;
|
||||
grant execute on function public.tablero_cdc_get_unseen_brief_count() to authenticated;
|
||||
|
||||
create or replace function public.tablero_cdc_mark_briefs_seen()
|
||||
returns jsonb
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path = public, auth
|
||||
as $$
|
||||
declare
|
||||
v_marked integer := 0;
|
||||
v_remaining integer := 0;
|
||||
begin
|
||||
if auth.uid() is null or not public.tablero_cdc_is_active_allowed_user() then
|
||||
raise exception 'No tienes permiso para marcar briefs como vistos.';
|
||||
end if;
|
||||
|
||||
insert into public.tablero_cdc_brief_inbox_seen (user_id, inbox_id, seen_at)
|
||||
select auth.uid(), i.id, now()
|
||||
from public.tablero_cdc_brief_inbox i
|
||||
where i.review_status = 'new'
|
||||
on conflict (user_id, inbox_id) do nothing;
|
||||
|
||||
get diagnostics v_marked = row_count;
|
||||
|
||||
-- Si un brief nuevo entró concurrentemente después del snapshot anterior,
|
||||
-- se conserva como no leído en vez de borrarle la notificación por accidente.
|
||||
select count(*)::integer
|
||||
into v_remaining
|
||||
from public.tablero_cdc_brief_inbox i
|
||||
where i.review_status = 'new'
|
||||
and not exists (
|
||||
select 1
|
||||
from public.tablero_cdc_brief_inbox_seen s
|
||||
where s.user_id = auth.uid()
|
||||
and s.inbox_id = i.id
|
||||
);
|
||||
|
||||
return jsonb_build_object(
|
||||
'ok', true,
|
||||
'marked_count', v_marked,
|
||||
'unseen_count', coalesce(v_remaining, 0)
|
||||
);
|
||||
end;
|
||||
$$;
|
||||
|
||||
revoke all on function public.tablero_cdc_mark_briefs_seen() from public;
|
||||
grant execute on function public.tablero_cdc_mark_briefs_seen() to authenticated;
|
||||
|
||||
-- =============================================================
|
||||
-- RPC: APROBAR BRIEF
|
||||
-- =============================================================
|
||||
create or replace function public.tablero_cdc_approve_brief(p_inbox_id uuid)
|
||||
returns jsonb
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path = public, auth
|
||||
as $$
|
||||
declare
|
||||
v_item public.tablero_cdc_brief_inbox%rowtype;
|
||||
v_project_id uuid;
|
||||
v_email text;
|
||||
v_name text;
|
||||
v_country_manager text := '';
|
||||
v_title text;
|
||||
v_description text;
|
||||
v_activity_description text;
|
||||
begin
|
||||
if auth.uid() is null or not public.tablero_cdc_is_active_allowed_user() then
|
||||
raise exception 'No tienes permiso para revisar briefs del Tablero CDC.';
|
||||
end if;
|
||||
|
||||
select *
|
||||
into v_item
|
||||
from public.tablero_cdc_brief_inbox
|
||||
where id = p_inbox_id
|
||||
for update;
|
||||
|
||||
if not found then
|
||||
raise exception 'No se encontró el brief solicitado.';
|
||||
end if;
|
||||
|
||||
-- Idempotencia: si el usuario repite el clic o se reintenta la petición
|
||||
-- después de haber completado la transacción, devolvemos el mismo proyecto.
|
||||
if v_item.review_status = 'approved' and v_item.approved_project_id is not null then
|
||||
return jsonb_build_object(
|
||||
'ok', true,
|
||||
'already_approved', true,
|
||||
'project_id', v_item.approved_project_id,
|
||||
'brief_id', v_item.brief_id
|
||||
);
|
||||
end if;
|
||||
|
||||
if v_item.review_status not in ('new', 'rejected') then
|
||||
raise exception 'Este brief ya fue revisado y no puede aprobarse desde esta bandeja.';
|
||||
end if;
|
||||
|
||||
-- Seguridad adicional: un brief rechazado no debe conservar un proyecto asociado.
|
||||
-- Si existiera una inconsistencia manual, detenemos la operación para evitar duplicados.
|
||||
if v_item.review_status = 'rejected' and v_item.approved_project_id is not null then
|
||||
raise exception 'Este brief rechazado ya tiene un proyecto asociado. Revisa los datos antes de aprobarlo.';
|
||||
end if;
|
||||
|
||||
v_activity_description := case
|
||||
when v_item.review_status = 'rejected'
|
||||
then 'El brief fue recuperado de Rechazados y aprobado como proyecto Activo.'
|
||||
else 'El brief fue revisado y aprobado desde la bandeja Nuevos.'
|
||||
end;
|
||||
|
||||
v_email := lower(trim(coalesce(auth.jwt() ->> 'email', '')));
|
||||
|
||||
select coalesce(nullif(trim(u.full_name), ''), nullif(trim(u.email), ''), 'Usuario CDC')
|
||||
into v_name
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where lower(trim(u.email)) = v_email
|
||||
and u.is_active = true
|
||||
limit 1;
|
||||
|
||||
v_name := coalesce(v_name, nullif(v_email, ''), 'Usuario CDC');
|
||||
|
||||
-- Si existe el mapeo BU -> CM en las listas dinámicas, lo reutilizamos.
|
||||
-- Si no existe, se deja vacío y el proyecto continúa siendo válido/editable.
|
||||
begin
|
||||
select coalesce(nullif(trim(l.label), ''), '')
|
||||
into v_country_manager
|
||||
from public.tablero_cdc_app_lists l
|
||||
where l.is_active = true
|
||||
and lower(trim(coalesce(l.value, ''))) = lower(trim(coalesce(v_item.country, '')))
|
||||
and lower(trim(coalesce(l.category, ''))) in (
|
||||
'country_manager', 'country manager', 'cm', 'bu_cm', 'bu cm', 'manager', 'managers'
|
||||
)
|
||||
order by coalesce(l.sort_order, 999999), l.label
|
||||
limit 1;
|
||||
exception
|
||||
when undefined_table then
|
||||
v_country_manager := '';
|
||||
end;
|
||||
|
||||
v_title := coalesce(
|
||||
nullif(trim(v_item.title), ''),
|
||||
nullif(trim(v_item.client), ''),
|
||||
'Brief CDC ' || v_item.brief_id
|
||||
);
|
||||
|
||||
v_description := coalesce(nullif(trim(v_item.summary), ''), '');
|
||||
|
||||
insert into public.tablero_cdc_projects (
|
||||
title,
|
||||
client,
|
||||
brand,
|
||||
country,
|
||||
requested_by,
|
||||
country_manager,
|
||||
description,
|
||||
status,
|
||||
internal_amount,
|
||||
brief_link,
|
||||
extra_data,
|
||||
created_by,
|
||||
updated_by
|
||||
)
|
||||
values (
|
||||
v_title,
|
||||
coalesce(v_item.client, ''),
|
||||
coalesce(v_item.brand, ''),
|
||||
coalesce(v_item.country, ''),
|
||||
coalesce(v_item.requested_by, ''),
|
||||
coalesce(v_country_manager, ''),
|
||||
v_description,
|
||||
'Activo',
|
||||
null,
|
||||
coalesce(nullif(trim(v_item.brief_link), ''), nullif(trim(v_item.document_link), ''), ''),
|
||||
jsonb_strip_nulls(
|
||||
jsonb_build_object(
|
||||
'source', 'cdc_brief',
|
||||
'source_brief_id', v_item.brief_id,
|
||||
'source_brief_inbox_id', v_item.id,
|
||||
'source_brief_created_at', v_item.source_created_at,
|
||||
'cdc_brief_document_link', nullif(trim(v_item.document_link), ''),
|
||||
'delivery_date', nullif(trim(v_item.delivery_date), ''),
|
||||
'request_type', nullif(trim(v_item.request_type), ''),
|
||||
'deliverable_type', nullif(trim(v_item.deliverable_type), ''),
|
||||
'cdc_brief_fields', v_item.raw_fields,
|
||||
'color', 'blue'
|
||||
)
|
||||
),
|
||||
auth.uid(),
|
||||
auth.uid()
|
||||
)
|
||||
returning id into v_project_id;
|
||||
|
||||
update public.tablero_cdc_brief_inbox
|
||||
set
|
||||
review_status = 'approved',
|
||||
approved_project_id = v_project_id,
|
||||
reviewed_by = auth.uid(),
|
||||
reviewed_by_name = v_name,
|
||||
reviewed_by_email = v_email,
|
||||
reviewed_at = now(),
|
||||
rejection_reason = null
|
||||
where id = v_item.id;
|
||||
|
||||
-- Mantiene el historial existente cuando el módulo de actividad ya está instalado,
|
||||
-- sin convertirlo en una dependencia obligatoria de esta migración.
|
||||
if to_regclass('public.tablero_cdc_project_activity') is not null then
|
||||
execute $activity$
|
||||
insert into public.tablero_cdc_project_activity (
|
||||
project_id,
|
||||
activity_type,
|
||||
title,
|
||||
description,
|
||||
actor_id,
|
||||
actor_name,
|
||||
actor_email
|
||||
)
|
||||
values ($1, 'created', 'Proyecto creado desde CDC Brief',
|
||||
$5, $2, $3, $4)
|
||||
$activity$
|
||||
using v_project_id, auth.uid(), v_name, v_email, v_activity_description;
|
||||
end if;
|
||||
|
||||
return jsonb_build_object(
|
||||
'ok', true,
|
||||
'already_approved', false,
|
||||
'project_id', v_project_id,
|
||||
'brief_id', v_item.brief_id
|
||||
);
|
||||
end;
|
||||
$$;
|
||||
|
||||
revoke all on function public.tablero_cdc_approve_brief(uuid) from public;
|
||||
grant execute on function public.tablero_cdc_approve_brief(uuid) to authenticated;
|
||||
|
||||
-- =============================================================
|
||||
-- RPC: NO APROBAR BRIEF
|
||||
-- =============================================================
|
||||
create or replace function public.tablero_cdc_reject_brief(
|
||||
p_inbox_id uuid,
|
||||
p_reason text default null
|
||||
)
|
||||
returns jsonb
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path = public, auth
|
||||
as $$
|
||||
declare
|
||||
v_item public.tablero_cdc_brief_inbox%rowtype;
|
||||
v_email text;
|
||||
v_name text;
|
||||
begin
|
||||
if auth.uid() is null or not public.tablero_cdc_is_active_allowed_user() then
|
||||
raise exception 'No tienes permiso para revisar briefs del Tablero CDC.';
|
||||
end if;
|
||||
|
||||
select *
|
||||
into v_item
|
||||
from public.tablero_cdc_brief_inbox
|
||||
where id = p_inbox_id
|
||||
for update;
|
||||
|
||||
if not found then
|
||||
raise exception 'No se encontró el brief solicitado.';
|
||||
end if;
|
||||
|
||||
if v_item.review_status = 'rejected' then
|
||||
return jsonb_build_object(
|
||||
'ok', true,
|
||||
'already_rejected', true,
|
||||
'brief_id', v_item.brief_id
|
||||
);
|
||||
end if;
|
||||
|
||||
if v_item.review_status <> 'new' then
|
||||
raise exception 'Este brief ya fue aprobado y no puede enviarse a No aprobados.';
|
||||
end if;
|
||||
|
||||
v_email := lower(trim(coalesce(auth.jwt() ->> 'email', '')));
|
||||
|
||||
select coalesce(nullif(trim(u.full_name), ''), nullif(trim(u.email), ''), 'Usuario CDC')
|
||||
into v_name
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where lower(trim(u.email)) = v_email
|
||||
and u.is_active = true
|
||||
limit 1;
|
||||
|
||||
v_name := coalesce(v_name, nullif(v_email, ''), 'Usuario CDC');
|
||||
|
||||
update public.tablero_cdc_brief_inbox
|
||||
set
|
||||
review_status = 'rejected',
|
||||
rejection_reason = nullif(trim(coalesce(p_reason, '')), ''),
|
||||
reviewed_by = auth.uid(),
|
||||
reviewed_by_name = v_name,
|
||||
reviewed_by_email = v_email,
|
||||
reviewed_at = now(),
|
||||
approved_project_id = null
|
||||
where id = v_item.id;
|
||||
|
||||
return jsonb_build_object(
|
||||
'ok', true,
|
||||
'already_rejected', false,
|
||||
'brief_id', v_item.brief_id
|
||||
);
|
||||
end;
|
||||
$$;
|
||||
|
||||
revoke all on function public.tablero_cdc_reject_brief(uuid, text) from public;
|
||||
grant execute on function public.tablero_cdc_reject_brief(uuid, text) to authenticated;
|
||||
|
||||
-- Realtime para que un brief nuevo o una decisión aparezcan/desaparezcan
|
||||
-- sin que otro miembro del equipo tenga que recargar la página.
|
||||
do $$
|
||||
begin
|
||||
if exists (select 1 from pg_publication where pubname = 'supabase_realtime')
|
||||
and not exists (
|
||||
select 1
|
||||
from pg_publication_tables
|
||||
where pubname = 'supabase_realtime'
|
||||
and schemaname = 'public'
|
||||
and tablename = 'tablero_cdc_brief_inbox'
|
||||
) then
|
||||
alter publication supabase_realtime add table public.tablero_cdc_brief_inbox;
|
||||
end if;
|
||||
|
||||
if exists (select 1 from pg_publication where pubname = 'supabase_realtime')
|
||||
and not exists (
|
||||
select 1
|
||||
from pg_publication_tables
|
||||
where pubname = 'supabase_realtime'
|
||||
and schemaname = 'public'
|
||||
and tablename = 'tablero_cdc_brief_inbox_seen'
|
||||
) then
|
||||
alter publication supabase_realtime add table public.tablero_cdc_brief_inbox_seen;
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
commit;
|
||||
|
||||
-- =============================================================
|
||||
-- VERIFICACIÓN
|
||||
-- =============================================================
|
||||
select
|
||||
review_status,
|
||||
count(*) as cantidad
|
||||
from public.tablero_cdc_brief_inbox
|
||||
group by review_status
|
||||
order by review_status;
|
||||
|
||||
select
|
||||
proname as funcion,
|
||||
pg_get_function_identity_arguments(p.oid) as argumentos
|
||||
from pg_proc p
|
||||
join pg_namespace n on n.oid = p.pronamespace
|
||||
where n.nspname = 'public'
|
||||
and proname in ('tablero_cdc_approve_brief', 'tablero_cdc_reject_brief', 'tablero_cdc_get_unseen_brief_count', 'tablero_cdc_mark_briefs_seen')
|
||||
order by proname;
|
||||
Reference in New Issue
Block a user