From e221f3804fe2a62b1b4cbbb53a7dc9a70c08b0d0 Mon Sep 17 00:00:00 2001 From: Edward Yang Date: Tue, 9 Aug 2022 15:50:29 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E7=8A=B6=E6=80=81=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Http/Controllers/OrderController.php | 4 +- beike/Services/StateMachineService.php | 198 ++++++++++++++++-- 2 files changed, 187 insertions(+), 15 deletions(-) diff --git a/beike/Admin/Http/Controllers/OrderController.php b/beike/Admin/Http/Controllers/OrderController.php index c2bb5018..a47557ad 100644 --- a/beike/Admin/Http/Controllers/OrderController.php +++ b/beike/Admin/Http/Controllers/OrderController.php @@ -41,14 +41,16 @@ class OrderController extends Controller * @param Request $request * @param Order $order * @return mixed + * @throws \Exception */ public function show(Request $request, Order $order) { $order->load(['orderTotals', 'orderHistories']); $data = [ 'order' => $order, + 'statuses' => StateMachineService::getInstance($order)->nextBackendStatuses() ]; - +dd($data); return view('admin::pages.orders.form', $data); } diff --git a/beike/Services/StateMachineService.php b/beike/Services/StateMachineService.php index 9f8cb135..1447dffb 100644 --- a/beike/Services/StateMachineService.php +++ b/beike/Services/StateMachineService.php @@ -11,6 +11,7 @@ namespace Beike\Services; +use Throwable; use Beike\Models\Order; use Beike\Models\OrderHistory; @@ -18,6 +19,39 @@ class StateMachineService { private Order $order; private int $orderId; + private string $comment; + private bool $notify; + + const CREATED = 'created'; // 已创建 + const UNPAID = 'unpaid'; // 待支付 + const PAID = 'paid'; // 已支付 + const SHIPPED = 'shipped'; // 已发货 + const COMPLETED = 'completed'; // 已完成 + + const ORDER_STATUS = [ + self::CREATED, + self::UNPAID, + self::PAID, + self::SHIPPED, + self::COMPLETED, + ]; + + const MACHINES = [ + self::CREATED => [ + self::UNPAID => ['updateStatus', 'addHistory'], + self::PAID => ['updateStatus', 'addHistory', 'subStock'], + ], + self::UNPAID => [ + self::PAID => ['updateStatus', 'addHistory', 'subStock'], + ], + self::PAID => [ + self::SHIPPED => ['updateStatus', 'addHistory'], + self::COMPLETED => ['updateStatus', 'addHistory'] + ], + self::SHIPPED => [ + self::COMPLETED => ['updateStatus', 'addHistory',] + ] + ]; public function __construct(Order $order) { @@ -25,36 +59,172 @@ class StateMachineService $this->orderId = $order->id; } + public static function getInstance($order): self + { + return new self($order); + } /** - * @param $status - * @param string $comment - * @param false $notify - * @throws \Throwable + * 设置订单备注 + * @param $comment + * @return $this */ - public function changeStatus($status, string $comment = '', bool $notify = false) + public function setComment($comment): self { - $order = $this->order; + $this->comment = $comment; + return $this; + } - $this->createOrderHistory($status, $comment, $notify); - $order->status = $status; - $order->saveOrFail(); + /** + * 设置是否通知 + * @param $flag + * @return $this + */ + public function setNotify($flag): self + { + $this->notify = (bool)$flag; + return $this; } + /** + * 获取所有订单状态列表 + * + * @return array + * @throws \Exception + */ + public static function getAllStatuses(): array + { + $result = []; + $statuses = self::ORDER_STATUS; + foreach ($statuses as $status) { + if ($status == self::CREATED) { + continue; + } + $result[] = [ + 'status' => $status, + 'name' => trans($status) + ]; + } + return $result; + } + + /** + * 获取当前订单可以变为的状态 + * + * @return array + * @throws \Exception + */ + public function nextBackendStatuses(): array + { + $currentStatusCode = $this->order->status; + $nextStatus = self::MACHINES[$currentStatusCode] ?? []; + + if (empty($nextStatus)) { + return []; + } + $nextStatusCodes = array_keys($nextStatus); + $result = []; + foreach ($nextStatusCodes as $status) { + $result[$status] = [ + 'status' => $status, + 'name' => trans($status) + ]; + } + return $result; + } + /** * @param $status * @param string $comment - * @param false $notify + * @param bool $notify + * @throws \Exception + */ + public function changeStatus($status, string $comment = '', bool $notify = false) + { + $orderId = $this->orderId; + $order = $this->order; + $oldStatusCode = $order->status; + $newStatusCode = $status; + + $this->setComment($comment)->setNotify($notify); + + $this->validStatusCode($status); + $functions = $this->getFunctions($oldStatusCode, $newStatusCode); + if (empty($functions)) { + return; + } + foreach ($functions as $function) { + if (!method_exists($this, $function)) { + throw new \Exception("{$function} not exist in StateMachine!"); + } + $this->{$function}($oldStatusCode, $status); + } + } + + /** + * + * 检测当前订单是否可以变更为某个状态 + * + * @param $statusCode + * @throws \Exception + */ + private function validStatusCode($statusCode) + { + if (!in_array($statusCode, self::ORDER_STATUS)) { + $statusCodeString = implode(', ', self::ORDER_STATUS); + throw new \Exception("Invalid order status, must be one of the '{$statusCodeString}'"); + } + $orderId = $this->orderId; + $orderNumber = $this->order->number; + $currentStatusCode = $this->order->status; + + $nextStatusCodes = array_keys($this->nextBackendStatuses()); + if (!in_array($statusCode, $nextStatusCodes)) { + throw new \Exception("Order {$orderId}({$orderNumber}) is {$currentStatusCode}, cannot be changed to $statusCode"); + } + } + + /** + * 通过订单当前状态以及即将变为的状态获取需要触发的事件 + * + * @param $oldStatus + * @param $newStatus + * @return array + */ + private function getFunctions($oldStatus, $newStatus): array + { + return self::MACHINES["{$oldStatus}.{$newStatus}"] ?? []; + } + + + /** + * 更新订单状态 + * + * @param $oldCode + * @param $newCode * @throws \Throwable */ - private function createOrderHistory($status, string $comment = '', bool $notify = false) + private function updateStatus($oldCode, $newCode) + { + $this->order->status = $newCode; + $this->order->saveOrFail(); + } + + /** + * 添加更改记录 + * + * @param $oldCode + * @param $newCode + * @throws Throwable + */ + private function addHistory($oldCode, $newCode) { $history = new OrderHistory([ 'order_id' => $this->orderId, - 'status' => $status, - 'comment' => $comment, - 'notify' => $notify + 'status' => $newCode, + 'notify' => (int)$this->notify, + 'comment' => (string)$this->comment, ]); $history->saveOrFail(); }