where('uid', $userId)->find(); if (empty($order)) { throw new BusinessException('订单不存在'); } if (!$order->allowRefund()) { throw new BusinessException('订单不能退款'); } $orderCartInfoWhere = ['oid' => $order['id']]; $refundNum = 0; if (!empty($params['old_cart_id'])) { $orderCartInfoWhere['id'] = $params['old_cart_id']; $refundNum = count($params['old_cart_id']); } if (!empty($params['product_arr'])) { $orderCartInfoWhere['product_id'] = array_column($params['product_arr'], 'product_id'); $refundNum = count($params['product_arr']); } $orderCartProducts = StoreOrderCartInfo::where($orderCartInfoWhere)->select(); if (isset($params['refund_price'])) { $refundAmount = $params['refund_price']; } else { $refundAmount = $this->calculate($orderCartProducts); } if (bcadd($order->refund_price, $refundAmount, 2) > $order->pay_price) { throw new BusinessException('退款金额错误'); } // if ($order->status == 2 && $order->is_writeoff == 1) { // $this->refundStoreMoney($order, $refundAmount); // $this->refundCommission($order); // } $productInfo = reset_index($params['product_arr'] ?? [], 'product_id'); $this->refundMoney($order, $refundAmount); $this->updateProductStock($orderCartProducts, $productInfo); $this->updateOrderCartInfo($order, $orderCartProducts, $refundAmount, $productInfo); $this->updateOrderStatus($order, $refundAmount, $refundNum); $this->resetStoreFinanceFlow($order, $orderCartProducts, $productInfo); // if ($order->status == 2 && $order->is_writeoff == 1) { // $this->financeSettle($order); // } Db::commit(); } catch (Exception $e) { Db::rollback(); throw new BusinessException($e->getMessage()); } } /** * 计算退款金额 * @param $orderCartProducts * @return string */ public function calculate($orderCartProducts): string { $amount = '0.00'; foreach ($orderCartProducts as $orderCartProduct) { $amount = bcadd($amount, $orderCartProduct['total_price'], 2); } return $amount; } /** * 资金原路退回 * @param $order * @param $refundAmount * @return void */ public function refundMoney($order, $refundAmount): void { $payTool = PayTool::getInstance($order['pay_type']); $payTool->refund($refundAmount, $order); } /** * 更新商品库存 * @param $orderCartProducts * @param $productInfo * @throws Exception */ public function updateProductStock($orderCartProducts, $productInfo = []): void { $updateData = []; foreach ($orderCartProducts as $product) { if (empty($productInfo[$product['product_id']]['cart_num'])) { continue; } $number = $productInfo[$product['product_id']]['cart_num']; $storeBranchProductId = StoreBranchProduct::where('store_id', $product['store_id']) ->where('product_id', $product['product_id']) ->withTrashed()->value('id'); if ($storeBranchProductId) { $updateData[] = [ 'id' => $storeBranchProductId, 'stock' => ['inc', $number], 'sales' => ['dec', $number], ]; } } (new StoreBranchProduct())->saveAll($updateData); } /** * 更新订单商品状态 * @param $order * @param $orderCartIds * @param $productInfo * @return void * @throws DbException */ public function updateOrderCartInfo($order, $orderCartProducts, $refundAmount, $productInfo = []): void { if (!empty($productInfo)) { foreach ($orderCartProducts as $orderCartProduct) { $product = $productInfo[$orderCartProduct['product_id']] ?? []; if (empty($product)) { continue; } $cartRefundAmount = min($refundAmount, $orderCartProduct['total_price']); $refundAmount = bcsub($refundAmount, $cartRefundAmount, 2); $attrs = ['refund_num' => ['inc', $product['cart_num']]]; if ($cartRefundAmount > 0) { $attrs['refund_amount'] = ['inc', $cartRefundAmount]; } if ($cartRefundAmount == $orderCartProduct['total_price']) { $attrs['status'] = 2; } StoreOrderCartInfo::where('oid', $order['id'])->where('product_id', $product['product_id'])->update($attrs); } } else { $updateData = []; foreach ($orderCartProducts as $orderCartProduct) { if ($refundAmount <= 0) { break; } $updateData[] = [ 'id' => $orderCartProduct['id'], 'refund_amount' => ['inc', min($orderCartProduct['total_price'], $refundAmount)], 'status' => 2 ]; $refundAmount = bcsub($refundAmount, $orderCartProduct['total_price'], 2); } (new StoreOrderCartInfo())->saveAll($updateData); } } /** * 更新订单状态 * @param $order * @param $refundAmount * @param $refundNum * @return void * @throws DbException */ public function updateOrderStatus($order, $refundAmount, $refundNum): void { $order->refund_price = bcadd($order['refund_price'], $refundAmount, 2); $order->refund_num += $refundNum; if ($order->pay_price == $order->refund_price) { // 全部退款完成,订单状态改为已退款 $order->refund_status = OrderEnum::REFUND_STATUS_FINISH; $order->status = OrderEnum::RECEIVED_BACK; } $order->save(); } /** * 退佣金 * @param $order * @param $storeOrderProducts * @param $productInfo * @return void * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function resetStoreFinanceFlow($order, $storeOrderProducts, $productInfo): void { foreach ($storeOrderProducts as $storeOrderProduct) { $refundInfo = $productInfo[$storeOrderProduct['product_id']] ?? []; $arr = StoreFinanceFlowProduct::where('oid', $order['id'])->where('product_id', $storeOrderProduct['product_id'])->select()->toArray(); foreach ($arr as $value) { if (!empty($refundInfo['cart_num'])) { $value['cart_num'] = $storeOrderProduct['cart_num'] - $refundInfo['cart_num']; } else { $value['cart_num'] = 0; } $value['total_price'] = bcmul($value['cart_num'], $value['price'], 2); $value['number'] = bcmul($value['total_price'], $value['rate'], 2); StoreFinanceFlowProduct::where('id', $value['id'])->update(['delete_time' => time()]); unset($value['id']); $value['create_time'] = strtotime($value['create_time']); $value['update_time'] = strtotime($value['update_time']); StoreFinanceFlowProduct::create($value); } } $productIds = array_unique(array_column($storeOrderProducts->toArray(), 'product_id')); StoreFinanceFlowProduct::where('oid', $order['id'])->whereIn('product_id', $productIds)->update(['number' => 0, 'update_time' => strtotime(time())]); $village_uid = StoreFinanceFlow::where('order_id', $order['id'])->where('financial_type', 14)->value('other_uid'); $brigade_uid = StoreFinanceFlow::where('order_id', $order['id'])->where('financial_type', 15)->value('other_uid'); $transaction_id = StoreFinanceFlow::where('order_id', $order['id'])->value('transaction_id'); StoreFinanceFlow::where('order_id', $order['id'])->update(['delete_time' => time()]); CommissionnLogic::setStore($order, $village_uid, $brigade_uid, $transaction_id); } /** * 扣除店铺余额和押金 * @param $order * @param $refundAmount * @return void * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function refundStoreMoney($order, $refundAmount): void { $margin = StoreFinanceFlow::where('order_id', $order['id'])->where('financial_type', OrderEnum::ORDER_MARGIN)->value('number'); $income = StoreFinanceFlow::where('order_id', $order['id'])->where('financial_type', OrderEnum::MERCHANT_ORDER_OBTAINS)->value('number'); if (empty($margin) && empty($income)) { return; } $store = SystemStore::where('id', $order['store_id'])->find(); if ($margin > 0) { $margin = min($margin, $refundAmount); $refundAmount = bcsub($refundAmount, $margin, 2); $store->paid_deposit = bcsub($store->paid_deposit, $margin, 2); } if ($income > 0 && $refundAmount > 0) { $income = min($income, $refundAmount); $store->store_money = bcsub($store->store_money, $income, 2); } $store->save(); } /** * 退佣金 * @param $order * @return void * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function refundCommission($order) { $list = StoreFinanceFlow::where(['order_id' => $order['id'], 'financial_pm' => 1, 'status' => 0])->where('other_uid', '>', 0)->select(); foreach ($list as $v) { $v->save(['status' => 1]); $find = User::where('id', $v['other_uid'])->find(); $capitalFlowDao = new CapitalFlowLogic($find); $capitalFlowDao->userExpense('system_balance_sub', 'order', $order['id'], $v['number']); $find->dec('now_money', $v['number'])->update(); } } /** * 财务结算 * @param $order * @return void * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function financeSettle($order) { $financeFlowLogic = new StoreFinanceFlowLogic(); $financeFlow = new StoreFinanceFlow(); $select_1 = $financeFlow->where(['order_id' => $order['id'], 'financial_pm' => 1, 'status' => 0])->where('other_uid', '>', 0)->select(); foreach ($select_1 as $v) { if ($v['other_uid'] > 0) { $financeFlowLogic->updateStatusUser($v['id'], $v['other_uid'], $v['number'], $v['order_id']); } } $deposit = $financeFlow->where(['order_id' => $order['id'], 'financial_pm' => 0, 'financial_type' => 11, 'status' => 0])->value('number') ?? 0; $money = $financeFlow->where(['order_id' => $order['id'], 'financial_pm' => 1, 'financial_type' => 2, 'status' => 0])->value('number') ?? 0; $financeFlowLogic->updateStatusStore($order['id'], $order['store_id'], $money, $deposit); } }