Order Processing Example

Complete e-commerce order fulfillment workflow with inventory, payment, and shipping.

Overview

This example demonstrates:

Code

import { Workflow } from "@mdwr/sdk";

const orderProcessingWorkflow = Workflow.create("order_processing_v1")
  .step("validate_order", async (ctx) => {
    const { orderId, items, customerId } = ctx.input;

    if (!orderId || !items || items.length === 0) {
      return {
        decision: "reject",
        reason: "Invalid order: missing orderId or items",
        confidence: 1.0
      };
    }

    // Query memory for similar orders
    const insights = await ctx.memory.similar({
      situation: "order_validation",
      context: { customerId, itemCount: items.length }
    });

    let decision = "approve";
    let reason = "Order validated successfully";
    let confidence = 0.9;

    // Check for suspicious patterns
    if (insights.length > 0) {
      const suspicious = insights.filter(i => i.outcome && !i.outcome.success);
      if (suspicious.length > 2) {
        decision = "flag";
        reason = "Multiple failed orders detected for this customer";
        confidence = 0.8;
      }
    }

    return { decision, reason, confidence };
  }, true)
  .step("check_inventory", async (ctx) => {
    if (ctx.state.validate_order?.decision !== "approve") {
      return { decision: "skip", reason: "Order validation failed", confidence: 1.0 };
    }

    const { items } = ctx.input;
    const unavailableItems = [];

    // Simulate inventory check
    for (const item of items) {
      const inStock = Math.random() > 0.1; // 90% chance in stock
      if (!inStock) {
        unavailableItems.push(item.productId);
      }
    }

    if (unavailableItems.length > 0) {
      return {
        decision: "partial",
        reason: `Some items unavailable: ${unavailableItems.join(", ")}`,
        confidence: 0.9,
        metadata: { unavailableItems }
      };
    }

    return {
      decision: "available",
      reason: "All items in stock",
      confidence: 0.95
    };
  }, true)
  .step("process_payment", async (ctx) => {
    const inventoryDecision = ctx.state.check_inventory?.decision;
    if (inventoryDecision !== "available" && inventoryDecision !== "partial") {
      return { decision: "skip", reason: "Inventory check failed", confidence: 1.0 };
    }

    const { paymentMethod, totalAmount, customerId } = ctx.input;

    // Query memory for payment decisions
    const insights = await ctx.memory.similar({
      situation: "payment_processing",
      context: { paymentMethod, amount: totalAmount, customerId }
    });

    let decision = "success";
    let reason = "Payment processed successfully";
    let confidence = 0.9;

    // Use historical payment data
    if (insights.length > 0) {
      const failedPayments = insights.filter(i => i.outcome && !i.outcome.success);
      if (failedPayments.length > 0) {
        decision = "review";
        reason = "Historical payment issues detected";
        confidence = 0.7;
      }
    }

    // Simulate payment processing
    const paymentSuccess = Math.random() > 0.05; // 95% success rate
    if (!paymentSuccess) {
      decision = "failed";
      reason = "Payment processing failed";
      confidence = 1.0;
    }

    return { decision, reason, confidence };
  }, true)
  .step("calculate_shipping", async (ctx) => {
    if (ctx.state.process_payment?.decision !== "success") {
      return { decision: "skip", reason: "Payment processing failed", confidence: 1.0 };
    }

    const { shippingAddress, items } = ctx.input;

    // Query memory for shipping decisions
    const insights = await ctx.memory.similar({
      situation: "shipping_calculation",
      context: { address: shippingAddress.country, itemCount: items.length }
    });

    let shippingCost = 10; // Base shipping
    let shippingMethod = "standard";
    let reason = "Standard shipping calculated";

    // Use historical shipping data
    if (insights.length > 0) {
      const best = insights[0];
      if (best.metadata?.shippingCost) {
        shippingCost = best.metadata.shippingCost;
        shippingMethod = best.metadata.shippingMethod || "standard";
        reason = `Shipping based on similar orders: ${shippingMethod}`;
      }
    }

    // Calculate based on address
    if (shippingAddress.country !== "US") {
      shippingCost = 25;
      shippingMethod = "international";
      reason = "International shipping";
    }

    return {
      decision: "calculated",
      reason,
      confidence: 0.95,
      metadata: {
        shippingCost,
        shippingMethod,
        estimatedDays: shippingMethod === "international" ? 14 : 5
      }
    };
  }, true)
  .step("fulfill_order", async (ctx) => {
    if (ctx.state.calculate_shipping?.decision !== "calculated") {
      return { decision: "skip", reason: "Shipping calculation failed", confidence: 1.0 };
    }

    const { orderId } = ctx.input;
    const shipping = ctx.state.calculate_shipping.metadata;

    // Simulate order fulfillment
    console.log(`Fulfilling order ${orderId}`);
    console.log(`Shipping via ${shipping.shippingMethod} - $${shipping.shippingCost}`);

    return {
      decision: "completed",
      reason: "Order fulfilled successfully",
      confidence: 1.0,
      metadata: {
        orderId,
        fulfilledAt: new Date().toISOString(),
        trackingNumber: `TRK-${Math.random().toString(36).substring(7)}`,
        shipping
      }
    };
  }, true);

export default orderProcessingWorkflow;

Running the Example

# Deploy the workflow
npx ts-node scripts/deploy.ts

# Execute with sample input
npx ts-node scripts/execute.ts order_processing_v1

Input Example

{
  "orderId": "ORD-123",
  "customerId": "CUST-456",
  "items": [
    { "productId": "PROD-1", "quantity": 2 }
  ],
  "paymentMethod": "credit_card",
  "totalAmount": 99.99,
  "shippingAddress": {
    "country": "US"
  }
}

Workflow Steps

  1. Validate Order - Check order validity and customer history
  2. Check Inventory - Verify item availability
  3. Process Payment - Handle payment with fraud detection
  4. Calculate Shipping - Determine shipping cost and method
  5. Fulfill Order - Complete order processing

Key Features

Memory-Based Fraud Detection

const suspicious = insights.filter(i => i.outcome && !i.outcome.success);
if (suspicious.length > 2) {
  decision = "flag";
}

Historical Shipping Data

const insights = await ctx.memory.similar({
  situation: "shipping_calculation",
  context: { address: shippingAddress.country }
});

Next Steps