Organization · Campos Stripe (v1.67.0)
Resumen
Extensión de Organization (migración 0032) con 3 campos para integración de Stripe. Caché mínima del estado de suscripción; la verdad vive en Stripe. La migración 0036 (v1.163.0) añade un 4º campo para proteger ese caché de eventos que llegan fuera de orden.
Campos
| Campo | Tipo | Default | Descripción |
|---|---|---|---|
stripe_customer_id | CharField(255) | "" | ID del customer en Stripe (cus_...). Vacío si nunca hubo checkout. |
subscription_status | CharField(20, choices) | "none" | Estado de suscripción: none, trialing, active, past_due, canceled |
current_period_end | DateTimeField | null | Fecha/hora de renovación o vencimiento de la suscripción actual. |
last_subscription_event_at | DateTimeField | null | created (epoch Stripe) del último customer.subscription.* aplicado. Añadido en la migración 0036 (mega-auditoría B-62) para descartar eventos que lleguen con fecha anterior a la ya aplicada. |
Poblado por
- Webhooks:
apply_event()escribe al recibir eventos (checkout.session.completed,customer.subscription.{created,updated,deleted},invoice.payment_failed) - Reconciliación diaria:
reconcile_stripe_subscriptions()(06:40 UTC)
Orden de eventos (B-62, v1.163.0)
Stripe no garantiza que los eventos lleguen en el orden en que ocurrieron — un reintento de un updated viejo podía llegar después de un deleted y dejar la suscripción activa otra vez. Desde v1.163.0, _apply_subscription_event() (billing/services.py) compara el created del evento contra last_subscription_event_at bajo un select_for_update() de la fila: si el evento es más viejo que el último aplicado, se descarta (skipped, responde 200 — Stripe no reintenta lo ya entregado). El bloqueo de la fila lleva un tope de 3 s (SET LOCAL lock_timeout); si salta, el webhook responde 500 para que Stripe reintente en vez de perder el evento con un 200.
Detalle completo: [[feature—billing—stripe-pr2-webhooks]].
Agnóstico a modelo de precios
Estos campos NO asumen cómo se vende (por rack, equipo, sitio, etc.). Valen igual con cualquier modelo. La decisión de precios aún está abierta (conv. MSP sept., anotado en task #136).
Nota de producto
PR-2 NO toca is_active ni plan. Desactivar org por impago o cambiar plan son políticas de negocio (PR-3+).
Véase también
- [[entity—billing—endpoint—stripe-webhook]]
- [[entity—billing—service—event-applier]]
- [[feature—billing—stripe-pr2-webhooks]]