Shinkansen · LoanPro CEP (comprobante de pago → LoanPro)
Cuando Shinkansen confirma un payout, este proceso toma el comprobante de pago (
receipt_url) y lo escribe en el loan correspondiente de LoanPro, para que el comprobante quede visible en la aplicación. Es un proceso de escritura de vuelta a la app, no de carga al warehouse.
¿Llegaste hasta acá desde…?
| Si ves… | Eso sale de… | La lógica está en… |
|---|---|---|
| El comprobante de pago (receipt URL) en un loan de LoanPro | Custom field del loan, escrito por este servicio | shinkansen-loandpro-cep-process → shinkansen_loandpro_cep_process.py |
La tabla shinkansen.shinkansen_metadata en BigQuery |
Otro consumidor del mismo topic (Dataflow) | ver [Shinkansen · Payout metadata] (mismo origen, rama warehouse) |
tracking_key que no resuelve a un loan |
public.payment_orders (Postgres del producto) |
El payout no tenía loan_management_id mapeado |
Resumen
| Campo | Valor |
|---|---|
| Origen | Webhook de Shinkansen, notificación metadata de un payout |
| Patrón | Event-driven con escritura de vuelta a la app (no carga BigQuery) |
| Disparo | Push de Pub/Sub (topic shinkansen-payout-metadata-prod) al endpoint /register-cep |
| Salida | Custom field de receipt URL en el loan de LoanPro |
| Depende de | public.payment_orders (Postgres) y API LoanPro |
| Criticidad | 🟡 Media (operacional: que el comprobante aparezca en LoanPro) |
| Dueño | Martin (data eng) |
Diagrama de linaje
graph LR
SHK[["📨 Shinkansen<br/>webhook payout"]]
CR["Cloud Run<br/>webhook-shinkansen-inline-prod<br/><i>clasifica por tipo</i>"]
TOP(["Pub/Sub<br/>shinkansen-payout-metadata-prod"])
subgraph warehouse["Rama warehouse (otro proceso)"]
DF["Dataflow<br/>shinkansen-metadata-webhook-prod"]
BQ[("solvento-data-prod<br/>shinkansen.shinkansen_metadata")]
end
subgraph cep["Este proceso · writeback a la app"]
SVC["Cloud Run<br/>shinkansen-loanpro-cep-process<br/>POST /register-cep"]
PG[("PostgreSQL producto<br/>public.payment_orders<br/><i>tracking_key → loan_management_id</i>")]
LP["🖥️ LoanPro API<br/>custom field = receipt_url"]
end
SHK -->|HTTP| CR --> TOP
TOP -->|"sub warehouse"| DF --> BQ
TOP -->|"sub push /register-cep"| SVC
SVC -->|"1· busca loan por tracking_key"| PG
SVC -->|"2· PUT receipt_url en el loan"| LP
classDef src fill:#fde68a,stroke:#b45309,color:#000;
classDef store fill:#bfdbfe,stroke:#1e40af,color:#000;
classDef app fill:#dcfce7,stroke:#15803d,color:#000;
class SHK src;
class BQ,PG store;
class LP app;
Procesos subyacentes
Este proceso no funciona solo; cuelga de la cadena de ingesta de Shinkansen:
webhook-shinkansen-inline-prod(webhook_shinkansen) recibe el webhook de Shinkansen y lo clasifica por tipo (payout_metadata,payout_results, …), publicando cada uno en su topic. La notificación de tipometadata(la que traereceipt_url+tracking_key) va al topicshinkansen-payout-metadata-prod.- Topic
shinkansen-payout-metadata-prodtiene dos consumidores (fan-out):- Rama warehouse: suscripción
shinkansen-payout-metadata-prod-sub→ Dataflowshinkansen-metadata-webhook-prod-…→solvento-data-prod.shinkansen.shinkansen_metadata(esto es otro proceso, el de analítica). - Esta rama: una suscripción push que entrega cada mensaje al endpoint
/register-cepde este servicio.
- Rama warehouse: suscripción
public.payment_orders(Postgres del producto) provee el mapeotracking_key → loan_management_id; lo escribe el producto cuando crea el payout. Sin esa fila, el comprobante no se puede asociar a un loan.
Paso a paso (/register-cep)
- Recibe el push de Pub/Sub: un POST con
message.dataen base64; lo decodifica y extraereceipt_urlytracking_keydepayment_operator_metadata. - Valida: si falta
receipt_urlotracking_key, responde 200 conskipped: true(no es error). - Resuelve el loan:
SELECT loan_management_id FROM public.payment_orders WHERE tracking_key = %s. Si no hay match, omite (200, skipped). - Consulta LoanPro: obtiene el loan por
displayId = loan_management_id(OData, expandiendoLoanSettings/CustomFieldValues) para sacaridysettingsId. - Actualiza:
PUTdel custom field de receipt URL del loan con elreceipt_url. El id del campo es configurable (LOAN_RECEIPT_CUSTOM_FIELD_ID; default 287 en código, el README menciona 236 — conviene confirmar el valor productivo en Cloud Run).
Nota: este flujo no pasa por dbt ni por BigQuery. La "lógica" vive en el propio servicio (
shinkansen_loandpro_cep_process.py); su resultado se consume en la aplicación (LoanPro), no en analytics.
Si falla 🛠️
Impacto: los comprobantes de pago no se reflejan en LoanPro (los loans quedan sin el receipt URL). No afecta al warehouse ni a la rama de shinkansen_metadata. Pub/Sub reintenta los push fallidos, así que fallos transitorios se recuperan solos.
| Síntoma | Dónde mirar | Acción |
|---|---|---|
| El comprobante no aparece en el loan | Logs Cloud Run shinkansen-loanpro-cep-process (en /register-cep) |
Ver si fue skipped (faltaba dato o no hubo match en payment_orders) o un error real |
| Muchos "skipped" por sin match | public.payment_orders: ¿existe la fila para ese tracking_key? |
El payout no quedó mapeado a un loan; revisar del lado del producto |
| Error al actualizar LoanPro | Respuesta de la API LoanPro en logs (auth, custom field id) | Verificar LOANPRO_AUTHORIZATION_TOKEN, LOANPRO_INSTANCE_ID y el LOAN_RECEIPT_CUSTOM_FIELD_ID correcto |
| Error de conexión a Postgres | Variables POSTGRES_* y salud del Postgres del producto |
Revisar credenciales/conectividad |
Escalación: resto → Martin (mapeo de payouts / producto, coordinar con el equipo dueño de payment_orders).
Enlaces
- 📦 Servicio:
shinkansen-loandpro-cep-process· webhook origen:webhook_shinkansen - 📊 Estado en vivo: dashboard "Data Processes" (Cloud Monitoring)
Última actualización: 2026-06-21 · Si cambia el flujo, el custom field o el esquema del webhook, actualizar esta ficha en el mismo MR.