312 lines
12 KiB
PL/PgSQL
312 lines
12 KiB
PL/PgSQL
-- ============================================================
|
|
-- CRUCE DE CUENTAS GLM · HABILITAR PUERTO RICO (PR)
|
|
-- GT + TT + PA + SV + HN + PR
|
|
-- ============================================================
|
|
-- Ejecutar una sola vez en el SQL Editor del Supabase empresarial.
|
|
-- Es idempotente respecto a PR: conserva datos existentes y puede
|
|
-- volver a ejecutarse si se interrumpe antes del COMMIT.
|
|
|
|
begin;
|
|
|
|
-- 1) Validar tablas requeridas y ampliar constraints de país.
|
|
do $$
|
|
declare r record;
|
|
begin
|
|
if to_regclass('public.cruce_cuentas_bamboo_aliases') is null then raise exception 'No existe public.cruce_cuentas_bamboo_aliases.'; end if;
|
|
if to_regclass('public.cruce_cuentas_bamboo_correcciones') is null then raise exception 'No existe public.cruce_cuentas_bamboo_correcciones.'; end if;
|
|
if to_regclass('public.cruces_cuentas_gt_reportes') is null then raise exception 'No existe public.cruces_cuentas_gt_reportes.'; end if;
|
|
if to_regclass('public.cruce_cuentas_usuarios_autorizados') is null then raise exception 'No existe public.cruce_cuentas_usuarios_autorizados.'; end if;
|
|
|
|
-- Alias BambooHR.
|
|
for r in
|
|
select conname
|
|
from pg_constraint
|
|
where conrelid='public.cruce_cuentas_bamboo_aliases'::regclass
|
|
and contype='c'
|
|
and pg_get_constraintdef(oid) ilike '%pais%'
|
|
and pg_get_constraintdef(oid) ilike '%GT%'
|
|
and pg_get_constraintdef(oid) not ilike '%PR%'
|
|
loop
|
|
execute format('alter table public.cruce_cuentas_bamboo_aliases drop constraint %I',r.conname);
|
|
end loop;
|
|
alter table public.cruce_cuentas_bamboo_aliases drop constraint if exists ck_cruce_cuentas_bamboo_aliases_pais;
|
|
alter table public.cruce_cuentas_bamboo_aliases
|
|
add constraint ck_cruce_cuentas_bamboo_aliases_pais
|
|
check (upper(trim(pais)) in ('GT','TT','PA','SV','HN','PR'));
|
|
|
|
-- Solicitudes/correcciones BambooHR.
|
|
for r in
|
|
select conname
|
|
from pg_constraint
|
|
where conrelid='public.cruce_cuentas_bamboo_correcciones'::regclass
|
|
and contype='c'
|
|
and pg_get_constraintdef(oid) ilike '%pais%'
|
|
and pg_get_constraintdef(oid) ilike '%GT%'
|
|
and pg_get_constraintdef(oid) not ilike '%PR%'
|
|
loop
|
|
execute format('alter table public.cruce_cuentas_bamboo_correcciones drop constraint %I',r.conname);
|
|
end loop;
|
|
alter table public.cruce_cuentas_bamboo_correcciones drop constraint if exists ck_cruce_cuentas_bamboo_correcciones_pais;
|
|
alter table public.cruce_cuentas_bamboo_correcciones
|
|
add constraint ck_cruce_cuentas_bamboo_correcciones_pais
|
|
check (upper(trim(pais)) in ('GT','TT','PA','SV','HN','PR'));
|
|
|
|
-- Históricos multi-país (el nombre de la tabla es legado).
|
|
for r in
|
|
select conname
|
|
from pg_constraint
|
|
where conrelid='public.cruces_cuentas_gt_reportes'::regclass
|
|
and contype='c'
|
|
and pg_get_constraintdef(oid) ilike '%country%'
|
|
and pg_get_constraintdef(oid) ilike '%GT%'
|
|
and pg_get_constraintdef(oid) not ilike '%PR%'
|
|
loop
|
|
execute format('alter table public.cruces_cuentas_gt_reportes drop constraint %I',r.conname);
|
|
end loop;
|
|
alter table public.cruces_cuentas_gt_reportes drop constraint if exists ck_cruces_cuentas_reportes_country;
|
|
alter table public.cruces_cuentas_gt_reportes
|
|
add constraint ck_cruces_cuentas_reportes_country
|
|
check (country is null or upper(trim(country)) in ('GT','TT','PA','SV','HN','PR'));
|
|
|
|
-- Accesos: text[] de países habilitados.
|
|
alter table public.cruce_cuentas_usuarios_autorizados drop constraint if exists cruce_cuentas_paises_validos_check;
|
|
alter table public.cruce_cuentas_usuarios_autorizados
|
|
add constraint cruce_cuentas_paises_validos_check
|
|
check (paises is null or paises <@ array['GT','TT','PA','SV','HN','PR']::text[]);
|
|
end;
|
|
$$;
|
|
|
|
-- 2) Dar PR a todos los usuarios actualmente autorizados, preservando permisos.
|
|
update public.cruce_cuentas_usuarios_autorizados
|
|
set paises = case
|
|
when paises is null then array['GT','TT','PA','SV','HN','PR']::text[]
|
|
when not ('PR'=any(paises)) then array_append(paises,'PR')
|
|
else paises
|
|
end,
|
|
updated_at = now();
|
|
|
|
-- 3) Alias BambooHR activos: habilitar PR en la función compartida.
|
|
create or replace function public.cruce_cuentas_bamboo_aliases_activos(p_pais text)
|
|
returns jsonb
|
|
language sql
|
|
stable
|
|
security definer
|
|
set search_path=public
|
|
as $$
|
|
select jsonb_build_object(
|
|
'ok',true,
|
|
'pais',upper(trim(coalesce(p_pais,''))),
|
|
'aliases',coalesce(
|
|
jsonb_agg(
|
|
jsonb_build_object(
|
|
'id',a.id,
|
|
'pais',a.pais,
|
|
'nombre_origen',a.nombre_origen,
|
|
'nombre_origen_normalizado',a.nombre_origen_normalizado,
|
|
'cuenta_bancaria',a.cuenta_bancaria,
|
|
'bamboo_employee_number',a.bamboo_employee_number,
|
|
'bamboo_employee_id',a.bamboo_employee_id,
|
|
'bamboo_nombre',a.bamboo_nombre,
|
|
'motivo',a.motivo,
|
|
'activo',a.activo
|
|
) order by a.updated_at desc
|
|
) filter (where a.id is not null),
|
|
'[]'::jsonb
|
|
)
|
|
)
|
|
from public.cruce_cuentas_bamboo_aliases a
|
|
where a.activo=true
|
|
and a.pais=upper(trim(coalesce(p_pais,'')))
|
|
and upper(trim(coalesce(p_pais,''))) in ('GT','TT','PA','SV','HN','PR');
|
|
$$;
|
|
revoke all on function public.cruce_cuentas_bamboo_aliases_activos(text) from public,anon,authenticated;
|
|
grant execute on function public.cruce_cuentas_bamboo_aliases_activos(text) to service_role;
|
|
|
|
-- 4) Históricos paginados multi-país, incluyendo PR.
|
|
create index if not exists idx_cruces_cuentas_reportes_country_created
|
|
on public.cruces_cuentas_gt_reportes(country,created_at desc);
|
|
create index if not exists idx_cruces_cuentas_reportes_country_status_created
|
|
on public.cruces_cuentas_gt_reportes(country,estado,created_at desc);
|
|
|
|
create or replace function public.cruce_cuentas_get_historicos(
|
|
p_country text,
|
|
p_page integer default 1,
|
|
p_page_size integer default 10,
|
|
p_search text default null,
|
|
p_status text default null
|
|
)
|
|
returns jsonb
|
|
language plpgsql
|
|
security definer
|
|
set search_path=public
|
|
as $$
|
|
declare
|
|
v_country text := upper(trim(coalesce(p_country,'')));
|
|
v_page integer := greatest(coalesce(p_page,1),1);
|
|
v_page_size integer := least(greatest(coalesce(p_page_size,10),1),100);
|
|
v_offset integer;
|
|
v_search text := nullif(trim(coalesce(p_search,'')),'');
|
|
v_status text := nullif(trim(coalesce(p_status,'')),'');
|
|
v_total bigint;
|
|
v_filtered_total bigint;
|
|
v_reports jsonb;
|
|
begin
|
|
if v_country not in ('GT','TT','PA','SV','HN','PR') then
|
|
raise exception 'País no permitido: %',v_country;
|
|
end if;
|
|
|
|
v_offset := (v_page-1)*v_page_size;
|
|
|
|
select count(*) into v_total
|
|
from public.cruces_cuentas_gt_reportes r
|
|
where upper(coalesce(r.country,'GT'))=v_country;
|
|
|
|
select count(*) into v_filtered_total
|
|
from public.cruces_cuentas_gt_reportes r
|
|
where upper(coalesce(r.country,'GT'))=v_country
|
|
and (v_status is null or r.estado=v_status)
|
|
and (
|
|
v_search is null
|
|
or coalesce(r.period_label,'') ilike '%'||v_search||'%'
|
|
or coalesce(r.payroll_file_name,'') ilike '%'||v_search||'%'
|
|
or coalesce(r.ejecutado_por_nombre,'') ilike '%'||v_search||'%'
|
|
or coalesce(r.resuelto_por_nombre,'') ilike '%'||v_search||'%'
|
|
or r.id::text ilike '%'||v_search||'%'
|
|
);
|
|
|
|
select coalesce(
|
|
jsonb_agg((to_jsonb(q)-'detalle_banco_sin_bamboo') order by q.created_at desc),
|
|
'[]'::jsonb
|
|
) into v_reports
|
|
from (
|
|
select r.*
|
|
from public.cruces_cuentas_gt_reportes r
|
|
where upper(coalesce(r.country,'GT'))=v_country
|
|
and (v_status is null or r.estado=v_status)
|
|
and (
|
|
v_search is null
|
|
or coalesce(r.period_label,'') ilike '%'||v_search||'%'
|
|
or coalesce(r.payroll_file_name,'') ilike '%'||v_search||'%'
|
|
or coalesce(r.ejecutado_por_nombre,'') ilike '%'||v_search||'%'
|
|
or coalesce(r.resuelto_por_nombre,'') ilike '%'||v_search||'%'
|
|
or r.id::text ilike '%'||v_search||'%'
|
|
)
|
|
order by r.created_at desc
|
|
limit v_page_size offset v_offset
|
|
) q;
|
|
|
|
return jsonb_build_object(
|
|
'ok',true,
|
|
'country',v_country,
|
|
'page',v_page,
|
|
'page_size',v_page_size,
|
|
'total',v_total,
|
|
'filtered_total',v_filtered_total,
|
|
'total_pages',greatest(ceil(v_filtered_total::numeric/v_page_size)::integer,1),
|
|
'reports',v_reports
|
|
);
|
|
end;
|
|
$$;
|
|
revoke all on function public.cruce_cuentas_get_historicos(text,integer,integer,text,text) from public,anon;
|
|
grant execute on function public.cruce_cuentas_get_historicos(text,integer,integer,text,text) to authenticated;
|
|
|
|
-- 5) Detalle Banco sin BambooHR de históricos, incluyendo PR.
|
|
create or replace function public.cruce_cuentas_get_banco_sin_bamboo_reporte(
|
|
p_report_id text,
|
|
p_country text
|
|
)
|
|
returns jsonb
|
|
language plpgsql
|
|
stable
|
|
security definer
|
|
set search_path=public
|
|
as $$
|
|
declare
|
|
v_country text := upper(trim(coalesce(p_country,'')));
|
|
v_report public.cruces_cuentas_gt_reportes%rowtype;
|
|
v_corrections jsonb := '[]'::jsonb;
|
|
begin
|
|
if auth.uid() is null then raise exception 'No autenticado.'; end if;
|
|
if v_country not in ('GT','TT','PA','SV','HN','PR') then raise exception 'País no permitido: %',v_country; end if;
|
|
|
|
select r.* into v_report
|
|
from public.cruces_cuentas_gt_reportes r
|
|
where r.id::text=trim(coalesce(p_report_id,''))
|
|
and upper(coalesce(r.country,'GT'))=v_country
|
|
limit 1;
|
|
|
|
if not found then
|
|
return jsonb_build_object('ok',false,'message','No se encontró el reporte solicitado.');
|
|
end if;
|
|
|
|
select coalesce(
|
|
jsonb_agg(
|
|
jsonb_build_object(
|
|
'id',c.id,
|
|
'pais',c.pais,
|
|
'nombre_origen_principal',c.nombre_origen_principal,
|
|
'nombres_origen',c.nombres_origen,
|
|
'cuenta_bancaria',c.cuenta_bancaria,
|
|
'bamboo_employee_number',c.bamboo_employee_number,
|
|
'bamboo_nombre',c.bamboo_nombre,
|
|
'estado',c.estado,
|
|
'correo_enviado',c.correo_enviado,
|
|
'correo_enviado_at',c.correo_enviado_at,
|
|
'created_at',c.created_at
|
|
) order by c.created_at desc
|
|
),
|
|
'[]'::jsonb
|
|
) into v_corrections
|
|
from public.cruce_cuentas_bamboo_correcciones c
|
|
where c.pais=v_country
|
|
and (
|
|
c.execution_id=v_report.id::text
|
|
or (
|
|
nullif(trim(coalesce(c.execution_id,'')),'') is null
|
|
and nullif(trim(coalesce(c.report_url,'')),'') is not null
|
|
and c.report_url=v_report.report_url
|
|
)
|
|
);
|
|
|
|
return jsonb_build_object(
|
|
'ok',true,
|
|
'report',jsonb_build_object(
|
|
'id',v_report.id,
|
|
'country',v_report.country,
|
|
'period_label',v_report.period_label,
|
|
'period_start',v_report.period_start,
|
|
'period_end',v_report.period_end,
|
|
'report_url',v_report.report_url,
|
|
'banco_sin_bamboo',v_report.banco_sin_bamboo
|
|
),
|
|
'cases',coalesce(v_report.detalle_banco_sin_bamboo,'[]'::jsonb),
|
|
'corrections',v_corrections
|
|
);
|
|
end;
|
|
$$;
|
|
revoke all on function public.cruce_cuentas_get_banco_sin_bamboo_reporte(text,text) from public,anon;
|
|
grant execute on function public.cruce_cuentas_get_banco_sin_bamboo_reporte(text,text) to authenticated;
|
|
|
|
commit;
|
|
|
|
-- ============================================================
|
|
-- VALIDACIÓN (solo lectura)
|
|
-- ============================================================
|
|
select email,nombre,paises
|
|
from public.cruce_cuentas_usuarios_autorizados
|
|
order by email;
|
|
|
|
select conname, pg_get_constraintdef(oid) as definicion
|
|
from pg_constraint
|
|
where conrelid in (
|
|
'public.cruce_cuentas_bamboo_aliases'::regclass,
|
|
'public.cruce_cuentas_bamboo_correcciones'::regclass,
|
|
'public.cruces_cuentas_gt_reportes'::regclass,
|
|
'public.cruce_cuentas_usuarios_autorizados'::regclass
|
|
)
|
|
and contype='c'
|
|
and (pg_get_constraintdef(oid) ilike '%pais%' or pg_get_constraintdef(oid) ilike '%country%')
|
|
order by conname;
|
|
|
|
select public.cruce_cuentas_get_historicos('PR',1,10,null,null) as historicos_pr;
|