Veredicto auditoría 2026-06-13: Aprobado con observaciones
Observaciones operativas (auditoría 2026-06-13): monitorear manifest_webhook_refetch_failed (alerta GCP desplegada); eventos Betterez no usados (manifest.dispatch.reporting.created) clasificados como observados.
Flujo de ingesta
manifests.*, manifestStatus.updated
manifest_legs
fact_manifest_leg
Dos vías complementarias (no duplicadas innecesariamente):
- Webhooks — casi tiempo real desde ~may-2026
- Job andesmar-manifests-sync — cada 30 min, outlook + detalle (red de seguridad)
Qué dice Betterez
La documentación oficial (engineering.betterez.com/webhooks/manifests) lista eventos como manifests.created, manifests.updated, manifestStatus.updated, etc.
legs[].tickets vacío. Por eso re-fetch del manifiesto completo es la práctica correcta — no un workaround local.
Eventos reconocidos vs no usados
| Evento | Acción GCP |
|---|---|
| manifests.created / updated / edited | Re-fetch + persist_manifest_detail |
| manifest.tickets.first.added | Re-fetch completo |
| manifestStatus.updated | Update status; re-fetch si no hay filas OLTP |
| manifests.tripClosed / emptied | Update status/tags |
| manifest.dispatch.reporting.created | Observado, no transformado (monitorear) |
Tablas BI relacionadas
| Tabla | Grano | Para qué |
|---|---|---|
fact_ticket / fact_ticket_mstr | 1 boleto | Match ticket↔manifiesto por ticket_number; flags has_* |
dim_manifest | 1 manifiesto | peak_load, peak_load_factor del servicio |
fact_manifest_leg | 1 parada del manifiesto | pax_on, pax_off, load por estación |
bridge_manifest_tag | N:M ticket↔tag | Etiquetas nacional/internacional/etc. |
Ocupación: qué tabla usar
| Pregunta de negocio | Tabla | Grano |
|---|---|---|
| Ocupación por manifiesto/servicio (pico del bus) | dim_manifest | 1 viaje |
| Ocupación por parada (suben/bajan en cada estación) | fact_manifest_leg | 1 parada |
| Ventas / revenue de boletos | fact_ticket | 1 boleto |
pax_on, pax_off, load, load_factor,
station, to_station, manifest_date, schedule_display_name
manifest_date (fecha del viaje), no confundir con sale_date (fecha de venta).
Dos incidentes distintos (abr–may 2026)
Gap A — Ingesta OLTP (webhooks ausentes)
Hasta ~2026-05-21 Betterez no enviaba webhooks de manifiesto de forma confiable; el polling solo cubría outlook corto (hoy → hoy+5). Resultado: tickets vendidos sin fila en manifest_entries.
- Huérfanos globales documentados: ~1.163 tickets (320 abr + 747 may)
- 282 de mayo: venta anticipada con viaje jul–nov (esperable, no bug de ingesta)
- Remediación: backfill histórico + webhooks activos +
betterez-manifests-safety-net
Fuente: docs/comunicaciones/2026-06-06_gap_ingesta_manifiestos_analisis.md
Gap B — ETL BI paso 7b (fact_manifest_leg)
Entre ~28-abr y el redeploy del paso 7b, fact_manifest_leg quedó congelada en max(manifest_date) = 2026-05-03 mientras public.manifest_legs seguía actualizándose.
Remediación: backfill + incremental 7b activo. Fuente: GUIA_FACT_MANIFEST_LEG_BI_REBUILD.md § Incidente 2026-06-02.
Redes de seguridad (mantener activas)
- andesmar-manifests-sync — polling outlook cada 30 min
- betterez-manifests-safety-net — tickets huérfanos travel_date D-3..D-1
- manifest-leg-guard — detecta drift fact_manifest_leg vs OLTP
- ETL incremental paso 7b — delta por manifest_legs.updated_at
Uso en MicroStrategy
Joins sugeridos
fact_manifest_leg.manifest_id → dim_manifest.manifest_id fact_manifest_leg.schedule_id → dim_schedule.schedule_id (opcional) fact_ticket.manifest_id → dim_manifest.manifest_id
Cobertura de manifiesto en tickets
Medición 2026-06-10 (post-oleada 1): tickets pagados con manifest_id en BI — cobertura alta; no_match bajó de 2.568 → 313 tras backfill del 09-06.
Ventana reciente (auditoría 2026-06-13): en lookback 14 días, ~11 tickets pagados sin manifiesto vs ~39.732 con match — residual operativo (lag sync/ETL o viaje aún no asignado).
La cifra “~93%” de la auditoría del 05-06 quedó superada; no usar en reuniones sin fecha de medición.
Para etiquetas (nacional, Cuyanita, etc.) ver presentación dedicada: Etiquetas de manifiesto.