Files
water_new/modules/Mall/Facades/Refund.php
2023-03-08 09:16:04 +08:00

251 lines
5.4 KiB
PHP

<?php
namespace Modules\Mall\Facades;
use Exception;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Facades\DB;
use Modules\Mall\Events\RefundApplied;
use Modules\Mall\Models\Order as OrderModel;
use Modules\Mall\Models\Refund as RefundModel;
class Refund
{
protected $user;
/**
* @var string
*/
protected string $remark;
/**
* @var array
*/
protected array $logs;
protected $refund;
protected $order;
protected $items;
protected $total;
/**
* @throws \Exception
*/
public function user($user): Refund
{
if ($user instanceof Authenticatable) {
$this->user = $user;
} else {
throw new Exception('非法用户');
}
return $this;
}
/**
* Notes: 订单
*
* @Author: 玄尘
* @Date : 2021/5/17 8:46
* @param OrderModel $order
* @return $this
*/
public function order(OrderModel $order): Refund
{
$this->order = $order;
return $this;
}
/**
* Notes:商品
*
* @Author: 玄尘
* @Date : 2021/5/17 8:46
* @param array $items
* @return Refund
*/
public function items(array $items): Refund
{
$this->items = $items;
return $this;
}
/**
* Notes: 退款金额
*
* @Author: 玄尘
* @Date : 2021/5/17 8:48
* @param float $total
* @return Refund
*/
public function total(float $total): Refund
{
$this->total = $total;
return $this;
}
/**
* Notes: 设置订单备注信息
*
* @Author: 玄尘
* @Date : 2021/5/21 10:31
* @param string $remark
* @return $this
*/
public function remark(string $remark): Refund
{
$this->remark = $remark;
return $this;
}
/**
* Notes: 退款日志
*
* @Author: 玄尘
* @Date : 2021/5/17 11:37
* @param $logs
* @return $this
*/
public function logs($logs): Refund
{
if (! isset($logs['remark']) && ! empty($this->remark)) {
$logs['remark'] = $this->remark;
}
$this->logs = $logs;
return $this;
}
/**
* Notes: 设置退款商品
*
* @Author: 玄尘
* @Date : 2021/5/17 8:51
*/
public function setItems(): Refund
{
$this->items = $this->order->items->map(function ($item) {
return [
'order_item_id' => $item->id,
'qty' => $item->qty,
];
});
return $this;
}
/**
* Notes: 创建退款单
*
* @Author: 玄尘
* @Date : 2021/5/17 8:49
* @return mixed
* @throws \Exception
*/
public function create()
{
if (! $this->order) {
throw new Exception('未设置订单');
}
if (empty($this->items)) {
$this->setItems();
}
if (! $this->order->can('refund')) {
throw new Exception('订单状态不可退款');
}
$maxAmount = 0;
$refundItems = [];
//判断最大可退数量
foreach ($this->items as $item) {
$orderItem = $this->order->items()->find($item['order_item_id']);
if (! $orderItem) {
throw new Exception('未找到可退商品');
}
if (! $orderItem->canRefund()) {
throw new \Exception('退款/货失败,此商品不可退款/货');
}
if ($item['qty'] <= 0) {
throw new Exception('【'.$orderItem->source['goods_name'].'】退货数量必须大于0');
}
if ($item['qty'] > $orderItem->qty) {
throw new Exception('【'.$orderItem->source['goods_name'].'】超过最大可退数量');
}
$maxAmount += $orderItem->price * $item['qty'];
$refundItems[] = new RefundItem($orderItem, $item['qty']);
}
// 自动计算退款金额
if (is_null($this->total)) {
$this->total = $maxAmount;
} elseif ($this->total > $maxAmount) {
throw new Exception('超过最大可退金额');
}
DB::transaction(function () use ($refundItems) {
$this->refund = $this->order->refunds()
->create([
'refund_total' => $this->total,
'actual_total' => 0,
'user_id' => $this->user->id,
'shop_id' => $this->order->shop_id,
'state' => RefundModel::REFUND_APPLY,
'remark' => $this->remark,
]);
foreach ($refundItems as $item) {
$this->refund->items()->create($item->toArray());
}
if ($this->logs) {
$this->createLog();
}
event(new RefundApplied($this->order, $this->refund));
});
return $this->refund;
}
/**
* Notes: 添加日志
*
* @Author: 玄尘
* @Date : 2020/12/11 11:43
*/
public function createLog()
{
$logs = $this->logs;
if ($this->user) {
$logs['userable_type'] = get_class($this->user);
$logs['userable_id'] = $this->user->id;
$logs['state'] = $this->refund->state;
}
$this->refund->logs()->create($logs);
}
}