Skip to content

feat(tools): filtros de rango de fecha en las tools get_*#7

Open
Asermar wants to merge 1 commit into
FacturaScripts:mainfrom
Asermar:feat/date-range-filters
Open

feat(tools): filtros de rango de fecha en las tools get_*#7
Asermar wants to merge 1 commit into
FacturaScripts:mainfrom
Asermar:feat/date-range-filters

Conversation

@Asermar

@Asermar Asermar commented Jul 25, 2026

Copy link
Copy Markdown

Problema

Las tools get_* solo permiten filtrar por fecha exacta (un único parámetro fecha), y solo 13 de las 85 lo ofrecen, pese a que 38 tienen columnas de fecha en su modelo. Para consultar por periodo —lo más habitual en un ERP: “facturas de enero”, “recibos vencidos este trimestre”— hay que traerse todo y filtrar en memoria, que es justo lo que hacen hoy los KPI de analytics con fetchAllPaginated.

Causa

No es una limitación de la API. APIModel::getWhereValues ya interpreta los sufijos de operador _gte / _lte y los combina con AND, y toApiQueryParams ya envuelve cualquier clave suelta como filter[clave]. Simplemente las tools no exponían ni reenviaban esos parámetros.

Solución

Nuevo metadata/dateRange.ts con una sola fuente de verdad, dateColumnsForTool(), que usan los dos lados:

  • el esquemaaddDateRangeParams() inyecta al arrancar <columna>_gte / <columna>_lte por cada columna date/datetime del modelo de la tool;
  • el reenvíodateRangeFilters() los propaga en el handler.

Que la regla sea la misma en ambos lados es deliberado: si cada uno aplicara su criterio podrían divergir y la tool anunciaría un filtro que el handler descarta en silencio, que es el modo de fallo que este diseño debe evitar.

Se usa el sufijo de operador como convención porque ya estaba en el código (descripcion_like, nombre_like), en vez de introducir un dialecto nuevo.

La inyección se limita a las tools del core: los módulos locales también registran sus modelos, pero sus handlers son genéricos y solo leen el parámetro filter, así que descartarían <columna>_gte sin avisar. Esos ya ofrecen rangos por su propio DSL.

Alcance

38 tools get_* reciben los pares de rango (138 parámetros nuevos en total). Se exporta resolveModelFromToolName de metadata/enrich.ts para reutilizar la resolución tool → modelo en lugar de duplicarla. No se toca el core de FacturaScripts.

Es aditivo: el parámetro fecha existente se mantiene y nada cambia para quien no use los nuevos.

Verificación

  • Test de contrato: recorre las 38 tools con el cliente HTTP interceptado y comprueba que cada handler propaga de verdad los parámetros hasta la petición. Si alguien añade una tool con columnas de fecha y olvida el reenvío, falla.
  • Contra una API real: un rango de un mes devuelve 169 facturas con 0 fuera de rango; un rango imposible devuelve 0; sin filtro, más registros que con él.

Nota: si se fusiona también el PR de parseo de fechas, ambos añaden la misma línea "test" a package.json; el conflicto es de una línea.

Las tools get_* solo permitían filtrar por fecha EXACTA (un único parámetro
`fecha`), y solo 13 de las 85 lo ofrecían, pese a que 38 tienen columnas de fecha
en su modelo. Para consultar por periodo había que traerse todo y filtrar en
memoria, que es justo lo que hacen hoy los KPI de analytics.

La API REST ya soportaba el rango: `APIModel::getWhereValues` interpreta los
sufijos `_gte`/`_lte` y los combina con AND, y `toApiQueryParams` ya envuelve
cualquier clave suelta como `filter[clave]`. Bastaba con exponer y reenviar los
parámetros; no hace falta tocar el core de FacturaScripts.

Añade `metadata/dateRange.ts` con UNA sola fuente de verdad (`dateColumnsForTool`)
que usan tanto la inyección en el inputSchema (`addDateRangeParams`, al arrancar)
como el reenvío en los handlers (`dateRangeFilters`). Si cada lado tuviera su
criterio podrían divergir y la tool anunciaría un filtro que el handler descarta
en silencio.

Cobertura: 38 tools get_* reciben `<columna>_gte` / `<columna>_lte` por cada
columna date/datetime de su modelo. Se usa el sufijo de operador como convención,
que ya estaba en el código (`descripcion_like`, `nombre_like`).

La inyección se limita a las tools del core: los módulos locales también registran
sus modelos, pero sus handlers son genéricos y solo leen el parámetro `filter`, así
que descartarían `<columna>_gte` sin avisar. Esos ya ofrecen rangos por su DSL.

Exporta `resolveModelFromToolName` de `metadata/enrich.ts` para reutilizar la
resolución tool -> modelo en lugar de duplicarla.

El test de contrato recorre las 38 tools con el cliente HTTP interceptado y
comprueba que cada handler propaga de verdad los parámetros hasta la petición, que
es el fallo que este diseño podría introducir.

Verificado contra una API real: un rango de un mes devuelve 169 facturas con 0
fuera de rango, y un rango imposible devuelve 0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant