6
0
Fork 0
jiqu-library-server/app/Services/AfterSaleService.php

491 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?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('赠品不能发起退款/退款退货操作');
}
$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)
{
if ($this->isWaitVerify($afterSale)) {
switch ($afterSale->type) {
case AfterSale::TYPE_REFUND_AND_RETURN:
$afterSale->update([
'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([
'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([
'state' => $afterSale::STATE_AGREE,
'remarks' => $remarks,
]);
AfterSaleLog::create([
'after_sale_id' => $afterSale->id,
'name' => '客服审核',
'desc' => $remarks,
]);
break;
case AfterSale::TYPE_FILL:
$afterSale->update([
'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 (in_array($afterSale->type, [AfterSale::TYPE_CHANGE])) {//换货流程
$qty = $afterSale->num;
if ($qty > $afterSaleProduct->quantity) {
$qty = $afterSaleProduct->quantity;
}
$salesValue = bcmul($afterSaleProduct->sales_value, $qty, 2);
$vipDiscountAmount = 0;
// 如果订单享受了会员折扣,则需计算会员折扣
if ($afterSaleProduct->vip_discount_amount > 0) {
$vipDiscountAmount = bcmul(($afterSaleProduct->sell_price-$afterSaleProduct->vip_price), $afterSale->num);
}
//复制一个订单存商品价格支付价格为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 = $salesValue;
// 收货地址
$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,
'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,
]);
}
$afterSale->logs()->create([
'name' => '财务审核',
'desc' => $remarks,
]);
$afterSale->update([
'sales_value' => $salesValue,
'state' => AfterSale::STATE_FINISH,
'remarks' => $remarks,
]);
// 非赠品售后单,且售后单类型是换货、退款、退款退货
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 (bccomp($afterSale->sales_value, '0', 2) === 1) {
$order->user->userInfo->incrPreGrowthValue(bcmul($afterSale->sales_value, '-1', 2));
}
} else {
throw new BizException('该售后订单状态异常');
}
}
}