Overview

This guide covers the complete order management flow, from cart validation to order completion. Understanding this process is crucial for building a reliable storefront.

Order Flow Overview

1. Cart Validation

Before accepting payment, validate the cart:
const validateCart = async (locationId, cartId, customerData) => {
  try {
    const validatedCart = await fetch(`/api/v1/locations/${locationId}/cart/${cartId}/validate-and-update`, {
      method: 'PUT',
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        customerName: customerData.name,
        emailAddress: customerData.email,
        phoneNumber: customerData.phone
      })
    });
    
    if (!validatedCart.ok) {
      const error = await validatedCart.json();
      throw new Error(error.message);
    }
    
    return validatedCart.json();
  } catch (error) {
    console.error('Cart validation failed:', error);
    throw error;
  }
};

2. Payment Processing

Create payment intent and handle payment:
const processPayment = async (locationId, cartId, paymentMethod) => {
  try {
    // Create payment intent
    const paymentIntent = await createPaymentIntent(locationId, cartId);
    
    // Confirm payment with Stripe
    const { error, paymentIntent: confirmedPayment } = await stripe.confirmCardPayment(
      paymentIntent.client_secret,
      {
        payment_method: paymentMethod
      }
    );
    
    if (error) {
      throw new Error(error.message);
    }
    
    return confirmedPayment;
  } catch (error) {
    console.error('Payment processing failed:', error);
    throw error;
  }
};

3. Order Creation

Orders are automatically created when payment succeeds:
const handlePaymentSuccess = async (paymentIntentId, locationId, cartId) => {
  try {
    // Order is automatically created by Crave backend
    // You can fetch the order details if needed
    const orderResponse = await fetch(`/api/v1/locations/${locationId}/orders/by-payment-intent/${paymentIntentId}`, {
      headers: { 'X-API-Key': API_KEY }
    });
    
    if (orderResponse.ok) {
      const order = await orderResponse.json();
      
      // Redirect to order confirmation
      router.push(`/order-confirmation/${order.id}`);
      
      // Clear cart
      clearCart();
      
      return order;
    }
  } catch (error) {
    console.error('Order creation failed:', error);
    // Handle gracefully - payment succeeded but order retrieval failed
  }
};

4. Order Status Management

Order States

Orders can have these states:
  • pending - Order created, waiting for restaurant confirmation
  • confirmed - Restaurant confirmed the order
  • preparing - Order is being prepared
  • ready - Order is ready for pickup/delivery
  • completed - Order has been fulfilled
  • cancelled - Order was cancelled

Status Updates

const trackOrder = async (orderId) => {
  try {
    const response = await fetch(`/api/v1/orders/${orderId}/status`, {
      headers: { 'X-API-Key': API_KEY }
    });
    
    if (!response.ok) {
      throw new Error('Failed to fetch order status');
    }
    
    const order = await response.json();
    
    // Update UI based on order status
    updateOrderStatus(order.status, order.estimatedReadyTime);
    
    return order;
  } catch (error) {
    console.error('Order tracking failed:', error);
  }
};

5. Customer Communication

Order Confirmation

const sendOrderConfirmation = async (order) => {
  // This is handled automatically by Crave backend
  // But you can send additional confirmations if needed
  
  try {
    if (order.customer.email) {
      await sendCustomerEmail({
        to: order.customer.email,
        subject: `Order Confirmation - ${order.id}`,
        template: 'order-confirmation',
        data: {
          orderId: order.id,
          items: order.items,
          total: order.total,
          estimatedReadyTime: order.estimatedReadyTime
        }
      });
    }
  } catch (error) {
    console.error('Failed to send confirmation email:', error);
  }
};

Status Updates

const notifyCustomer = async (orderId, status) => {
  const messages = {
    confirmed: 'Your order has been confirmed!',
    preparing: 'Your order is being prepared',
    ready: 'Your order is ready for pickup!',
    completed: 'Thank you for your order!'
  };
  
  // Send notification (email, SMS, push, etc.)
  await sendNotification({
    orderId,
    message: messages[status],
    status
  });
};

6. Error Recovery

Payment Failures

const handlePaymentError = (error, cartId) => {
  console.error('Payment failed:', error);
  
  // Keep cart intact for retry
  // Show user-friendly error message
  showErrorMessage('Payment failed. Please try again or use a different payment method.');
  
  // Log for debugging
  logPaymentError(error, cartId);
};

Order Creation Failures

const handleOrderCreationError = (paymentIntentId, error) => {
  console.error('Order creation failed after successful payment:', error);
  
  // Critical error - payment succeeded but order not created
  // Show user that payment was processed but order needs manual verification
  showCriticalError('Payment processed successfully. Please contact support with your payment confirmation.');
  
  // Alert support team
  alertSupport({
    type: 'order_creation_failure',
    paymentIntentId,
    error: error.message
  });
};

7. Testing Order Flow

Test Scenarios

describe('Order Flow', () => {
  test('successful order creation', async () => {
    const cart = await createCart(locationId);
    await addItemToCart(locationId, cart.id, testProduct, 1);
    
    const validatedCart = await validateCart(locationId, cart.id, testCustomer);
    expect(validatedCart.isValid).toBe(true);
    
    const paymentIntent = await createPaymentIntent(locationId, cart.id);
    expect(paymentIntent.client_secret).toBeDefined();
    
    // Simulate successful payment
    const order = await simulateSuccessfulPayment(paymentIntent.id);
    expect(order.status).toBe('pending');
  });
  
  test('cart validation failure', async () => {
    const cart = await createCart(locationId);
    // Add out of stock item
    
    await expect(validateCart(locationId, cart.id, testCustomer))
      .rejects.toThrow('Item is out of stock');
  });
});

Best Practices

  1. Always validate carts before payment
  2. Handle payment failures gracefully
  3. Provide real-time order updates when possible
  4. Log critical errors for debugging
  5. Test edge cases thoroughly
  6. Keep customers informed throughout the process