Syntage · Invoices (facturación CFDI)
De punta a punta: del webhook de Syntage a su uso en análisis y producto. Incluye dónde vive la lógica de cada transformación.
Camino de terminal_client (dbt-etls) ELIMINADO el 2026-09-11
El cálculo de terminal en dbt-etls (models/terminal_client/, tabla …terminal.client_dbt) ya no existe: se borró el 2026-09-11 junto con el export a Supabase (ver Apagado Terminal → Supabase). El producto de pricing vivo es Terminal v3, que lee de dbt-analytics en solvento-risk-analytics-prod, no de aquí. El consumo vivo y confiable de este proceso es consistency_jobs.invoices (abajo). La vía exacta de la facturación de cara al cliente conviene confirmarla.
¿Llegaste hasta acá desde…?
Usa esta tabla para entrar en sentido inverso (lo que ves → de dónde sale):
| Si ves… | Eso sale de… | La lógica está en… |
|---|---|---|
| Montos/totales canonizados en análisis o Metabase | solvento-adv-analytics-prod.consistency_jobs.invoices |
dbt-etls → models/advanced_analytics/invoices.sql |
| Tarifas de lanes / pricing de flete | solvento-risk-analytics-prod.terminal_v3.datarelease_* |
Terminal v3 (vía dbt-analytics) |
❌ terminal.client_dbt (dbt-etls) |
Eliminado el 2026-09-11 (dataset dropeado) | Ya no existe — ver Apagado Terminal → Supabase |
| Una factura "cruda" / sin deduplicar | solvento-data-prod.syntage.invoices (RAW) |
Ingesta (sin lógica de negocio); ver "Paso a paso" |
Resumen
| Campo | Valor |
|---|---|
| Origen | Webhook de Syntage (evento invoice) |
| Patrón | Event-driven (Cloud Run → Pub/Sub → Dataflow) + transformación dbt |
| Tabla RAW | solvento-data-prod.syntage.invoices |
| Tabla transformada (viva) | solvento-adv-analytics-prod.consistency_jobs.invoices (vía dbt-etls) |
terminal.client_dbt |
❌ Eliminado el 2026-09-11 junto con el dataset (ver Apagado Terminal → Supabase) |
| Frecuencia | Ingesta streaming · transformación dbt diaria (madrugada) |
| Criticidad | 🔴 Alta — flujo más crítico del ecosistema |
| Dueño | Martin (data eng) |
Diagrama de linaje (ingesta → lógica → consumo)
graph LR
SYN[["📨 Syntage<br/>webhook invoice"]]
subgraph ing["1 · Ingesta (sin lógica de negocio)"]
CR["Cloud Run<br/>webhook-syntage-inline-prod"]
TOP(["Pub/Sub<br/>invoices-webhook-prod"])
DF["Dataflow<br/>invoices-webhook-prod"]
RAW[("solvento-data-prod<br/>syntage.invoices · RAW")]
end
subgraph logica["2 · Lógica de negocio · dbt-etls"]
M1["invoices.sql<br/><i>dedup · redondeo · nombres · FX</i>"]
M2["invoices_360.sql<br/><i>une items + carta porte</i>"]
M3["❌ final_invoice.sql<br/><i>ELIMINADO 2026-09-11</i>"]
M4["❌ client_dbt.sql<br/><i>ELIMINADO 2026-09-11</i>"]
GOLD[("❌ terminal.client_dbt<br/>dataset dropeado")]
end
subgraph cons["3 · Consumo"]
MB["Metabase / Riesgo<br/>(consumo vivo)"]
end
SYN -->|HTTP| CR --> TOP --> DF --> RAW
RAW --> M1 --> M2
RAW -.->|deprecado| M3 -.-> M4 -.-> GOLD
M1 --> MB
M2 -.-> M4
classDef src fill:#fde68a,stroke:#b45309,color:#000;
classDef store fill:#bfdbfe,stroke:#1e40af,color:#000;
classDef logic fill:#dcfce7,stroke:#15803d,color:#000;
class SYN src;
class RAW,GOLD store;
class M1,M2,M3,M4 logic;
Paso a paso
1 · Ingesta (mueve datos, no aplica lógica de negocio)
- Syntage emite un webhook por cada factura nueva o actualizada.
- Cloud Run
webhook-syntage-inline-prod(webhook_syntage) enruta a Pub/Sub según el tipo de evento. Enruta todo Syntage, por eso es tan crítico. - Pub/Sub desacopla: topic
invoices-webhook-prod(factura completa),invoices-api-topic(requiere detalle vía API →invoices_items),invoices-dlq(fallidos). - Dataflow
invoices-webhook-prod-…(template-invoices) escribe el dato crudo ensolvento-data-prod.syntage.invoices. Ojo: la RAW puede tener duplicados; aún no hay lógica de negocio.
2 · Lógica de negocio (dbt — aquí están las reglas) → repo dbt-etls
invoices.sql(models/advanced_analytics/invoices.sql) →solvento-adv-analytics-prod.consistency_jobs.invoices. Deduplica porid, redondea montos (total,subtotal,tax, etc.), canoniza nombres de emisor/receptor (issuer_names,receiver_names) y convierte moneda conanaliticas.exchange_rates.invoices_360.sqluneinvoices+invoices_items+cp_data+items_partition_map(vista 360 de la factura).- ❌
final_invoice.sqlyclient_dbt.sql(models/terminal_client/) — eliminados el 2026-09-11 junto con el dataset…terminal. Combinaban la factura con carta porte/mercancías y producían la tabla GOLD del terminal de cliente. Se dejan nombrados solo por el ruido histórico: ya no existen (ver Apagado Terminal → Supabase).
3 · Consumo
- ❌
terminal.client_dbten dbt-etls — eliminado el 2026-09-11. La vía actual de la facturación de cara al cliente conviene confirmarla. - Metabase / modelos de riesgo leen de
consistency_jobs.invoices.
Si falla 🛠️
Impacto: si cae webhook-syntage-inline-prod se afecta todo Syntage. Mitigante: Syntage reintenta los webhooks; recuperar el servicio suele bastar.
| Síntoma | Dónde mirar | Acción |
|---|---|---|
| No llegan facturas nuevas | Logs Cloud Run webhook-syntage-inline-prod |
Si fue un deploy → rollback; si es saturación → subir instancias/memoria (Terraform gcp/terraform-gcp-infrastructure) |
| Llega a RAW pero el frontend no actualiza | Run diario de dbt Cloud (proyecto ingeniería) | Re-ejecutar el job; revisar qué modelo falló (invoices, invoices_360) |
| Llega al topic pero la RAW no avanza | Dataflow: watermark del job; backlog de la suscripción | Transitorios se recuperan solos; relanzar consumiendo la misma suscripción. Si hay duda, escalar |
| Montos/nombres "raros" en el frontend | Lógica en dbt-etls (invoices.sql, invoices_360.sql) |
Revisar la transformación en el repo, no la ingesta |
Escalación: lógica SQL / Metabase → Diego · Airbyte → Gero · resto → Martin.
Enlaces
- 📊 Estado en vivo: dashboard "Data Processes" (Cloud Monitoring)
- 📦 Ingesta:
webhook_syntage·template-invoices - 🧮 Lógica:
dbt-etls— modelos enmodels/advanced_analytics/(models/terminal_client/fue eliminado el 2026-09-11)
Última actualización: 2026-06-21 · Si cambia el flujo o un modelo dbt, actualizar esta ficha en el mismo MR.