Métricas — Periodos de tiempo y rendimiento (spec 006)¶
Gerencia pidió ver la efectividad por ciudad por periodos y que la vista cargue rápido con ~1 100 ciudades × 4 transportadoras y 926 k guías. Esta página resume el diseño. Estado al 2026-10-30: implementado en las ramas feature/metricas-entrega, pendiente de despliegue y de las mediciones antes/después.
Periodos¶
Cinco periodos fijos, contados hacia atrás desde el día de la corrida (hora de Bogotá) por la fecha del ObjectId _id de la guía en PedidosInter (el día en que se sincronizó), no por FechaCarga (decisión de Iker, 2026-10-30).
| Periodo | Id | Rango |
|---|---|---|
| Histórico | HISTORICO |
todo |
| Últimos 6 meses | MESES_6 |
hoy − 6 meses hasta hoy (meses móviles) |
| Últimos 3 meses | MESES_3 |
hoy − 3 meses hasta hoy |
| Último mes | DIAS_30 |
30 días móviles, hoy incluido |
| Última semana | DIAS_7 |
7 días móviles, hoy incluido |
Datos inmaduros en los periodos cortos
Las guías de los últimos días todavía no tienen estado final (entregada o devuelta). En 7 y 30 días el porcentaje puede cambiar y habrá ciudades con muestra insuficiente. La vista lo avisa y el mínimo de guías por defecto baja a 5 (semana) y 15 (mes); el resto usa el general (30). Se acepta por decisión de Iker.
Cómo se calcula¶
flowchart LR
P[(PedidosInter
índice por _id)] -->|5 tramos disjuntos por rango de _id| L[Lambda: corrida]
L -->|suma de tramos| R[(MetricasEntregaResumenPeriodo
1 documento por periodo)]
L -->|agregación mensual de siempre| M[(MetricasEntregaCiudadMes)]
F[Entregas: selector de periodo] -->|GET ?periodo=X| G[Lambda GET] -->|1 documento| R
- Cada guía se lee una sola vez: los 5 tramos (7 días, de 7 a 30 días, de 30 días a 3 meses, de 3 a 6 meses, más viejo) no se cruzan, y cada periodo es la suma de los tramos más nuevos hasta el suyo.
- Los tramos se consultan antes de escribir: si uno falla, la corrida queda
FALLIDAy no toca nada. - La colección mensual y la auditoría siguen por
FechaCarga(están validadas contra la base). El histórico por periodos puede diferir levemente porque incluye guías sinFechaCargaválida. - El
$matchpor_idno necesita índice nuevo. Un índice deFechaCarga(M-124) ya no hace falta.
API¶
GET /metricas/entrega-ciudad?periodo=<id> (por defecto HISTORICO; inválido, 400 PERIODO_INVALIDO). Lee un documento. Responde compacto (camelCase, sin nulls, solo entregas y devoluciones por celda; el front calcula finales y porcentaje) con ETag y Cache-Control: private, max-age=60; con If-None-Match igual responde 304 sin leer el documento. desde/hasta se conserva por compatibilidad. Antes de la primera corrida posterior al despliegue, el histórico sale de los meses y los demás periodos responden sinDatos.
Ajuste visual por periodo¶
El AjusteVisual de la spec 005 pasa a ser el ajuste general; cada periodo puede tener el suyo en AjustePorPeriodo (con sus excepciones por ciudad). En la pestaña Ajuste del panel de administración:
- Se elige el periodo; un periodo con ajuste propio se marca con ●. Editar un periodo que usaba el general le crea su propio ajuste.
- Aplicar a todos los periodos: el ajuste del periodo editado pasa a ser el general y se borran los ajustes propios de los demás (pide confirmación).
- Restablecer este periodo: vuelve a usar el general.
- Mínimo de guías por periodo. El botón anterior "Restablecer" se llama ahora Descartar cambios (recarga lo guardado).
El backend solo guarda y entrega los parámetros; el cálculo del ajuste sigue siendo del front y la base guarda siempre el real.
Rendimiento¶
| Qué | Antes | Ahora |
|---|---|---|
| Lectura por GET | todos los documentos mensuales del rango (≈ 25 000 en histórico), sumados en cada petición | 1 documento ya armado por la corrida |
| Payload | PascalCase, con Finales, Porcentaje y nulls por celda |
compacto, sin campos derivables |
| Repetición | cada visita pedía todo | ETag + 304, caché del navegador 60 s y caché en memoria por periodo 5 min; los demás periodos se precargan |
| Compresión | ninguna | gzip del gateway (ver abajo) |
Payload medido con datos reales de prod (1 189 ciudades, 2 270 celdas): antes 281 KB; después 212 KB (compacto) y 23,5 KB con gzip. Tiempo del GET antes/después: pendiente; se toma con tools/medir-get-entregas.ps1 en PreProd y prod y la tabla se completa al desplegar.
Compresión (estándar)¶
Ninguna lambda comprime respuestas; el estándar es el gzip nativo de API Gateway REST (minimum_compression_size), una propiedad del API, no de las rutas. En PreProd la fija Terraform (environments/preprod/datos, 1024 bytes). En producción el REST 7elgyten88 no es de Terraform: se activa por consola (API → Configuración → Codificación de contenido → 1024 bytes → volver a desplegar el stage). El navegador ya envía Accept-Encoding: gzip y descomprime solo.
Operación¶
- El Scheduler del domingo 8:00 refresca todos los periodos (y los meses). Sigue
DISABLEDen prod hasta que gerencia revise. - Desde el panel (pestaña Corridas) se puede lanzar una corrida de un solo periodo a elección, de una en una: consulta solo sus tramos y escribe solo su documento (la semana tarda ≈ 2 s; el histórico, ≈ 1 min). Los demás periodos quedan como estaban.
- Costo medido en prod (solo lectura, 2026-10-30): los 5 tramos tardan 2,2 / 3,2 / 7,8 / 16,7 y 28,3 s (≈ 53 s); sumados a la mensual (1 min 53 s) la corrida del domingo queda en ≈ 3 min (estimación; se confirma con la primera corrida real).
- Verificado en prod: la fecha del ObjectId coincide con el día de carga de la guía (1 500 guías, hora de Bogotá, mismo día en todas).
Spec completa: specs/006_periodos/spec.md. Contrato y datos: docs/architecture/contratos/ y datos/ (metricas-entrega-ciudad).