订单状态机
This commit is contained in:
parent
4b23f93884
commit
e221f3804f
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue