507 lines
18 KiB
PHP
507 lines
18 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Admin\Services\OrderService;
|
||
use App\Exceptions\BizException;
|
||
use App\Models\AfterSale;
|
||
use App\Models\AfterSaleLog;
|
||
use App\Models\DistributionPreIncomeJob;
|
||
use App\Models\Order;
|
||
use App\Models\OrderProduct;
|
||
use App\Models\User;
|
||
|
||
class AfterSaleService
|
||
{
|
||
/**
|
||
* 创建售后单
|
||
*
|
||
* @param User $user
|
||
* @param OrderProduct $orderProduct
|
||
* @param integer $type
|
||
* @param integer $num
|
||
* @param array $params
|
||
* @return AfterSale
|
||
*/
|
||
public function create(User $user, OrderProduct $orderProduct, int $type, int $num, array $params): AfterSale
|
||
{
|
||
if (!$orderProduct->can_after_sale) {
|
||
throw new BizException('该订单商品无法发起售后');
|
||
}
|
||
|
||
//校验申请数量不能超过订单商品数量
|
||
if ($num > $orderProduct->quantity) {
|
||
throw new BizException('申请售后的数量不能大于订单商品数量');
|
||
}
|
||
|
||
if ($orderProduct->isGift() && in_array($params['type'], [AfterSale::TYPE_REFUND, Aftersale::TYPE_REFUND_AND_RETURN])) {
|
||
throw new BizException('赠品不能发起退款/退款退货操作');
|
||
}
|
||
|
||
if ($orderProduct->order->is_change && in_array($params['type'], [AfterSale::TYPE_REFUND, Aftersale::TYPE_REFUND_AND_RETURN])) {
|
||
throw new BizException('换货后的商品不能发起退款/退款退货操作');
|
||
}
|
||
|
||
$amount = ($num == $orderProduct->quantity) ? $orderProduct->total_amount : bcmul(bcdiv($orderProduct->total_amount, $orderProduct->quantity), $num);
|
||
|
||
if ($amount == 0 && in_array($params['type'], [AfterSale::TYPE_REFUND])) {
|
||
throw new BizException('实际支付金额为0的商品无法发起退款售后');
|
||
}
|
||
|
||
$afterSale = AfterSale::create(array_merge($params, [
|
||
'user_id' => $user->id,
|
||
'order_id' => $orderProduct->order_id,
|
||
'amount' => $amount,
|
||
'state' => AfterSale::STATE_VERIFY,
|
||
]));
|
||
|
||
$orderProduct->update([
|
||
'after_sale_state'=>1,
|
||
]);
|
||
|
||
return $afterSale;
|
||
}
|
||
|
||
/**
|
||
* 是否待审核
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @return boolean
|
||
*/
|
||
protected function isWaitVerify(AfterSale $afterSale)
|
||
{
|
||
return $afterSale->state == $afterSale::STATE_VERIFY;
|
||
}
|
||
|
||
/**
|
||
* 是否待补充资料
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @return boolean
|
||
*/
|
||
protected function isWaitApply(AfterSale $afterSale)
|
||
{
|
||
return $afterSale->state == $afterSale::STATE_APPLY;
|
||
}
|
||
|
||
/**
|
||
* 是否待确认
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @return boolean
|
||
*/
|
||
protected function isWaitAgree(AfterSale $afterSale)
|
||
{
|
||
return $afterSale->state == $afterSale::STATE_AGREE;
|
||
}
|
||
|
||
/**
|
||
* 是否待确认收货
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @return boolean
|
||
*/
|
||
protected function isWaitShipping(AfterSale $afterSale)
|
||
{
|
||
return $afterSale->state == $afterSale::STATE_SHIPPING;
|
||
}
|
||
|
||
/**
|
||
* 是否待打款
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @return boolean
|
||
*/
|
||
protected function isWaitFinance(AfterSale $afterSale)
|
||
{
|
||
return $afterSale->state == $afterSale::STATE_FINANCE;
|
||
}
|
||
|
||
/**
|
||
* 补充资料申请
|
||
*
|
||
* @param [AfterSale] $afterSale
|
||
* @param array $params
|
||
* @return AfterSale
|
||
*/
|
||
public function apply(AfterSale $afterSale, array $params): AfterSale
|
||
{
|
||
if ($this->isWaitApply($afterSale)) {
|
||
$afterSale->update(array_merge($params, [
|
||
'state' => AfterSale::STATE_VERIFY,
|
||
]));
|
||
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '补充资料',
|
||
'desc' => $afterSale->description,
|
||
'images' => $afterSale->images,
|
||
]);
|
||
return $afterSale;
|
||
} else {
|
||
throw new BizException('售后订单状态异常,请稍后再试');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 审核通过
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @param string $remarks
|
||
* @return void
|
||
*/
|
||
public function verify(AfterSale $afterSale, string $remarks, int $amount, ?int $num = null)
|
||
{
|
||
if ($this->isWaitVerify($afterSale)) {
|
||
switch ($afterSale->type) {
|
||
case AfterSale::TYPE_REFUND_AND_RETURN:
|
||
$afterSale->update([
|
||
'num' => $num,
|
||
'amount' => $amount,
|
||
'state' => $afterSale::STATE_AGREE,
|
||
'remarks' => $remarks,
|
||
]);
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '客服审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
break;
|
||
case AfterSale::TYPE_REFUND:
|
||
$afterSale->update([
|
||
'num' => $num,
|
||
'amount' => $amount,
|
||
'state' => $afterSale::STATE_AGREE,
|
||
'remarks' => $remarks,
|
||
]);
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '客服审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
break;
|
||
case AfterSale::TYPE_CHANGE:
|
||
$afterSale->update([
|
||
'num' => $num,
|
||
'amount' => $amount,
|
||
'state' => $afterSale::STATE_AGREE,
|
||
'remarks' => $remarks,
|
||
]);
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '客服审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
break;
|
||
case AfterSale::TYPE_FILL:
|
||
$afterSale->update([
|
||
'num' => $num,
|
||
'amount' => $amount,
|
||
'state' => $afterSale::STATE_AGREE,
|
||
'remarks' => $remarks,
|
||
]);
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '客服审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
break;
|
||
}
|
||
} else {
|
||
throw new BizException('该售后订单状态异常');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 补充资料
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @param string $remarks
|
||
* @return void
|
||
*/
|
||
public function backApply(AfterSale $afterSale, string $remarks)
|
||
{
|
||
if ($this->isWaitVerify($afterSale)) {
|
||
$afterSale->update([
|
||
'state' => $afterSale::STATE_APPLY,
|
||
'remarks' => $remarks,
|
||
]);
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '客服审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
} else {
|
||
throw new BizException('该售后订单状态异常');
|
||
}
|
||
}
|
||
|
||
public function agree(AfterSale $afterSale, array $params, $remarks = '用户已同意客服审核结果')
|
||
{
|
||
if ($this->isWaitAgree($afterSale)) {
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '客户确认',
|
||
'desc' => $remarks,
|
||
]);
|
||
switch ($afterSale->type) {
|
||
case AfterSale::TYPE_REFUND_AND_RETURN:
|
||
$afterSale->update([
|
||
'tracking_number'=>$params['tracking_number'],
|
||
'remarks'=> $remarks,
|
||
'state' => AfterSale::STATE_SHIPPING,
|
||
]);
|
||
break;
|
||
case AfterSale::TYPE_REFUND://退款订单
|
||
$afterSale->update([
|
||
'remarks'=> $remarks,
|
||
'state' => AfterSale::STATE_FINANCE,
|
||
]);
|
||
break;
|
||
case AfterSale::TYPE_CHANGE:
|
||
$afterSale->update([
|
||
'tracking_number'=>$params['tracking_number'],
|
||
'remarks' => $remarks,
|
||
'state' => AfterSale::STATE_SHIPPING,
|
||
]);
|
||
break;
|
||
case AfterSale::TYPE_FILL:
|
||
$afterSale->update([
|
||
'remarks' => $remarks,
|
||
'state' => AfterSale::STATE_SHIPPING,
|
||
]);
|
||
break;
|
||
}
|
||
return $afterSale;
|
||
} else {
|
||
throw new BizException('售后订单状态异常,请稍后再试');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 物流拒绝确认收货
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @param string $remarks
|
||
* @return void
|
||
*/
|
||
public function shippingFail(AfterSale $afterSale, $remarks = '仓库验收未通过')
|
||
{
|
||
if ($this->isWaitShipping($afterSale)) {
|
||
$afterSale->update([
|
||
'state' => $afterSale::STATE_VERIFY,
|
||
'remarks' => $remarks,
|
||
]);
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '仓库审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
} else {
|
||
throw new BizException('该售后订单状态异常');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 物流补货
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @param string $remarks
|
||
* @return void
|
||
*/
|
||
public function shippingFill(AfterSale $afterSale, $remarks)
|
||
{
|
||
$remarks = '补货完成,新的物流单号:'.$remarks;
|
||
if ($this->isWaitShipping($afterSale)) {
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '仓库审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
$afterSale->update([
|
||
'state' => $afterSale::STATE_FINISH,
|
||
'remarks' => $remarks,
|
||
]);
|
||
} else {
|
||
throw new BizException('该售后订单状态异常');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 物流确认收货
|
||
*
|
||
* @param AfterSale $afterSale
|
||
* @param string $remarks
|
||
* @return void
|
||
*/
|
||
public function shipping(AfterSale $afterSale, $remarks = '仓库验收通过')
|
||
{
|
||
if ($this->isWaitShipping($afterSale)) {
|
||
$afterSale->update([
|
||
'state' => $afterSale::STATE_FINANCE,
|
||
'remarks' => $remarks,
|
||
]);
|
||
AfterSaleLog::create([
|
||
'after_sale_id' => $afterSale->id,
|
||
'name' => '仓库审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
} else {
|
||
throw new BizException('该售后订单状态异常');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 财务确认退款
|
||
*
|
||
* @return void
|
||
*/
|
||
public function finance(AfterSale $afterSale, $remarks = '退款成功')
|
||
{
|
||
if ($this->isWaitFinance($afterSale)) {
|
||
$order = $afterSale->order;
|
||
$afterSaleProduct = $afterSale->orderProduct;
|
||
|
||
// 售后变更的销售值
|
||
$salesValue = '0';
|
||
|
||
if (in_array($afterSale->type, [AfterSale::TYPE_REFUND_AND_RETURN, AfterSale::TYPE_REFUND])) {
|
||
if ($afterSaleProduct->total_amount > 0) {
|
||
// 总销售值
|
||
$totalSalesValue = bcmul($afterSaleProduct->sales_value, $afterSaleProduct->quantity, 2);
|
||
// 售后变更金额
|
||
$amount = $afterSale->amount;
|
||
|
||
if ($amount >= $afterSaleProduct->total_amount) {
|
||
$amount = $afterSaleProduct->total_amount;
|
||
}
|
||
|
||
$changeSalesValue = bcmul($totalSalesValue, $amount, 2);
|
||
$changeSalesValue = bcdiv($changeSalesValue, $afterSaleProduct->total_amount, 3);
|
||
// 四舍五入(保留两位小数)
|
||
$salesValue = round($changeSalesValue, 2);
|
||
} else {
|
||
$qty = $afterSale->num;
|
||
|
||
if ($qty > $afterSaleProduct->quantity) {
|
||
$qty = $afterSaleProduct->quantity;
|
||
}
|
||
|
||
$salesValue = bcmul($afterSaleProduct->sales_value, $qty, 2);
|
||
}
|
||
|
||
//执行实际退款操作;
|
||
if ($afterSale->amount > 0) {//退款金额大于0才做实际退款
|
||
$order->refundLogs()->create([
|
||
'sn' => serial_number(),
|
||
'after_sale_id' => $afterSale->id,
|
||
'amount' => $afterSale->amount,
|
||
'reason' => '售后退款',
|
||
]);
|
||
}
|
||
} elseif ($afterSale->isChange()) {//换货流程
|
||
$qty = $afterSale->num;
|
||
|
||
if ($qty > $afterSaleProduct->quantity) {
|
||
$qty = $afterSaleProduct->quantity;
|
||
}
|
||
|
||
$salesValue = bcmul($afterSaleProduct->sales_value, $qty, 2);
|
||
}
|
||
$afterSale->logs()->create([
|
||
'name' => '财务审核',
|
||
'desc' => $remarks,
|
||
]);
|
||
|
||
$afterSale->update([
|
||
'sales_value' => $salesValue,
|
||
'state' => AfterSale::STATE_FINISH,
|
||
'remarks' => $remarks,
|
||
]);
|
||
|
||
// 1.先扣除预收益(可能会将店铺降级为粉丝)
|
||
// 2.生成分销任务
|
||
// 3.生成新订单
|
||
|
||
// 非赠品售后单,且售后单类型是换货、退款、退款退货
|
||
if (! $afterSaleProduct->isGift()
|
||
&& in_array($afterSale->type, [
|
||
AfterSale::TYPE_REFUND_AND_RETURN,
|
||
AfterSale::TYPE_REFUND,
|
||
AfterSale::TYPE_CHANGE,
|
||
])
|
||
) {
|
||
DistributionPreIncomeJob::create([
|
||
'jobable_id' => $afterSale->id,
|
||
'jobable_type' => $afterSale->getMorphClass(),
|
||
'remarks' => $afterSale->isChange() ? '订单换货' : '订单退货',
|
||
]);
|
||
}
|
||
|
||
// 如果是换货单
|
||
if ($afterSale->isChange()) {
|
||
// 如果订单享受了会员折扣,则需计算会员折扣
|
||
$vipDiscountAmount = 0;
|
||
|
||
if ($afterSaleProduct->vip_discount_amount > 0) {
|
||
$vipDiscountAmount = bcmul(($afterSaleProduct->sell_price - $afterSaleProduct->vip_price), $qty);
|
||
}
|
||
|
||
//复制一个订单(存商品价格,支付价格为0;)
|
||
$changeOrder = new Order();
|
||
$changeOrder->user_id = $order->user_id;
|
||
$changeOrder->sn = serial_number();
|
||
$changeOrder->products_total_amount = bcmul($afterSaleProduct->sell_price, $afterSale->num);
|
||
$changeOrder->coupon_discount_amount = 0;
|
||
$changeOrder->vip_discount_amount = $vipDiscountAmount;
|
||
$changeOrder->reduced_amount = 0;
|
||
$changeOrder->shipping_fee = 0;
|
||
$changeOrder->total_amount = 0;
|
||
$changeOrder->sales_value = $afterSale->sales_value;
|
||
|
||
// 收货地址
|
||
$changeOrder->consignee_name = $order->consignee_name;
|
||
$changeOrder->consignee_telephone = $order->consignee_telephone;
|
||
$changeOrder->consignee_zone = $order->consignee_zone;
|
||
$changeOrder->consignee_address = $order->consignee_address;
|
||
|
||
//标记是换货单
|
||
$changeOrder->is_change = true;
|
||
$changeOrder->save();
|
||
|
||
OrderProduct::create([
|
||
'user_id' => $changeOrder->user_id,
|
||
'order_id' => $changeOrder->id,
|
||
'is_gift' => $afterSaleProduct->is_gift,
|
||
'activity_id' => $afterSaleProduct->activity_id,
|
||
'gift_for_sku_id' => $afterSaleProduct->gift_for_sku_id,
|
||
'spu_id' => $afterSaleProduct->spu_id,
|
||
'sku_id' => $afterSaleProduct->sku_id,
|
||
'category_id' => $afterSaleProduct->category_id,
|
||
'name' => $afterSaleProduct->name,
|
||
'specs' => $afterSaleProduct->specs,
|
||
'cover' => $afterSaleProduct->cover,
|
||
'weight' => $afterSaleProduct->weight,
|
||
'sell_price' => $afterSaleProduct->sell_price,
|
||
'vip_price' => $afterSaleProduct->vip_price,
|
||
'sales_value' => $afterSaleProduct->sales_value,
|
||
'quantity' => $afterSale->num,
|
||
'remain_quantity'=> $afterSale->num,
|
||
'coupon_discount_amount'=> 0,
|
||
'vip_discount_amount' => $vipDiscountAmount,
|
||
'reduced_amount' => 0,
|
||
'total_amount' => $afterSale->amount,
|
||
]);
|
||
|
||
$orderService = new OrderService();
|
||
$orderService->adminPay($changeOrder);//支付该订单
|
||
$changeOrder->update([
|
||
'shipping_state' => Order::SHIPPING_STATE_PROCESSING,
|
||
]);
|
||
}
|
||
} else {
|
||
throw new BizException('该售后订单状态异常');
|
||
}
|
||
}
|
||
}
|