Skip to content
intermediate Phase 48 · Checkout Production

Order Placement

Place order API, order creation, inventory reservation, and payment processing

45m
0 problems
Topic Progress 0%

Order Placement Flow

Place Order Service

namespace Magento\Checkout\Model;

class PlaceOrder
{
    public function __construct(
        private \Magento\Quote\Api\CartRepositoryInterface $cartRepository,
        private \Magento\Quote\Api\CartManagementInterface $cartManagement,
        private \Magento\Quote\Model\QuoteFactory $quoteFactory
    ) {}

    public function execute(int $cartId): int
    {
        $cart = $this->cartRepository->get($cartId);

        // Validate cart
        $this->validateCart($cart);

        // Reserve order ID
        $cart->reserveOrderId();

        // Convert quote to order
        $orderId = $this->cartManagement->placeOrder($cartId);

        return $orderId;
    }

    private function validateCart(\Magento\Quote\Api\Data\CartInterface $cart): void
    {
        if ($cart->getItemsCount() === 0) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('Cart is empty')
            );
        }

        if (!$cart->getShippingAddress()->getShippingMethod()) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('Shipping method not selected')
            );
        }

        if (!$cart->getPayment()->getMethod()) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('Payment method not selected')
            );
        }
    }
}

Inventory Reservation

Inventory Reservation System

// Magento\InventoryReservation\Model\ReservationFactory
namespace Magento\Inventory\Api\ReservationServiceInterface;

interface ReservationServiceInterface
{
    /**
     * Create inventory reservation
     */
    public function create(
        string $sku,
        int $stockId,
        float $quantity,
        string $reservationId
    ): void;
}

Reservation During Order Placement

// During order creation, inventory is reserved
namespace Magento\Sales\Model\Service\Order;

class InventoryReservation
{
    public function __construct(
        private \Magento\Inventory\Api\ReservationServiceInterface $reservationService,
        private \Magento\Inventory\Api\StockResolverInterface $stockResolver
    ) {}

    public function reserve(
        \Magento\Sales\Api\Data\OrderInterface $order
    ): void {
        foreach ($order->getItems() as $item) {
            $stockId = $this->stockResolver->execute(
                $item->getWebsiteId()
            )->getStockId();

            $this->reservationService->create(
                $item->getSku(),
                $stockId,
                -$item->getQtyOrdered(),
                sprintf('order:%s:items:%s', $order->getIncrementId(), $item->getItemId())
            );
        }
    }
}

Reservation Cleanup

// Cancel reservation when order is cancelled
public function cancelReservation(\Magento\Sales\Api\Data\OrderInterface $order): void
{
    foreach ($order->getItems() as $item) {
        $this->reservationService->create(
            $item->getSku(),
            $stockId,
            $item->getQtyOrdered(), // Positive to release
            sprintf('order:%s:cancel', $order->getIncrementId())
        );
    }
}

Payment Processing

Payment During Order Placement

namespace Magento\Quote\Model\QuoteManagement;

class PaymentProcessor
{
    public function process(
        \Magento\Quote\Model\Quote $quote,
        \Magento\Sales\Api\Data\OrderInterface $order
    ): void {
        $payment = $order->getPayment();
        $paymentMethod = $quote->getPayment()->getMethod();

        // Get payment method instance
        $method = $this->paymentMethodPool->getMethod($paymentMethod);

        // Process based on action type
        switch ($method->getConfigData('payment_action')) {
            case 'authorize':
                $method->authorize($payment, $order->getGrandTotal());
                break;
            case 'authorize_capture':
                $method->order($payment, $order->getGrandTotal());
                break;
        }

        // Set order status
        $order->setStatus($method->getConfigData('order_status'));
    }
}

Payment Error Handling

try {
    $orderId = $this->placeOrder->execute($cartId);
} catch (\Magento\Framework\Exception\PaymentException $e) {
    // Payment failed - restore inventory
    $this->inventoryReservation->cancelReservation($order);

    // Log error
    $this->logger->error('Payment failed: ' . $e->getMessage());

    throw new \Magento\Framework\Exception\LocalizedException(
        __('Payment processing failed: %1', $e->getMessage())
    );
} catch (\Exception $e) {
    // General error
    $this->logger->critical($e);
    throw $e;
}

Complete Order Placement

Quote to Order Conversion

// Full order placement flow
public function placeOrder(int $cartId): int
{
    $cart = $this->cartRepository->get($cartId);

    // 1. Validate cart items
    $this->validateItems($cart);

    // 2. Reserve order ID
    $cart->reserveOrderId();

    // 3. Collect totals
    $cart->collectTotals();

    // 4. Create order from quote
    $order = $this->quoteToOrderConverter->convert($cart);

    // 5. Process payment
    $this->paymentProcessor->process($cart, $order);

    // 6. Reserve inventory
    $this->inventoryReservation->reserve($order);

    // 7. Save order
    $this->orderRepository->save($order);

    // 8. Send order confirmation email
    $this->orderEmailSender->send($order);

    // 9. Deactivate quote
    $cart->setIsActive(0)->save();

    return $order->getEntityId();
}

Guest Order Placement

// Guest order with email
POST /rest/V1/guest-carts/{cartId}/payment-information
{
    "paymentMethod": {
        "method": "checkmo"
    },
    "billingAddress": {
        "firstname": "Guest",
        "lastname": "Customer",
        "email": "guest@example.com",
        "street": ["123 Main St"],
        "city": "New York",
        "region_id": 43,
        "postcode": "10001",
        "country_id": "US",
        "telephone": "555-1234"
    }
}

Quiz

1. What happens to inventory when an order is placed?

Question 1 options

2. What is the order of operations during order placement?

Question 2 options

3. What happens if payment fails during order placement?

Question 3 options

Flashcards

Question

Order placement first step?

Answer

Validate cart (items, shipping method, payment method)

Question

What is inventory reservation?

Answer

Decrementing stock when order is placed to prevent overselling

Question

Payment processing order?

Answer

authorize (hold) or authorize_capture (collect) based on config

Question

Post-order actions?

Answer

Send email, deactivate quote, log order

Revision Notes

Key Takeaways

  • 1. Order placement validates cart, reserves ID, processes payment, and saves order
  • 2. Inventory is reserved during order placement to prevent overselling
  • 3. Payment methods support authorize-only or authorize-capture actions
  • 4. Failed payments trigger inventory reservation cleanup
  • 5. Guest orders use email as identifier instead of customer ID

Interview Tips

  • Describe the complete order placement flow from cart to order
  • Explain how inventory reservation prevents overselling
  • Discuss error handling when payment processing fails

Cheat Sheet

Order Placement Flow:
  1. Validate cart
  2. Reserve order ID
  3. Collect totals
  4. Convert quote to order
  5. Process payment
  6. Reserve inventory
  7. Save order
  8. Send email
  9. Deactivate quote

Inventory:
  Reserve on order: negative qty
  Release on cancel: positive qty

Payment:
  authorize → hold funds
  authorize_capture → collect funds