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 ($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 (bccomp($afterSale->sales_value, '0', 2) === 1) { $order->user->userInfo->incrPreGrowthValue(bcmul($afterSale->sales_value, '-1', 2)); } // 非赠品售后单,且售后单类型是换货、退款、退款退货 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, '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('该售后订单状态异常'); } } }