Machine Coding Problem

Order Manager

macoAllcommercestate-machineevent-driven
Commonly Asked By:AmazonWalmartShopifyTarget

Functional Specifications (In-Scope)

  • Strict Finite State Machine: Defines valid transitions between states and throws errors on illegal moves.
  • Compensating Saga Transactions: Restores physical stock balances and triggers payment refunds if order flow fails.
  • Audit log & Event Stream: Records transitions to build structural tracking logs and emit domain events.
  • Idempotency Guarantees: Avoids executing repeat actions for identical status inputs.

Out-of-Scope Boundaries

  • Payment Gateway Handshakes: Excludes live Stripe/PayPal API endpoints, utilizing mock decorators.
  • Warehousing Carrier Routing: Excludes actual dynamic logistics matching or warehouse pickup slips.

Production reference implementations demonstrating order state validation, audit log capture, and Saga compensations:

// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;
import java.util.concurrent.*;

enum OrderStatus {
    PLACED,
    CONFIRMED,
    PACKED,
    SHIPPED,
    DELIVERED,
    CANCELLED,
    REFUNDED
}

class OrderItem {
    private final String productId;
    private final int quantity;
    private final double unitPrice;

    public OrderItem(String productId, int quantity, double unitPrice) {
        this.productId = productId;
        this.quantity = quantity;
        this.unitPrice = unitPrice;
    }

    public String getProductId() { return productId; }
    public int getQuantity() { return quantity; }
    public double getUnitPrice() { return unitPrice; }
}

class Order {
    private final String orderId;
    private final List<OrderItem> items;
    private OrderStatus status;
    private final double totalAmount;

    public Order(String orderId, List<OrderItem> items) {
        this.orderId = orderId;
        this.items = items;
        this.status = OrderStatus.PLACED;
        this.totalAmount = items.stream().mapToDouble(i -> i.getQuantity() * i.getUnitPrice()).sum();
    }

    public String getOrderId() { return orderId; }
    public List<OrderItem> getItems() { return items; }
    public OrderStatus getStatus() { return status; }
    public double getTotalAmount() { return totalAmount; }

    public void setStatus(OrderStatus status) {
        this.status = status;
    }
}

class InvalidTransitionException extends RuntimeException {
    public InvalidTransitionException(String message) {
        super(message);
    }
}

class OrderEvent {
    private final String eventId;
    private final String orderId;
    private final OrderStatus fromStatus;
    private final OrderStatus toStatus;
    private final long timestamp;

    public OrderEvent(String orderId, OrderStatus fromStatus, OrderStatus toStatus) {
        this.eventId = UUID.randomUUID().toString();
        this.orderId = orderId;
        this.fromStatus = fromStatus;
        this.toStatus = toStatus;
        this.timestamp = System.currentTimeMillis();
    }

    public String getEventId() { return eventId; }
    public String getOrderId() { return orderId; }
    public OrderStatus getFromStatus() { return fromStatus; }
    public OrderStatus getToStatus() { return toStatus; }
    public long getTimestamp() { return timestamp; }
}

interface OrderEventPublisher {
    void publish(OrderEvent event);
}

class AuditLogEntry {
    private final String orderId;
    private final OrderStatus fromStatus;
    private final OrderStatus toStatus;
    private final String actor;
    private final long timestamp;

    public AuditLogEntry(String orderId, OrderStatus fromStatus, OrderStatus toStatus, String actor) {
        this.orderId = orderId;
        this.fromStatus = fromStatus;
        this.toStatus = toStatus;
        this.actor = actor;
        this.timestamp = System.currentTimeMillis();
    }

    public String getOrderId() { return orderId; }
    public OrderStatus getFromStatus() { return fromStatus; }
    public OrderStatus getToStatus() { return toStatus; }
    public String getActor() { return actor; }
    public long getTimestamp() { return timestamp; }
}

class AuditService {
    private final List<AuditLogEntry> logs = new CopyOnWriteArrayList<>();

    public void logTransition(String orderId, OrderStatus from, OrderStatus to, String actor) {
        logs.add(new AuditLogEntry(orderId, from, to, actor));
    }

    public List<AuditLogEntry> getLogsForOrder(String orderId) {
        List<AuditLogEntry> result = new ArrayList<>();
        for (AuditLogEntry entry : logs) {
            if (entry.getOrderId().equals(orderId)) {
                result.add(entry);
            }
        }
        return result;
    }
}

class CompensationService {
    public boolean triggerPaymentRefund(String orderId, double amount) {
        System.out.println("SAGA COMPENSATOR: Refunding $" + amount + " to customer card for Order ID: " + orderId);
        return true;
    }

    public boolean triggerInventoryRestoration(String orderId, List<OrderItem> items) {
        for (OrderItem item : items) {
            System.out.println("SAGA COMPENSATOR: Restoring Qty " + item.getQuantity() + " for Product ID: " + item.getProductId());
        }
        return true;
    }
}

class OrderStateMachine {
    private final Map<OrderStatus, Set<OrderStatus>> validTransitions = new ConcurrentHashMap<>();

    public OrderStateMachine() {
        validTransitions.put(OrderStatus.PLACED, Set.of(OrderStatus.CONFIRMED, OrderStatus.CANCELLED));
        validTransitions.put(OrderStatus.CONFIRMED, Set.of(OrderStatus.PACKED, OrderStatus.CANCELLED));
        validTransitions.put(OrderStatus.PACKED, Set.of(OrderStatus.SHIPPED, OrderStatus.CANCELLED));
        validTransitions.put(OrderStatus.SHIPPED, Set.of(OrderStatus.DELIVERED, OrderStatus.CANCELLED));
        validTransitions.put(OrderStatus.DELIVERED, Set.of(OrderStatus.REFUNDED));
        validTransitions.put(OrderStatus.CANCELLED, Set.of());
        validTransitions.put(OrderStatus.REFUNDED, Set.of());
    }

    public boolean isValidTransition(OrderStatus from, OrderStatus to) {
        Set<OrderStatus> allowed = validTransitions.get(from);
        return allowed != null && allowed.contains(to);
    }
}

class OrderManager {
    private final Map<String, Order> orderRepository = new ConcurrentHashMap<>();
    private final OrderStateMachine stateMachine;
    private final OrderEventPublisher eventPublisher;
    private final AuditService auditService;
    private final CompensationService compensationService;

    public OrderManager(
        OrderStateMachine stateMachine,
        OrderEventPublisher eventPublisher,
        AuditService auditService,
        CompensationService compensationService
    ) {
        this.stateMachine = stateMachine;
        this.eventPublisher = eventPublisher;
        this.auditService = auditService;
        this.compensationService = compensationService;
    }

    public void registerOrder(Order order) {
        orderRepository.put(order.getOrderId(), order);
        auditService.logTransition(order.getOrderId(), null, OrderStatus.PLACED, "Customer");
    }

    public synchronized void transitionTo(String orderId, OrderStatus nextStatus, String actor) {
        Order order = orderRepository.get(orderId);
        if (order == null) {
            throw new IllegalArgumentException("Order not found: " + orderId);
        }

        OrderStatus currentStatus = order.getStatus();
        if (currentStatus == nextStatus) {
            return;
        }

        if (!stateMachine.isValidTransition(currentStatus, nextStatus)) {
            throw new InvalidTransitionException("Illegal state transition from " + currentStatus + " to " + nextStatus);
        }

        order.setStatus(nextStatus);
        auditService.logTransition(orderId, currentStatus, nextStatus, actor);

        OrderEvent event = new OrderEvent(orderId, currentStatus, nextStatus);
        eventPublisher.publish(event);

        if (nextStatus == OrderStatus.CANCELLED || nextStatus == OrderStatus.REFUNDED) {
            compensationService.triggerPaymentRefund(orderId, order.getTotalAmount());
            compensationService.triggerInventoryRestoration(orderId, order.getItems());
        }
    }

    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("=== JAVA ORDER MANAGEMENT SYSTEM SIMULATION ===");
        OrderStateMachine stateMachine = new OrderStateMachine();
        AuditService auditService = new AuditService();
        CompensationService compensationService = new CompensationService();
        
        OrderEventPublisher publisher = event -> {
            System.out.println("🔊 EVENT EMITTED: Order ID " + event.getOrderId() + 
                               " transitioned from " + event.getFromStatus() + 
                               " to " + event.getToStatus());
        };

        OrderManager manager = new OrderManager(stateMachine, publisher, auditService, compensationService);

        List<OrderItem> items = new ArrayList<>();
        items.add(new OrderItem("laptop", 1, 1200.0));
        items.add(new OrderItem("mouse", 2, 50.0));

        Order order = new Order("ORD-12345", items);
        manager.registerOrder(order);

        System.out.println("Initial Order Status: " + order.getStatus());
        System.out.println("Total Amount: $" + order.getTotalAmount());

        // Confirmed order
        manager.transitionTo("ORD-12345", OrderStatus.CONFIRMED, "Operator");
        System.out.println("Current Order Status: " + order.getStatus());

        // Attempt invalid transition
        try {
            System.out.println("\nAttempting illegal transition from CONFIRMED to DELIVERED...");
            manager.transitionTo("ORD-12345", OrderStatus.DELIVERED, "Operator");
        } catch (InvalidTransitionException e) {
            System.out.println("Caught Expected Error: " + e.getMessage());
        }

        // Cancel order to trigger compensating Saga transactions
        System.out.println("\nCancelling order to test compensating transaction...");
        manager.transitionTo("ORD-12345", OrderStatus.CANCELLED, "Customer");
        System.out.println("Final Order Status: " + order.getStatus());

        System.out.println("\nAudit Log History:");
        for (AuditLogEntry log : auditService.getLogsForOrder("ORD-12345")) {
            System.out.println(" - Status changed from " + log.getFromStatus() + 
                               " to " + log.getToStatus() + " by " + log.getActor());
        }

        System.out.println("=== END OF JAVA SIMULATION ===");
    }
}