> ## Documentation Index
> Fetch the complete documentation index at: https://upstash.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# E-commerce Order Fulfillment

## Introduction

This example demonstrates an automated e-commerce order fulfillment process using Upstash Workflow. The workflow takes an order, verifies the stock, processes the payment, and handles order dispatch and customer notifications.

## Use Case

Our workflow will:

1. Receive an order request
2. Verify the availability of the items in stock
3. Process the payment
4. Initiate the dispatch of the order
5. Send confirmation and delivery notifications to the customer

## Code Example

<CodeGroup>
  ```typescript api/workflow/route.ts theme={"system"}
  import { serve } from "@upstash/workflow/nextjs"
  import {
    createOrderId,
    checkStockAvailability,
    processPayment,
    dispatchOrder,
    sendOrderConfirmation,
    sendDispatchNotification,
  } from "./utils"

  type OrderPayload = {
    userId: string
    items: { productId: string, quantity: number }[]
  }

  export const { POST } = serve<OrderPayload>(async (context) => {
    const { userId, items } = context.requestPayload;

    // Step 1: Create Order Id
    const orderId = await context.run("create-order-id", async () => {
      return await createOrderId(userId);
    });

    // Step 2: Verify stock availability
    const stockAvailable = await context.run("check-stock", async () => {
      return await checkStockAvailability(items);
    });

    if (!stockAvailable) {
      console.warn("Some items are out of stock");
      return;
    };

    // Step 3: Process payment
    await context.run("process-payment", async () => {
      return await processPayment(orderId)
    })

    // Step 4: Dispatch the order
    await context.run("dispatch-order", async () => {
      return await dispatchOrder(orderId, items)
    })

    // Step 5: Send order confirmation email
    await context.run("send-confirmation", async () => {
      return await sendOrderConfirmation(userId, orderId)
    })

    // Step 6: Send dispatch notification
    await context.run("send-dispatch-notification", async () => {
      return await sendDispatchNotification(userId, orderId)
    })
  })
  ```

  ```python main.py theme={"system"}
  from fastapi import FastAPI
  from typing import List, TypedDict
  from upstash_workflow.fastapi import Serve
  from upstash_workflow import AsyncWorkflowContext
  from utils import (
      create_order_id,
      check_stock_availability,
      process_payment,
      dispatch_order,
      send_order_confirmation,
      send_dispatch_notification,
  )

  app = FastAPI()
  serve = Serve(app)


  class OrderItem(TypedDict):
      product_id: str
      quantity: int


  class OrderPayload(TypedDict):
      user_id: str
      items: List[OrderItem]


  @serve.post("/order-fulfillment")
  async def order_fulfillment(context: AsyncWorkflowContext[OrderPayload]) -> None:
      # Get the order payload from the request
      payload = context.request_payload
      user_id = payload["user_id"]
      items = payload["items"]

      # Step 1: Create Order Id
      async def _create_order_id():
          return await create_order_id(user_id)

      order_id: str = await context.run("create-order-id", _create_order_id)

      # Step 2: Verify stock availability
      async def _check_stock():
          return await check_stock_availability(items)

      stock_available: bool = await context.run("check-stock", _check_stock)

      if not stock_available:
          print("Some items are out of stock")
          return

      # Step 3: Process payment
      async def _process_payment():
          return await process_payment(order_id)

      await context.run("process-payment", _process_payment)

      # Step 4: Dispatch the order
      async def _dispatch_order():
          return await dispatch_order(order_id, items)

      await context.run("dispatch-order", _dispatch_order)

      # Step 5: Send order confirmation email
      async def _send_confirmation():
          return await send_order_confirmation(user_id, order_id)

      await context.run("send-confirmation", _send_confirmation)

      # Step 6: Send dispatch notification
      async def _send_dispatch_notification():
          return await send_dispatch_notification(user_id, order_id)

      await context.run("send-dispatch-notification", _send_dispatch_notification)

  ```
</CodeGroup>

## Code Breakdown

### 1. Verifying Stock Availability

We start by creating an order id and verifying if the items in the order are available in stock. If not, we throw an error to halt the process:

<CodeGroup>
  ```typescript api/workflow/route.ts theme={"system"}
  const orderId = await context.run("create-order-id", async () => {
    return await createOrderId(userId);
  });

  const stockAvailable = await context.run("check-stock", async () => {
    return await checkStockAvailability(items)
  })

  if (!stockAvailable) {
    console.warn("Some items are out of stock")
    return;
  }
  ```

  ```python main.py theme={"system"}
  async def _create_order_id():
      return await create_order_id(user_id)

  order_id: str = await context.run("create-order-id", _create_order_id)

  async def _check_stock():
      return await check_stock_availability(items)

  stock_available: bool = await context.run("check-stock", _check_stock)

  if not stock_available:
      print("Some items are out of stock")
      return

  ```
</CodeGroup>

### 2. Processing Payment

Once the stock is verified, the workflow processes the payment for the order:

<CodeGroup>
  ```typescript api/workflow/route.ts theme={"system"}
  await context.run("process-payment", async () => {
    return await processPayment(orderId)
  })
  ```

  ```python main.py theme={"system"}
  async def _process_payment():
      return await process_payment(order_id)

  await context.run("process-payment", _process_payment)

  ```
</CodeGroup>

### 3. Dispatching the Order

After payment confirmation, we dispatch the order for delivery:

<CodeGroup>
  ```typescript api/workflow/route.ts theme={"system"}
  await context.run("dispatch-order", async () => {
    return await dispatchOrder(orderId, items)
  })
  ```

  ```python main.py theme={"system"}
  async def _dispatch_order():
      return await dispatch_order(order_id, items)

  await context.run("dispatch-order", _dispatch_order)

  ```
</CodeGroup>

### 4. Sending Confirmation and Notification Emails

Lastly, we send an order confirmation email to the customer and notify them when the order is dispatched:

<CodeGroup>
  ```typescript api/workflow/route.ts theme={"system"}
  await context.run("send-confirmation", async () => {
    return await sendOrderConfirmation(userId, orderId)
  })

  await context.run("send-dispatch-notification", async () => {
    return await sendDispatchNotification(userId, orderId)
  })
  ```

  ```python main.py theme={"system"}
  async def _send_confirmation():
      return await send_order_confirmation(user_id, order_id)

  await context.run("send-confirmation", _send_confirmation)

  async def _send_dispatch_notification():
      return await send_dispatch_notification(user_id, order_id)

  await context.run("send-dispatch-notification", _send_dispatch_notification)

  ```
</CodeGroup>

## Key Features

1. **Stock Verification**: Ensures items are available in stock before processing the payment, avoiding issues with unavailable products.

2. **Payment Processing**: Handles payment securely and only proceeds to dispatch if successful.

3. **Customer Notifications**: Keeps the customer informed at each step of the order process, improving user experience.
