Skip to content

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:

  1. 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 tipo metadata (la que trae receipt_url + tracking_key) va al topic shinkansen-payout-metadata-prod.
  2. Topic shinkansen-payout-metadata-prod tiene dos consumidores (fan-out):
    • Rama warehouse: suscripción shinkansen-payout-metadata-prod-sub → Dataflow shinkansen-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-cep de este servicio.
  3. public.payment_orders (Postgres del producto) provee el mapeo tracking_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)

  1. Recibe el push de Pub/Sub: un POST con message.data en base64; lo decodifica y extrae receipt_url y tracking_key de payment_operator_metadata.
  2. Valida: si falta receipt_url o tracking_key, responde 200 con skipped: true (no es error).
  3. Resuelve el loan: SELECT loan_management_id FROM public.payment_orders WHERE tracking_key = %s. Si no hay match, omite (200, skipped).
  4. Consulta LoanPro: obtiene el loan por displayId = loan_management_id (OData, expandiendo LoanSettings/CustomFieldValues) para sacar id y settingsId.
  5. Actualiza: PUT del custom field de receipt URL del loan con el receipt_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


Ú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.