306 lines
12 KiB
PHP
306 lines
12 KiB
PHP
<?php
|
|
|
|
namespace app\common\service;
|
|
|
|
use app\common\enum\OrderEnum;
|
|
use app\common\logic\CapitalFlowLogic;
|
|
use app\common\logic\CommissionnLogic;
|
|
use app\common\logic\StoreFinanceFlowLogic;
|
|
use app\common\model\store_branch_product\StoreBranchProduct;
|
|
use app\common\model\store_finance_flow\StoreFinanceFlow;
|
|
use app\common\model\store_finance_flow_product\StoreFinanceFlowProduct;
|
|
use app\common\model\store_order\StoreOrder;
|
|
use app\common\model\store_order_cart_info\StoreOrderCartInfo;
|
|
use app\common\model\system_store\SystemStore;
|
|
use app\common\model\user\User;
|
|
use app\common\service\pay\PayTool;
|
|
use Exception;
|
|
use support\exception\BusinessException;
|
|
use think\db\exception\DataNotFoundException;
|
|
use think\db\exception\DbException;
|
|
use think\db\exception\ModelNotFoundException;
|
|
use think\facade\Db;
|
|
|
|
class RefundOrderService
|
|
{
|
|
|
|
public function refund($userId, $params): void
|
|
{
|
|
Db::startTrans();
|
|
try {
|
|
$order = StoreOrder::where('id', $params['id'])->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);
|
|
}
|
|
|
|
} |