Skip to main content

Overview

The order transitions module provides validation logic for state changes in the order lifecycle. It ensures that orders can only transition between valid states, maintaining data integrity and business rule compliance.

canTransition

Validates whether an order can transition from one status to another based on predefined business rules.

Function Signature

function canTransition(from: OrderStatus, to: OrderStatus): boolean

Parameters

from
OrderStatus
required
The current status of the order. Must be a valid OrderStatus value.
to
OrderStatus
required
The desired target status. Must be a valid OrderStatus value.

Returns

boolean
boolean
Returns true if the transition is allowed, false otherwise.

Transition Rules

The complete transition matrix defines which status changes are permitted:
const ALLOWED_TRANSITIONS: Record<OrderStatus, OrderStatus[]> = {
  RECEIVED: ["CONFIRMED", "CANCELLED"],
  CONFIRMED: ["PREPARING", "CANCELLED"],
  PREPARING: ["READY", "CANCELLED"],
  READY: ["PICKED_UP", "CANCELLED"],
  PICKED_UP: ["DELIVERED"],
  DELIVERED: [],
  CANCELLED: [],
};

Valid Transitions

From RECEIVED, can transition to:
  • CONFIRMED - Kitchen acknowledges and accepts the order
  • CANCELLED - Order is cancelled before confirmation
RECEIVED is the initial state for new orders. Orders must be confirmed before preparation can begin.

Usage Examples

import { canTransition } from "@/domain/order/order-transitions";

// Check if transition is valid
if (canTransition("RECEIVED", "CONFIRMED")) {
  console.log("Valid transition");
  // Proceed with status update
} else {
  console.log("Invalid transition");
  // Show error to user
}

State Diagram

The order status transitions can be visualized as a directed graph:

Business Rules

Terminal States: Once an order reaches DELIVERED or CANCELLED, no further transitions are allowed. These represent final states in the order lifecycle.
Cancellation Window: Orders can be cancelled at any point up to and including the READY status. Once PICKED_UP, cancellation is no longer possible.
Linear Progression: For successful order completion, the status must progress linearly through the normal flow: RECEIVED → CONFIRMED → PREPARING → READY → PICKED_UP → DELIVERED.

Complete Source Code

import { OrderStatus } from "./order-status";

const ALLOWED_TRANSITIONS: Record<OrderStatus, OrderStatus[]> = {
  RECEIVED: ["CONFIRMED", "CANCELLED"],
  CONFIRMED: ["PREPARING", "CANCELLED"],
  PREPARING: ["READY", "CANCELLED"],
  READY: ["PICKED_UP", "CANCELLED"],
  PICKED_UP: ["DELIVERED"],
  DELIVERED: [],
  CANCELLED: [],
};

export function canTransition(from: OrderStatus, to: OrderStatus): boolean {
  return ALLOWED_TRANSITIONS[from].includes(to);
}

Error Handling

When implementing status transitions, consider these error scenarios:
import { canTransition } from "@/domain/order/order-transitions";

class InvalidTransitionError extends Error {
  constructor(from: OrderStatus, to: OrderStatus) {
    super(`Invalid transition from ${from} to ${to}`);
    this.name = "InvalidTransitionError";
  }
}

async function safeTransition(
  orderId: string,
  currentStatus: OrderStatus,
  targetStatus: OrderStatus
) {
  // Validate transition
  if (!canTransition(currentStatus, targetStatus)) {
    throw new InvalidTransitionError(currentStatus, targetStatus);
  }
  
  try {
    // Perform database update
    await updateOrderInDb(orderId, targetStatus);
    
    // Log the transition
    await logStatusChange(orderId, currentStatus, targetStatus);
    
    return { success: true, newStatus: targetStatus };
  } catch (error) {
    console.error(`Failed to update order ${orderId}:`, error);
    throw error;
  }
}

Source Location

~/workspace/source/domain/order/order-transitions.ts

Build docs developers (and LLMs) love