Agregar Bono 14 Guatemala y actualizar dist
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
-- ============================================================
|
||||
-- Cruce de Cuentas GLM - Bono 14 Guatemala
|
||||
-- Script incremental / idempotente
|
||||
-- ============================================================
|
||||
-- Objetivo:
|
||||
-- Habilitar y verificar que Bono 14 use la MISMA infraestructura
|
||||
-- de reporte único ya instalada, pero con una identidad independiente:
|
||||
--
|
||||
-- GT-<AÑO>-07-bono14
|
||||
--
|
||||
-- Ejemplo:
|
||||
-- GT-2026-07-bono14
|
||||
--
|
||||
-- No crea otra tabla de históricos y no elimina datos existentes.
|
||||
-- Puede ejecutarse nuevamente sin borrar reportes.
|
||||
-- ============================================================
|
||||
|
||||
begin;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1. Validación de prerrequisitos de la versión "reporte único"
|
||||
-- ------------------------------------------------------------
|
||||
do $$
|
||||
declare
|
||||
v_missing text[] := array[]::text[];
|
||||
begin
|
||||
if to_regclass('public.cruces_cuentas_gt_reportes') is null then
|
||||
raise exception
|
||||
'No existe public.cruces_cuentas_gt_reportes. Instala primero la estructura base de Cruce de Cuentas.';
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'cruces_cuentas_gt_reportes'
|
||||
and column_name = 'report_identity'
|
||||
) then
|
||||
v_missing := array_append(v_missing, 'report_identity');
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'cruces_cuentas_gt_reportes'
|
||||
and column_name = 'updated_at'
|
||||
) then
|
||||
v_missing := array_append(v_missing, 'updated_at');
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'cruces_cuentas_gt_reportes'
|
||||
and column_name = 'country'
|
||||
) then
|
||||
v_missing := array_append(v_missing, 'country');
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'cruces_cuentas_gt_reportes'
|
||||
and column_name = 'year'
|
||||
) then
|
||||
v_missing := array_append(v_missing, 'year');
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'cruces_cuentas_gt_reportes'
|
||||
and column_name = 'month'
|
||||
) then
|
||||
v_missing := array_append(v_missing, 'month');
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = 'public'
|
||||
and table_name = 'cruces_cuentas_gt_reportes'
|
||||
and column_name = 'period_type'
|
||||
) then
|
||||
v_missing := array_append(v_missing, 'period_type');
|
||||
end if;
|
||||
|
||||
if cardinality(v_missing) > 0 then
|
||||
raise exception
|
||||
'Faltan columnas requeridas en public.cruces_cuentas_gt_reportes: %. Ejecuta primero el script de REPORTE ÚNICO POR PERÍODO.',
|
||||
array_to_string(v_missing, ', ');
|
||||
end if;
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2. Constructor canónico de identidad
|
||||
-- ------------------------------------------------------------
|
||||
-- Se mantiene genérico para nómina GT, nómina TT y Bono 14.
|
||||
create or replace function public.cruce_cuentas_build_report_identity(
|
||||
p_country text,
|
||||
p_year integer,
|
||||
p_month integer,
|
||||
p_period_type text
|
||||
)
|
||||
returns text
|
||||
language sql
|
||||
immutable
|
||||
as $$
|
||||
select
|
||||
upper(trim(coalesce(p_country, 'GT')))
|
||||
|| '-' ||
|
||||
coalesce(p_year, 0)::text
|
||||
|| '-' ||
|
||||
lpad(coalesce(p_month, 0)::text, 2, '0')
|
||||
|| '-' ||
|
||||
lower(trim(coalesce(p_period_type, 'periodo')));
|
||||
$$;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3. Trigger de identidad / updated_at
|
||||
-- ------------------------------------------------------------
|
||||
-- Reinstalado de forma idempotente para garantizar que un UPSERT de
|
||||
-- Bono 14 mantenga la misma identidad y actualice updated_at.
|
||||
create or replace function public.cruce_cuentas_set_report_identity()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
set search_path = public
|
||||
as $$
|
||||
declare
|
||||
v_canonical text;
|
||||
begin
|
||||
v_canonical :=
|
||||
public.cruce_cuentas_build_report_identity(
|
||||
coalesce(new.country, 'GT'),
|
||||
new.year,
|
||||
new.month,
|
||||
new.period_type
|
||||
);
|
||||
|
||||
if tg_op = 'INSERT' then
|
||||
if nullif(trim(coalesce(new.report_identity, '')), '') is null then
|
||||
new.report_identity := v_canonical;
|
||||
end if;
|
||||
else
|
||||
-- Los duplicados históricos antiguos conservan su sufijo :legacy:.
|
||||
if coalesce(old.report_identity, '') like '%:legacy:%' then
|
||||
new.report_identity := old.report_identity;
|
||||
else
|
||||
new.report_identity := v_canonical;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
new.updated_at := now();
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists trg_cruce_cuentas_report_identity
|
||||
on public.cruces_cuentas_gt_reportes;
|
||||
|
||||
create trigger trg_cruce_cuentas_report_identity
|
||||
before insert or update on public.cruces_cuentas_gt_reportes
|
||||
for each row
|
||||
execute function public.cruce_cuentas_set_report_identity();
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4. Garantizar unicidad por identidad
|
||||
-- ------------------------------------------------------------
|
||||
-- La versión de reporte único ya debe tener este índice. Se valida antes
|
||||
-- de recrearlo para no alterar ni eliminar históricos existentes.
|
||||
do $$
|
||||
begin
|
||||
if not exists (
|
||||
select 1
|
||||
from pg_indexes
|
||||
where schemaname = 'public'
|
||||
and tablename = 'cruces_cuentas_gt_reportes'
|
||||
and indexname = 'ux_cruces_cuentas_reportes_report_identity'
|
||||
) then
|
||||
if exists (
|
||||
select report_identity
|
||||
from public.cruces_cuentas_gt_reportes
|
||||
where report_identity is not null
|
||||
group by report_identity
|
||||
having count(*) > 1
|
||||
) then
|
||||
raise exception
|
||||
'Existen report_identity duplicados. Ejecuta primero el script de REPORTE ÚNICO POR PERÍODO para aplicar su backfill seguro antes de Bono 14.';
|
||||
end if;
|
||||
|
||||
create unique index ux_cruces_cuentas_reportes_report_identity
|
||||
on public.cruces_cuentas_gt_reportes (report_identity);
|
||||
end if;
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- Índice auxiliar específico para consultas/soporte de Bono 14.
|
||||
create index if not exists ix_cruces_cuentas_gt_reportes_bono14_updated
|
||||
on public.cruces_cuentas_gt_reportes (year, updated_at desc)
|
||||
where upper(coalesce(country, 'GT')) = 'GT'
|
||||
and lower(coalesce(period_type, '')) = 'bono14';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 5. RPC que n8n consulta ANTES de crear/reutilizar el Google Sheet
|
||||
-- ------------------------------------------------------------
|
||||
create or replace function public.cruce_cuentas_get_reporte_periodo(
|
||||
p_country text,
|
||||
p_year integer,
|
||||
p_month integer,
|
||||
p_period_type text
|
||||
)
|
||||
returns jsonb
|
||||
language plpgsql
|
||||
stable
|
||||
security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
declare
|
||||
v_identity text;
|
||||
v_report public.cruces_cuentas_gt_reportes%rowtype;
|
||||
begin
|
||||
v_identity :=
|
||||
public.cruce_cuentas_build_report_identity(
|
||||
p_country,
|
||||
p_year,
|
||||
p_month,
|
||||
p_period_type
|
||||
);
|
||||
|
||||
select r.*
|
||||
into v_report
|
||||
from public.cruces_cuentas_gt_reportes r
|
||||
where r.report_identity = v_identity
|
||||
order by
|
||||
r.updated_at desc nulls last,
|
||||
r.created_at desc nulls last
|
||||
limit 1;
|
||||
|
||||
if not found then
|
||||
return jsonb_build_object(
|
||||
'ok', true,
|
||||
'found', false,
|
||||
'report_identity', v_identity,
|
||||
'report', null
|
||||
);
|
||||
end if;
|
||||
|
||||
return jsonb_build_object(
|
||||
'ok', true,
|
||||
'found', true,
|
||||
'report_identity', v_identity,
|
||||
'report', jsonb_build_object(
|
||||
'id', v_report.id,
|
||||
'report_identity', v_report.report_identity,
|
||||
'country', v_report.country,
|
||||
'year', v_report.year,
|
||||
'month', v_report.month,
|
||||
'period_type', v_report.period_type,
|
||||
'period_label', v_report.period_label,
|
||||
'spreadsheet_id', v_report.spreadsheet_id,
|
||||
'report_url', v_report.report_url,
|
||||
'estado', v_report.estado,
|
||||
'created_at', v_report.created_at,
|
||||
'updated_at', v_report.updated_at
|
||||
)
|
||||
);
|
||||
end;
|
||||
$$;
|
||||
|
||||
revoke all on function public.cruce_cuentas_get_reporte_periodo(text, integer, integer, text)
|
||||
from public, anon, authenticated;
|
||||
|
||||
grant execute on function public.cruce_cuentas_get_reporte_periodo(text, integer, integer, text)
|
||||
to service_role;
|
||||
|
||||
commit;
|
||||
|
||||
-- ============================================================
|
||||
-- VALIDACIÓN FINAL (solo lectura)
|
||||
-- Debe devolver: GT-2026-07-bono14
|
||||
-- ============================================================
|
||||
select
|
||||
public.cruce_cuentas_build_report_identity(
|
||||
'GT',
|
||||
2026,
|
||||
7,
|
||||
'bono14'
|
||||
) as identidad_bono14_esperada;
|
||||
|
||||
-- Si ya existe un Bono 14 2026, esta consulta devuelve found=true.
|
||||
-- Si todavía no se ha generado, devuelve found=false (lo esperado antes
|
||||
-- de la primera ejecución).
|
||||
select public.cruce_cuentas_get_reporte_periodo(
|
||||
'GT',
|
||||
2026,
|
||||
7,
|
||||
'bono14'
|
||||
) as estado_bono14_2026;
|
||||
Reference in New Issue
Block a user