shish 1 dzień temu
rodzic
commit
e88efde6d2

+ 18 - 6
app-ghs/controllers/OrderController.php

@@ -1777,16 +1777,28 @@ class OrderController extends BaseController
         $shopAdminId = $this->shopAdminId;
         $shopAdminId = $this->shopAdminId;
         $shopAdminName = $shopAdmin->name ?? '';
         $shopAdminName = $shopAdmin->name ?? '';
 
 
+        //售后转冲销单场景(带relateOrderId/refundOrderId)本质是在做"售后退款审批",
+        //权限口径与老的 /refund/create-order、/refund/pass 保持一致,只有超管能操作;
+        //不带这两个参数的是"直接开冲销单"(selectCustom->index2->affirmForward),维持原有权限不变。ssh 冲销单功能
+        if (!empty($post['relateOrderId']) || !empty($post['refundOrderId'])) {
+            if (isset($shopAdmin->super) == false || $shopAdmin->super != 1) {
+                util::fail('超管才能操作退款');
+            }
+        }
+
         //防止连点/重复提交
         //防止连点/重复提交
         util::checkRepeatCommit('forward_' . $this->shopId . '_' . $this->adminId . '_' . $customId, 3);
         util::checkRepeatCommit('forward_' . $this->shopId . '_' . $this->adminId . '_' . $customId, 3);
 
 
-        $productJson = $post['product'] ?? '';
-        $productList = is_string($productJson) ? json_decode($productJson, true) : $productJson;
-        if (empty($productList)) {
-            util::fail('请选择花材');
+        //refundOrderId 场景由 OrderService::createForwardOrder 内部按售后申请明细自动生成商品列表,
+        //不需要前端再传product(也不信任前端在这个场景下传的商品,避免和售后申请不一致)
+        if (empty($post['refundOrderId'])) {
+            $productJson = $post['product'] ?? '';
+            $productList = is_string($productJson) ? json_decode($productJson, true) : $productJson;
+            if (empty($productList)) {
+                util::fail('请选择花材');
+            }
+            $post['product'] = $productList;
         }
         }
-
-        $post['product'] = $productList;
         $post['sjId'] = $this->sjId;
         $post['sjId'] = $this->sjId;
         $post['shopId'] = $this->shopId;
         $post['shopId'] = $this->shopId;
         $post['mainId'] = $this->mainId;
         $post['mainId'] = $this->mainId;

+ 11 - 0
app-ghs/controllers/RefundController.php

@@ -562,6 +562,17 @@ class RefundController extends BaseController
             util::fail('数据出错了');
             util::fail('数据出错了');
         }
         }
         $refund['relateOrderId'] = $order->id;
         $refund['relateOrderId'] = $order->id;
+        //补充原单信息,供前端判断该售后是否要走"转冲销单"(非当天单/欠款已结清),
+        //以及转冲销单弹框里只读展示原单支付渠道。ssh 冲销单功能
+        $refund['orderInfo'] = [
+            'id' => $order->id,
+            'payTime' => $order->payTime,
+            'debtPrice' => $order->debtPrice,
+            'remainDebtPrice' => $order->remainDebtPrice,
+            'actPrice' => $order->actPrice,
+            'forwardPrice' => $order->forwardPrice,
+            'payWay' => $order->payWay,
+        ];
 
 
         if (!empty($imgString)) {
         if (!empty($imgString)) {
             $imgArr = json_decode($imgString, true);
             $imgArr = json_decode($imgString, true);

+ 2 - 0
biz-ghs/custom/classes/CustomClass.php

@@ -1269,6 +1269,7 @@ class CustomClass extends BaseClass
      */
      */
     public static function forwardReturnBalance($custom, $forwardOrder, $returnAmount)
     public static function forwardReturnBalance($custom, $forwardOrder, $returnAmount)
     {
     {
+        AccountMoneyClass::ensureCustomMoneyReady($custom, true);
         if (bccomp($returnAmount, '0', 2) <= 0) {
         if (bccomp($returnAmount, '0', 2) <= 0) {
             return $custom->balance ?? '0.00';
             return $custom->balance ?? '0.00';
         }
         }
@@ -1279,6 +1280,7 @@ class CustomClass extends BaseClass
         if (empty($ghs)) {
         if (empty($ghs)) {
             util::fail('没有找到供货商信息,无法返充余额');
             util::fail('没有找到供货商信息,无法返充余额');
         }
         }
+        AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
 
 
         $newBalance = bcadd($custom->balance ?? '0.00', $returnAmount, 2);
         $newBalance = bcadd($custom->balance ?? '0.00', $returnAmount, 2);
         $custom->balance = $newBalance;
         $custom->balance = $newBalance;

+ 8 - 0
biz-ghs/order/classes/RefundOrderClass.php

@@ -2,6 +2,7 @@
 
 
 namespace bizGhs\order\classes;
 namespace bizGhs\order\classes;
 
 
+use biz\ghs\classes\GhsClass;
 use biz\shop\classes\ShopCapitalClass;
 use biz\shop\classes\ShopCapitalClass;
 use biz\shop\classes\ShopClass;
 use biz\shop\classes\ShopClass;
 use biz\shop\classes\ShopExtClass;
 use biz\shop\classes\ShopExtClass;
@@ -256,6 +257,13 @@ class RefundOrderClass extends BaseClass
         $custom->buyAmount = $buyAmount;
         $custom->buyAmount = $buyAmount;
         $custom->save();
         $custom->save();
 
 
+        // xhGhs.expendAmount 是 xhGhsCustom.buyAmount 的镜像字段(花店侧视角的累计消费),售后退款同步扣减
+        $ghs = GhsClass::getLockById($custom->ghsId ?? 0);
+        if (!empty($ghs)) {
+            $ghs->expendAmount = bcsub($ghs->expendAmount ?? '0.00', $refundPrice, 2);
+            $ghs->save(false, ['expendAmount']);
+        }
+
 
 
         if ($onlinePay == dict::getDict('onlinePay', 'yes')) {
         if ($onlinePay == dict::getDict('onlinePay', 'yes')) {
             //退款流程
             //退款流程

+ 60 - 1
biz-ghs/order/services/OrderService.php

@@ -22,6 +22,8 @@ use bizGhs\order\classes\OrderExpressClass;
 use bizGhs\order\classes\OrderForwardClass;
 use bizGhs\order\classes\OrderForwardClass;
 use bizGhs\order\classes\OrderItemClass;
 use bizGhs\order\classes\OrderItemClass;
 use bizGhs\order\classes\OrderSendClass;
 use bizGhs\order\classes\OrderSendClass;
+use bizGhs\order\classes\RefundOrderClass;
+use bizGhs\order\classes\RefundOrderItemClass;
 use bizGhs\product\classes\ProductClass;
 use bizGhs\product\classes\ProductClass;
 use bizGhs\shop\classes\MainClass;
 use bizGhs\shop\classes\MainClass;
 use bizGhs\shop\classes\ShopMoneyChangeClass;
 use bizGhs\shop\classes\ShopMoneyChangeClass;
@@ -1033,7 +1035,46 @@ class OrderService extends BaseService
         $shopAdminName = $post['shopAdminName'] ?? '';
         $shopAdminName = $post['shopAdminName'] ?? '';
         $ghsId = $custom['ghsId'] ?? 0;
         $ghsId = $custom['ghsId'] ?? 0;
 
 
-        $productList = $post['product'] ?? [];
+        //售后申请审核转冲销单场景:refundOrderId 是待审核的售后申请(xhRefund)id,
+        //由 refundDetail.vue"通过"弹框直接提交而来,商品明细以售后申请里已提交的为准(不信任前端重新传的product),
+        //避免和客户/花店实际申请的售后商品不一致;这里锁行是因为最后要把它标记为"已通过"。ssh 冲销单功能
+        $refundOrderId = $post['refundOrderId'] ?? 0;
+        $refundOrder = null;
+        if (!empty($refundOrderId)) {
+            $refundOrder = RefundOrderClass::getLockById($refundOrderId);
+            if (empty($refundOrder)) {
+                util::fail('没有找到售后申请');
+            }
+            if ($refundOrder->mainId != $mainId) {
+                util::fail('售后申请信息不匹配');
+            }
+            if ($refundOrder->status != 0) {
+                util::fail('该售后申请已被处理,请刷新页面');
+            }
+            if ($refundOrder->customId != $customId) {
+                util::fail('售后申请客户信息不匹配');
+            }
+
+            $relateOrderSnFromRefund = $refundOrder->relateOrderSn ?? '';
+            $relateOrderFromRefund = OrderClass::getByCondition(['orderSn' => $relateOrderSnFromRefund], true);
+            if (empty($relateOrderFromRefund)) {
+                util::fail('没有找到售后申请关联的原订单');
+            }
+            $post['relateOrderId'] = $relateOrderFromRefund->id;
+
+            $refundItems = RefundOrderItemClass::getAllByCondition(['orderSn' => $refundOrder->orderSn], null, '*');
+            $productList = [];
+            foreach ($refundItems as $refundItem) {
+                $productList[] = [
+                    'productId' => $refundItem['productId'] ?? 0,
+                    'bigNum' => ($refundItem['xhUnitType'] ?? 0) == 0 ? ($refundItem['xhNum'] ?? 0) : 0,
+                    'smallNum' => ($refundItem['xhUnitType'] ?? 0) == 1 ? ($refundItem['xhNum'] ?? 0) : 0,
+                    'price' => $refundItem['xhUnitPrice'] ?? 0,
+                ];
+            }
+        } else {
+            $productList = $post['product'] ?? [];
+        }
         if (empty($productList)) {
         if (empty($productList)) {
             util::fail('请选择花材');
             util::fail('请选择花材');
         }
         }
@@ -1322,6 +1363,24 @@ class OrderService extends BaseService
             }
             }
         }
         }
 
 
+        //售后申请审核转冲销单:这条售后申请本身并没有走老的 passRefund 流程(没有原路退款/没有改原订单actPrice等),
+        //真正的退款/退货/返余额是由上面新生成的这张冲销单完成的,所以不能标"已通过"(会让人误以为是走了老流程原路退款)。
+        //这里标"已取消",并把冲销单号写进 hdRemark 备注,方便后续排查这条售后申请最终去了哪。ssh 冲销单功能
+        if (!empty($refundOrder)) {
+            $refundOrder->status = RefundOrderClass::STATUS_CANCEL;
+            $refundOrder->hdRemark = '已转为冲销单处理,退款/退货/返余额流程详见冲销单:' . $orderSn;
+            $refundOrder->shopAdminId = $shopAdminId;
+            $refundOrder->shopAdminName = $shopAdminName;
+            $refundOrder->save(false, ['status', 'hdRemark', 'shopAdminId', 'shopAdminName']);
+
+            //明细项同步标记为已处理,避免和"待处理"的正常售后混在一起统计
+            $refundItemModels = RefundOrderItemClass::getAllByCondition(['orderSn' => $refundOrder->orderSn], null, '*', null, true);
+            foreach ($refundItemModels as $refundItemModel) {
+                $refundItemModel->status = 1;
+                $refundItemModel->save(false, ['status']);
+            }
+        }
+
         return ['order' => $order, 'customBalance' => $customBalance];
         return ['order' => $order, 'customBalance' => $customBalance];
     }
     }