From 03ccd97f99f55a69a423d5084a594ecb01704135 Mon Sep 17 00:00:00 2001 From: George Date: Mon, 19 Oct 2026 17:46:44 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20par=C3=A1metros=20ocultos=20(t=C3=ADtul?= =?UTF-8?q?os=20y=20separadores)=20de=20los=20reportes=20Crystal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/gateway/gateway.controller.ts | 1 + libs/sap-types/src/gateway.spec.ts | 6 ++++++ libs/sap-types/src/gateway.ts | 7 ++++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/api/src/gateway/gateway.controller.ts b/apps/api/src/gateway/gateway.controller.ts index 45636bc..035693f 100644 --- a/apps/api/src/gateway/gateway.controller.ts +++ b/apps/api/src/gateway/gateway.controller.ts @@ -14,6 +14,7 @@ const paramSchema = z.object({ label: text(120).min(1), kind: z.enum(['text', 'number', 'date', 'select', 'lookup']), required: z.boolean(), + hidden: z.boolean().optional(), range: z.boolean().optional(), multiple: z.boolean().optional(), defaultValue: text(200).optional(), diff --git a/libs/sap-types/src/gateway.spec.ts b/libs/sap-types/src/gateway.spec.ts index ca96347..db7c625 100644 --- a/libs/sap-types/src/gateway.spec.ts +++ b/libs/sap-types/src/gateway.spec.ts @@ -8,11 +8,13 @@ describe('paramsFromLoadCr', () => { { name: 'Dockey@', type: 'xsd:decimal', description: 'Especificar Dockey@:', isOptionalPrompt: 'false', valueRangeKind: 'Discrete', allowMultiValue: 'false' }, { name: 'BP@From OCRD', type: 'xsd:string', description: 'Socios de negocios', isOptionalPrompt: 'true', allowMultiValue: 'true', defaultValues: ['C1'] }, { type: 'xsd:string' }, + { name: 'Title_Items@Title', type: 'xsd:string', description: 'Artículos', isOptionalPrompt: 'false' }, ]); expect(params).toEqual([ { name: 'PWZRunDate', type: 'xsd:date', label: 'Fecha de ejecución de pago', kind: 'date', required: false, range: true }, { name: 'Dockey@', type: 'xsd:decimal', label: 'Dockey@', kind: 'number', required: true }, { name: 'BP@From OCRD', type: 'xsd:string', label: 'Socios de negocios', kind: 'text', required: false, multiple: true, defaultValue: 'C1' }, + { name: 'Title_Items@Title', type: 'xsd:string', label: 'Artículos', kind: 'text', required: false, hidden: true }, ]); }); }); @@ -36,6 +38,10 @@ describe('exportBody', () => { expect(r.missing).toEqual(['Cliente']); }); + it('los títulos del reporte no se piden ni se envían', () => { + expect(exportBody([p({ name: 'T@Title', hidden: true, required: true })], { 'T@Title': 'x' }).body).toEqual([]); + }); + it('ignora valores de parámetros que no están matriculados', () => { expect(exportBody([p({ name: 'A' })], { A: '1', Otro: '2' }).body.map((b) => b.name)).toEqual(['A']); }); diff --git a/libs/sap-types/src/gateway.ts b/libs/sap-types/src/gateway.ts index e7fb0b6..b9b8850 100644 --- a/libs/sap-types/src/gateway.ts +++ b/libs/sap-types/src/gateway.ts @@ -23,6 +23,8 @@ export interface GatewayParam { placeholder?: string; /** Opciones de una lista fija (`kind = select`). */ options?: { value: string; label: string }[]; + /** Un título o separador del reporte (`Title_Items@Title`, `Sep_item@separator`): no se pide al usuario ni se envía. */ + hidden?: boolean; /** Ventana de selección (`kind = lookup`): identificador de su catálogo en la web (`socios`, `articulos`, `doc:Invoices`…). */ lookup?: string; } @@ -70,12 +72,14 @@ export function paramsFromLoadCr(resultSet: readonly CrystalParameter[]): Gatewa .map((p) => { const type = p.type ?? 'xsd:string'; const first = p.defaultValues?.[0]; + const decorative = /@(title|separator)$/i.test(p.name); return { name: p.name, type, label: (p.description ?? p.name).replace(/[:\s]+$/, '').replace(/^Especificar\s+/i, '') || p.name, kind: /date/i.test(type) ? 'date' : NUMERIC.test(type) ? 'number' : 'text', - required: p.isOptionalPrompt !== 'true', + required: decorative ? false : p.isOptionalPrompt !== 'true', + ...(decorative ? { hidden: true } : {}), ...(p.valueRangeKind === 'Range' ? { range: true } : {}), ...(p.allowMultiValue === 'true' ? { multiple: true } : {}), ...(first !== undefined && first !== null && first !== '' ? { defaultValue: String(first) } : {}), @@ -94,6 +98,7 @@ export function exportBody(params: readonly GatewayParam[], values: GatewayValue const body: { name: string; type: string; value: string[][] }[] = []; const missing: string[] = []; for (const p of params) { + if (p.hidden) continue; const raw = values[p.name]; if (isBlank(raw)) { if (p.required) missing.push(p.label);