From 85467c4c583eef82c66e58fc1ffeb9e6a85ef62c Mon Sep 17 00:00:00 2001 From: Ivan Bochkarev Date: Tue, 28 Jul 2026 11:38:15 +0600 Subject: [PATCH] fix(order): revalidate fixed status after plugin status mutation Extract validateStatusTransition() and run it again after msOnBeforeChangeOrderStatus may change the target status id. --- .../src/Services/Order/OrderStatusService.php | 37 +++++++++++++++---- .../tests/OrderStatusFixedRevalidateTest.php | 37 +++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 core/components/minishop3/tests/OrderStatusFixedRevalidateTest.php diff --git a/core/components/minishop3/src/Services/Order/OrderStatusService.php b/core/components/minishop3/src/Services/Order/OrderStatusService.php index 5185b1df..3c1544f5 100644 --- a/core/components/minishop3/src/Services/Order/OrderStatusService.php +++ b/core/components/minishop3/src/Services/Order/OrderStatusService.php @@ -104,13 +104,9 @@ public function change(int $orderId, int $statusId, bool $skipNotifications = fa ); if ($oldStatus) { - if ($oldStatus->get('final')) { - return $this->modx->lexicon('ms3_err_status_final'); - } - if ($oldStatus->get('fixed')) { - if ($status->get('position') <= $oldStatus->get('position')) { - return $this->modx->lexicon('ms3_err_status_fixed'); - } + $transitionError = $this->validateStatusTransition($oldStatus, $status); + if ($transitionError !== null) { + return $transitionError; } } @@ -143,6 +139,11 @@ public function change(int $orderId, int $statusId, bool $skipNotifications = fa if ($msOrder->get('status_id') == $statusId) { return $this->modx->lexicon('ms3_err_status_same'); } + + $transitionError = $this->validateStatusTransition($oldStatus, $status); + if ($transitionError !== null) { + return $transitionError; + } } $msOrder->set('status_id', $statusId); @@ -173,6 +174,28 @@ public function change(int $orderId, int $statusId, bool $skipNotifications = fa return true; } + /** + * Validate transition from old status to new (final/fixed rules). + */ + protected function validateStatusTransition( + ?msOrderStatusModel $oldStatus, + msOrderStatusModel $newStatus + ): ?string { + if (!$oldStatus) { + return null; + } + + if ($oldStatus->get('final')) { + return $this->modx->lexicon('ms3_err_status_final'); + } + + if ($oldStatus->get('fixed') && $newStatus->get('position') <= $oldStatus->get('position')) { + return $this->modx->lexicon('ms3_err_status_fixed'); + } + + return null; + } + /** * Send notifications for status change * diff --git a/core/components/minishop3/tests/OrderStatusFixedRevalidateTest.php b/core/components/minishop3/tests/OrderStatusFixedRevalidateTest.php new file mode 100644 index 00000000..4b1a9c15 --- /dev/null +++ b/core/components/minishop3/tests/OrderStatusFixedRevalidateTest.php @@ -0,0 +1,37 @@ +