Order Fulfillment Workflow

Business
10 nodes · 10 edgesbusiness
ex-order-fulfillment.osop.yaml
# Order Fulfillment Workflow
# Order placement through inventory check, picking, packing, shipping, and delivery confirmation
osop_version: "2.0"
id: order-fulfillment
name: Order Fulfillment Workflow

nodes:
  - id: receive_order
    type: api
    purpose: Accept and validate new customer order from storefront or API
    runtime:
      endpoint: /api/v1/orders
      method: POST
      url: https://commerce.internal
    outputs: [order_id, customer_id, line_items, shipping_address, priority]
    timeout_sec: 10

  - id: check_inventory
    type: db
    purpose: Check real-time inventory availability for all order line items
    runtime:
      engine: postgresql
      connection: postgresql://warehouse:5432/inventory
    inputs: [line_items]
    outputs: [available_items, backorder_items, fulfillment_warehouse]
    timeout_sec: 5
    explain: |
      Queries inventory across all warehouses. Selects optimal fulfillment
      location based on stock availability and shipping distance.

  - id: reserve_stock
    type: db
    purpose: Place inventory hold to prevent overselling during fulfillment
    runtime:
      engine: postgresql
      connection: postgresql://warehouse:5432/inventory
    inputs: [order_id, available_items, fulfillment_warehouse]
    outputs: [reservation_id, reserved_until]
    timeout_sec: 5

  - id: process_payment
    type: api
    purpose: Capture payment authorization for the order total
    runtime:
      endpoint: /v1/payment_intents/capture
      method: POST
      url: https://api.stripe.com
    inputs: [order_id, customer_id]
    outputs: [payment_id, payment_status, charged_amount]
    security:
      auth: bearer_token
      secret_ref: STRIPE_SECRET_KEY
    timeout_sec: 30
    retry_policy:
      max_retries: 3
      backoff_sec: 5

  - id: generate_pick_list
    type: cli
    purpose: Generate optimized pick list with warehouse zone routing
    runtime:
      command: |
        python generate_pick_list.py \
          --order-id ${order_id} \
          --warehouse ${fulfillment_warehouse} \
          --optimize-route
    inputs: [order_id, available_items, fulfillment_warehouse]
    outputs: [pick_list_id, zone_sequence, estimated_pick_time]
    timeout_sec: 15

  - id: pick_items
    type: human
    purpose: Warehouse associate picks items from shelves following optimized route
    role: warehouse_associate
    inputs: [pick_list_id, zone_sequence]
    outputs: [picked_items, pick_discrepancies]
    timeout_sec: 3600

  - id: pack_shipment
    type: human
    purpose: Packing station associate packs items, applies shipping label, and scans
    role: packing_associate
    inputs: [picked_items, shipping_address, order_id]
    outputs: [package_id, weight_kg, dimensions, packing_photo]
    timeout_sec: 1800

  - id: ship_order
    type: api
    purpose: Create shipping label and schedule carrier pickup
    runtime:
      endpoint: /api/v1/shipments
      method: POST
      url: https://shipping-api.internal
    inputs: [package_id, shipping_address, weight_kg, dimensions, priority]
    outputs: [tracking_number, carrier, estimated_delivery, label_url]
    security:
      auth: bearer_token
      secret_ref: SHIPPING_API_KEY
    timeout_sec: 30

  - id: notify_customer
    type: api
    purpose: Send shipment confirmation with tracking link to customer
    runtime:
      endpoint: /api/v1/notifications/send
      method: POST
      url: https://notification-service.internal
    inputs: [order_id, customer_id, tracking_number, estimated_delivery]
    outputs: [notification_id]

  - id: confirm_delivery
    type: api
    purpose: Monitor carrier tracking and confirm successful delivery
    runtime:
      endpoint: /api/v1/tracking/${tracking_number}/status
      method: GET
      url: https://shipping-api.internal
    inputs: [tracking_number]
    outputs: [delivery_status, delivery_timestamp, proof_of_delivery]
    timeout_sec: 604800
    retry_policy:
      max_retries: 168
      backoff_sec: 3600
    explain: "Polls carrier every hour for up to 7 days until delivery confirmed."

edges:
  - from: receive_order
    to: check_inventory
    mode: sequential

  - from: check_inventory
    to: reserve_stock
    mode: conditional
    condition: "backorder_items.length == 0"

  - from: reserve_stock
    to: process_payment
    mode: parallel

  - from: reserve_stock
    to: generate_pick_list
    mode: parallel

  - from: process_payment
    to: pick_items
    mode: sequential

  - from: generate_pick_list
    to: pick_items
    mode: sequential

  - from: pick_items
    to: pack_shipment
    mode: sequential

  - from: pack_shipment
    to: ship_order
    mode: sequential

  - from: ship_order
    to: notify_customer
    mode: sequential

  - from: notify_customer
    to: confirm_delivery
    mode: sequential