Order Workflow
Processing Workflow
// Standard order processing workflow
namespace Vendor\Order\Processor;
class OrderProcessor
{
public function __construct(
private \Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
private \Magento\Sales\Model\Service\InvoiceService $invoiceService,
private \Magento\Sales\Model\Service\ShipmentService $shipmentService
) {}
public function processOrder(int $orderId): void
{
$order = $this->orderRepository->get($orderId);
// Step 1: Validate order
$this->validateOrder($order);
// Step 2: Process payment
$this->processPayment($order);
// Step 3: Create invoice (if auto-invoice enabled)
if ($this->canAutoInvoice($order)) {
$this->createInvoice($order);
}
// Step 4: Create shipment (if digital product)
if ($this->isDigitalProduct($order)) {
$this->createShipment($order);
}
// Step 5: Send notifications
$this->sendNotifications($order);
}
}
Workflow Steps
| Step | Action | Condition |
|---|---|---|
| 1 | Validate | Always |
| 2 | Process Payment | If not already paid |
| 3 | Create Invoice | Auto-invoice enabled |
| 4 | Create Shipment | Digital products or auto-ship |
| 5 | Send Notifications | Always |
Automatic Invoicing
Auto-Invoice Configuration
// Configuration for automatic invoicing
namespace Vendor\Order\Config;
class AutoInvoiceConfig
{
public function __construct(
private \Magento\Framework\App\Config\ScopeConfigInterface $config
) {}
public function isAutoInvoiceEnabled(): bool
{
return $this->config->isSetFlag(
'sales/orders/auto_invoice',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
);
}
}
Auto-Invoice Observer
namespace Vendor\Order\Observer;
class AutoInvoiceObserver implements \Magento\Framework\Event\ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer): void
{
$order = $observer->getEvent()->getOrder();
if ($this->canAutoInvoice($order)) {
$this->createInvoice($order);
}
}
private function canAutoInvoice(\Magento\Sales\Api\Data\OrderInterface $order): bool
{
return $order->canInvoice() &&
$this->config->isAutoInvoiceEnabled() &&
$order->getPayment()->getMethod() !== 'checkmo';
}
}
Event Registration
<!-- etc/events.xml -->
<config>
<event name="sales_order_place_after">
<observer name="auto_invoice" instance="Vendor\Order\Observer\AutoInvoiceObserver"/>
</event>
</config>
Automated Shipment Processing
Auto-Shipment for Digital Products
namespace Vendor\Order\Processor;
class DigitalShipmentProcessor
{
public function __construct(
private \Magento\Sales\Model\Service\ShipmentService $shipmentService,
private \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
) {}
public function processDigitalShipment(
\Magento\Sales\Api\Data\OrderInterface $order
): void {
$hasDigitalItems = false;
foreach ($order->getItems() as $item) {
$product = $this->productRepository->getById($item->getProductId());
if ($product->getIsDigital()) {
$hasDigitalItems = true;
break;
}
}
if ($hasDigitalItems) {
$this->shipmentService->createShipment(
$order,
[], // All items
[['carrier' => 'digital', 'number' => 'DIGITAL-' . $order->getIncrementId()]]
);
}
}
}
Batch Processing
namespace Vendor\Order\Cron;
class BatchShipment
{
public function execute(): void
{
$orders = $this->getOrdersForShipment();
foreach ($orders as $order) {
try {
$this->processShipment($order);
} catch (\Exception $e) {
$this->logger->error(
'Shipment failed for order: ' . $order->getIncrementId(),
['error' => $e->getMessage()]
);
}
}
}
private function getOrdersForShipment(): array
{
return $this->orderCollectionFactory->create()
->addFieldToFilter('state', 'processing')
->addFieldToFilter('can_ship', 1)
->setPageSize(100)
->getItems();
}
}
State Transition Automation
Automatic State Updates
namespace Vendor\Order\State;
class StateAutomation
{
public function __construct(
private \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
) {}
public function updateOrderState(
\Magento\Sales\Api\Data\OrderInterface $order
): void {
$state = $this->determineState($order);
if ($state !== $order->getState()) {
$order->setState($state);
$order->addStatusHistoryComment(
sprintf('Automatic state transition to %s', $state)
);
$this->orderRepository->save($order);
}
}
private function determineState(
\Magento\Sales\Api\Data\OrderInterface $order
): string {
// All items invoiced and shipped = complete
if (!$order->canInvoice() && !$order->canShip()) {
return \Magento\Sales\Model\Order::STATE_COMPLETE;
}
// Payment captured but items not fully processed = processing
if ($order->getPayment()->isCaptured()) {
return \Magento\Sales\Model\Order::STATE_PROCESSING;
}
// Awaiting payment = pending_payment
if (!$order->getPayment()->isCaptured()) {
return \Magento\Sales\Model\Order::STATE_PENDING_PAYMENT;
}
return $order->getState();
}
}
Cron-Based Processing
<!-- crontab.xml -->
<config>
<group id="default">
<job name="order_processing_automation" instance="Vendor\Order\Cron\ProcessOrders" method="execute">
<schedule>*/5 * * * *</schedule>
</job>
</group>
</config>
Quiz
1. What triggers automatic invoicing?
2. When does an order state transition to complete?
3. How are digital products shipped?
Flashcards
Question
Auto-invoice trigger?
Click to reveal answer
Answer
sales_order_place_after event + auto_invoice config enabled
Question
Complete state condition?
Click to reveal answer
Answer
All items invoiced AND shipped
Question
Digital product shipment?
Click to reveal answer
Answer
Automatic with digital carrier and tracking
Question
Order processing cron?
Click to reveal answer
Answer
Runs periodically to automate state transitions
Revision Notes
Key Takeaways
- 1. Order workflows automate processing steps after placement
- 2. Automatic invoicing triggers on order place when configured
- 3. Digital products receive automatic shipment processing
- 4. State transitions are determined by invoice and shipment status
- 5. Cron jobs can automate batch order processing
Interview Tips
- • Describe the complete order processing workflow
- • Explain how automatic invoicing is triggered and configured
- • Discuss the criteria for state transitions to complete
Cheat Sheet
Order Processing:
Place → Validate → Payment → Invoice → Ship → Notify
Auto-Invoice:
Event: sales_order_place_after
Config: sales/orders/auto_invoice
Condition: canInvoice() && payment captured
State Transitions:
canInvoice() == false && canShip() == false → complete
payment captured → processing
awaiting payment → pending_payment
Cron:
Batch process orders periodically