Crear orden

Flujo de creación de una orden: desde el frontend hasta el microservicio de órdenes, con publicación de eventos y coordinación con inventario y pagos.

Por qué la creación de orden es un flujo complejo

Crear una orden no es simplemente guardar un registro en una base de datos. Es un flujo que involucra múltiples servicios, validaciones de negocio, reserva de inventario, inicio de pago y notificaciones. Es el ejemplo perfecto de cómo la comunicación sincrónica y asíncrona conviven en un mismo caso de uso.

El flujo completo

sequenceDiagram
    participant FE as Frontend
    participant GW as API Gateway
    participant BFF as BFF
    participant ORD as ms-orders
    participant DB as Orders DB
    participant EB as Event Bus
    participant INV as ms-inventory
    participant PAY as ms-payments
    participant NOT as ms-notifications

    FE->>GW: POST /orders
    GW->>GW: Auth, rate limiting
    GW->>BFF: Forward
    BFF->>ORD: Crear orden

    ORD->>ORD: Validar datos de la orden
    ORD->>DB: Guardar orden (estado: pending)
    DB-->>ORD: OK
    ORD->>EB: Publicar OrderPlaced

    ORD-->>BFF: Orden creada (id, estado)
    BFF-->>GW: Respuesta para UI
    GW-->>FE: 201 Created + orden

    Note over EB: Procesamiento asíncrono

    EB->>INV: OrderPlaced
    INV->>INV: Reservar stock
    INV->>EB: InventoryReserved

    EB->>PAY: OrderPlaced
    PAY->>PAY: Iniciar proceso de pago

    EB->>NOT: OrderPlaced
    NOT->>NOT: Enviar confirmación al usuario

Fase sincrónica: crear la orden

La primera parte del flujo es sincrónica. El usuario espera una confirmación de que su orden fue recibida.

Frontend

  1. El usuario revisa su carrito y confirma la compra
  2. El frontend envía los datos de la orden: items, cantidades, dirección de envío, método de pago
  3. Muestra un spinner mientras espera la confirmación
  4. Recibe la confirmación con el ID de la orden y muestra un mensaje de éxito

BFF

  1. Recibe los datos del frontend
  2. Puede enriquecer la petición (resolver IDs de productos, validar formato)
  3. Invoca al microservicio de órdenes
  4. Transforma la respuesta para el frontend

Microservicio de órdenes (ms-orders)

Este es el servicio que orquesta la creación:

  1. Valida los datos de la orden (items existen, cantidades válidas, dirección completa)
  2. Calcula el total
  3. Guarda la orden en su base de datos con estado pending
  4. Publica el evento OrderPlaced al Event Bus
  5. Devuelve la orden creada al BFF

Punto clave: la orden se guarda y el evento se publica en la misma operación (idealmente usando el Outbox Pattern para garantizar consistencia).

Fase asíncrona: coordinación entre servicios

Una vez publicado el evento OrderPlaced, varios servicios reaccionan de forma independiente.

Inventario (ms-inventory)

  1. Recibe el evento OrderPlaced
  2. Verifica que hay stock suficiente para cada item
  3. Reserva el stock (lo marca como comprometido)
  4. Publica InventoryReserved o InventoryInsufficient

Pagos (ms-payments)

  1. Recibe el evento OrderPlaced
  2. Inicia el proceso de cobro con el proveedor de pagos
  3. Publica PaymentCompleted o PaymentFailed

Notificaciones (ms-notifications)

  1. Recibe el evento OrderPlaced
  2. Envía un email de confirmación al usuario
  3. Puede enviar una notificación push si la app lo soporta

Coordinación y estados de la orden

La orden pasa por varios estados según los eventos que recibe:

stateDiagram-v2
    [*] --> Pending: OrderPlaced
    Pending --> Confirmed: InventoryReserved + PaymentCompleted
    Pending --> Cancelled: InventoryInsufficient
    Pending --> Cancelled: PaymentFailed
    Confirmed --> Shipped: ShipmentCreated
    Shipped --> Delivered: ShipmentDelivered
    Cancelled --> [*]
    Delivered --> [*]

El microservicio de órdenes escucha los eventos de inventario y pagos para actualizar el estado:

  • Si ambos son exitosos → confirmed
  • Si inventario falla → cancelled (y se revierte el pago si ya se cobró)
  • Si pago falla → cancelled (y se libera el inventario reservado)

El problema de la consistencia

En este flujo, no hay una transacción distribuida que garantice que todo ocurra de forma atómica. En su lugar, se usa consistencia eventual:

  1. La orden se crea en estado pending
  2. Los servicios procesan sus partes de forma independiente
  3. Los eventos de resultado actualizan el estado de la orden
  4. Si algo falla, se ejecutan compensaciones (liberar stock, revertir pago)

Este es el patrón Saga en acción: una secuencia de transacciones locales coordinadas por eventos.

Compensaciones

Cuando algo falla después de que otros servicios ya actuaron, se necesitan compensaciones:

FalloCompensación
Pago falla después de reservar inventarioPublicar PaymentFailed → inventario libera stock
Inventario insuficiente después de iniciar pagoPublicar InventoryInsufficient → pagos cancela el cobro
Timeout sin respuesta de inventarioOrden pasa a cancelled después de un tiempo límite

Idempotencia

Cada consumidor debe ser idempotente. Si el evento OrderPlaced se entrega dos veces:

  • Inventario no debe reservar stock dos veces
  • Pagos no debe cobrar dos veces
  • Notificaciones no debe enviar dos emails

La forma más común de lograr esto es guardar el ID del evento procesado y verificar antes de actuar.

Qué ve el usuario

Desde la perspectiva del usuario:

  1. Hace clic en “Confirmar compra”
  2. Ve un spinner por 1–2 segundos
  3. Ve “Orden #12345 recibida” con estado “Procesando”
  4. Recibe un email de confirmación
  5. Puede consultar el estado de la orden, que se actualiza conforme los servicios procesan

El usuario no necesita saber que detrás hay 4 servicios coordinándose. Solo ve un flujo limpio.

Resumen

La creación de una orden combina comunicación sincrónica (para dar una respuesta rápida al usuario) con comunicación asíncrona (para coordinar inventario, pagos y notificaciones). La consistencia se logra mediante eventos y compensaciones, no mediante transacciones distribuidas. Cada servicio es responsable de su parte y reacciona a los eventos de los demás.