订单状态机
This commit is contained in:
parent
4b23f93884
commit
e221f3804f
|
|
@ -41,14 +41,16 @@ class OrderController extends Controller
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Order $order
|
* @param Order $order
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Order $order)
|
public function show(Request $request, Order $order)
|
||||||
{
|
{
|
||||||
$order->load(['orderTotals', 'orderHistories']);
|
$order->load(['orderTotals', 'orderHistories']);
|
||||||
$data = [
|
$data = [
|
||||||
'order' => $order,
|
'order' => $order,
|
||||||
|
'statuses' => StateMachineService::getInstance($order)->nextBackendStatuses()
|
||||||
];
|
];
|
||||||
|
dd($data);
|
||||||
return view('admin::pages.orders.form', $data);
|
return view('admin::pages.orders.form', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
namespace Beike\Services;
|
namespace Beike\Services;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
use Beike\Models\Order;
|
use Beike\Models\Order;
|
||||||
use Beike\Models\OrderHistory;
|
use Beike\Models\OrderHistory;
|
||||||
|
|
||||||
|
|
@ -18,6 +19,39 @@ class StateMachineService
|
||||||
{
|
{
|
||||||
private Order $order;
|
private Order $order;
|
||||||
private int $orderId;
|
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)
|
public function __construct(Order $order)
|
||||||
{
|
{
|
||||||
|
|
@ -25,36 +59,172 @@ class StateMachineService
|
||||||
$this->orderId = $order->id;
|
$this->orderId = $order->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getInstance($order): self
|
||||||
|
{
|
||||||
|
return new self($order);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $status
|
* 设置订单备注
|
||||||
* @param string $comment
|
* @param $comment
|
||||||
* @param false $notify
|
* @return $this
|
||||||
* @throws \Throwable
|
|
||||||
*/
|
*/
|
||||||
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 $status
|
||||||
* @param string $comment
|
* @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
|
* @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([
|
$history = new OrderHistory([
|
||||||
'order_id' => $this->orderId,
|
'order_id' => $this->orderId,
|
||||||
'status' => $status,
|
'status' => $newCode,
|
||||||
'comment' => $comment,
|
'notify' => (int)$this->notify,
|
||||||
'notify' => $notify
|
'comment' => (string)$this->comment,
|
||||||
]);
|
]);
|
||||||
$history->saveOrFail();
|
$history->saveOrFail();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue