Skip to content

Commit 95561f1

Browse files
committed
Fix setState() silent failure causing state/status desynchronization
When setState() cannot find a matching state in the $possibleStates array (from STATE_TRANSITION_MATRIX), it now falls back to a direct lookup in sales_order_status_state for the given status, preferring the default state mapping. This prevents the order state from being permanently stuck at its previous value (typically pending_payment) while the status advances through the order lifecycle. The fallback query uses addOrder('is_default', 'DESC') to prefer the default state when a status maps to multiple states, and setPageSize(1) to limit the SQL query at the database level. Uses getOrderContext() for consistent logging with the rest of the module. Fixes #3288
1 parent 11cda6a commit 95561f1

1 file changed

Lines changed: 32 additions & 1 deletion

File tree

Helper/Order.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,12 +493,43 @@ private function setState(MagentoOrder $order, $status, $possibleStates): Magent
493493
}
494494

495495
$this->adyenLogger->addAdyenNotification(
496-
'No new state assigned, status should be connected to one of the following states: ' . json_encode($possibleStates),
496+
'No new state assigned via preferred states, attempting fallback lookup. '
497+
. 'Status should be connected to one of the following states: ' . json_encode($possibleStates),
497498
[
498499
'pspReference' => $order->getPayment()->getData('adyen_psp_reference'),
499500
'merchantReference' => $order->getPayment()->getData('entity_id')
500501
]);
501502

503+
// Fallback: resolve state directly from sales_order_status_state without
504+
// constraining to $possibleStates. This prevents state/status desynchronization
505+
// when the configured status maps to a state not in STATE_TRANSITION_MATRIX.
506+
// The fallback is intentionally unconstrained: the status was already set by the
507+
// caller, so aligning the state to match is always better than leaving a permanent
508+
// mismatch (e.g. state=pending_payment + status=complete).
509+
// See https://github.com/Adyen/adyen-magento2/issues/3288
510+
$fallbackCollection = $this->orderStatusCollectionFactory->create()
511+
->addFieldToFilter('main_table.status', $status)
512+
->joinStates();
513+
$fallbackCollection->getSelect()->order('state_table.is_default DESC');
514+
$fallbackCollection->setPageSize(1);
515+
$fallbackStatus = $fallbackCollection->getFirstItem();
516+
$fallbackState = $fallbackStatus->getState();
517+
518+
if (!empty($fallbackState)) {
519+
$order->setState($fallbackState);
520+
$this->adyenLogger->addAdyenNotification(
521+
'State set via fallback to ' . $fallbackState
522+
. ' (status "' . $status . '" not mapped to preferred states: '
523+
. json_encode($possibleStates) . ')',
524+
array_merge(
525+
$this->adyenLogger->getOrderContext($order),
526+
['pspReference' => $order->getPayment()->getData('adyen_psp_reference')]
527+
)
528+
);
529+
530+
return $order;
531+
}
532+
502533
return $order;
503534
}
504535

0 commit comments

Comments
 (0)