Просмотр исходного кода

Merge branch 'after-sale' into dev

shish 8 часов назад
Родитель
Сommit
d8ea304b47

+ 3 - 0
app-ghs/controllers/ConsoleController.php

@@ -240,6 +240,7 @@ class ConsoleController extends BaseController
             ["name" => "收款流水", "img" => "ghs/home/kcyjs.png", "url" => "/admin/order/scanPay"],
             // 无原单退款:选客户→选花材→生成 sameDay=0 退款单(不关联销售单)
             ["name" => "退款", "img" => "ghs/home/icon_caigou.png", "url" => "/admin/custom/selectCustom?style=1&refund=1"],
+            ["name" => "退款记录", "img" => "ghs/home/icon_caigou.png", "url" => "/admin/billing/freeRefundList"],
             ["name" => "公告", "img" => "ghs/home/icon_caigou.png", "url" => "/admin/ghsNotice/list"],
         ];
         $menuV3 = [
@@ -264,6 +265,7 @@ class ConsoleController extends BaseController
             ["name" => "收款流水", "img" => "ghs/home/kcyjs.png", "url" => "/admin/order/scanPay"],
             // 无原单退款:选客户→选花材→生成 sameDay=0 退款单(不关联销售单)
             ["name" => "退款", "img" => "ghs/home/icon_caigou.png", "url" => "/admin/custom/selectCustom?style=1&refund=1"],
+            ["name" => "退款记录", "img" => "ghs/home/icon_caigou.png", "url" => "/admin/billing/freeRefundList"],
             ["name" => "公告", "img" => "ghs/home/icon_caigou.png", "url" => "/admin/ghsNotice/list"],
         ];
         $menuIconMap = [
@@ -291,6 +293,7 @@ class ConsoleController extends BaseController
             '商城' => 'mall_code',
             '花材(简)' => 'item',
             '退款' => 'purchase_record',
+            '退款记录' => 'purchase_record',
         ];
         if ($version == 2) {
             $menu = $menuV2;

+ 53 - 20
app-ghs/controllers/RefundController.php

@@ -460,6 +460,11 @@ class RefundController extends BaseController
         if (!empty($orderSn)) {
             $where['relateOrderSn'] = $orderSn;
         }
+        // 工作台「退款记录」:只查无关联销售单的退款
+        $freeOnly = intval($get['freeOnly'] ?? 0);
+        if ($freeOnly === 1) {
+            $where['relateOrderSn'] = '';
+        }
         $searchTime = $get['searchTime'] ?? '';
         if (!empty($searchTime)) {
             $startTime = $get['startTime'] ?? '';
@@ -469,9 +474,13 @@ class RefundController extends BaseController
         }
 
         $refundSearchTime = $get['refundSearchTime'] ?? '';
+        // 退款记录默认近30天(按售后单创建时间)
+        if ($freeOnly === 1 && empty($refundSearchTime) && empty($searchTime)) {
+            $refundSearchTime = 'last30Days';
+        }
         if (!empty($refundSearchTime)) {
-            $startTime = $get['refundStartTime'] ?? '';
-            $endTime = $get['refundEndTime'] ?? '';
+            $startTime = $get['refundStartTime'] ?? ($get['startTime'] ?? '');
+            $endTime = $get['refundEndTime'] ?? ($get['endTime'] ?? '');
             $period = dateUtil::formatTime($refundSearchTime, $startTime, $endTime);
             $where['addTime'] = ['between', [$period['startTime'], $period['endTime']]];
         }
@@ -582,22 +591,30 @@ class RefundController extends BaseController
         }
         $imgString = $refund['imgList'] ?? '';
         $relateOrderSn = $refund['relateOrderSn'] ?? '';
-        $order = OrderClass::getByCondition(['orderSn' => $relateOrderSn], true);
-        if (empty($order)) {
-            util::fail('数据出错了');
-        }
-        $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,
-        ];
+        // 无原单退款:不强制关联销售单
+        $order = null;
+        if ($relateOrderSn !== '' && $relateOrderSn !== null) {
+            $order = OrderClass::getByCondition(['orderSn' => $relateOrderSn], true);
+        }
+        if (!empty($order)) {
+            $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 ?? 0,
+                'payWay' => $order->payWay,
+            ];
+            $refund['isFreeRefund'] = 0;
+        } else {
+            $refund['relateOrderId'] = 0;
+            $refund['orderInfo'] = null;
+            $refund['isFreeRefund'] = 1;
+        }
 
         if (!empty($imgString)) {
             $imgArr = json_decode($imgString, true);
@@ -813,7 +830,16 @@ class RefundController extends BaseController
                 $connection = Yii::$app->db;
                 $transaction = $connection->beginTransaction();
                 try {
-                    $refundType = intval($post['refundType'] ?? RefundOrderClass::REFUND_TYPE_MONEY_GOOD);
+                    // returnWay 优先:1库存退回要花材;0库存不退可只记金额
+                    $returnWay = intval($post['returnWay'] ?? -1);
+                    if ($returnWay === 1) {
+                        $refundType = RefundOrderClass::REFUND_TYPE_MONEY_GOOD;
+                    } elseif ($returnWay === 0) {
+                        $refundType = RefundOrderClass::REFUND_TYPE_MONEY;
+                    } else {
+                        $refundType = intval($post['refundType'] ?? RefundOrderClass::REFUND_TYPE_MONEY_GOOD);
+                    }
+                    $post['refundType'] = $refundType;
                     if ($refundType == RefundOrderClass::REFUND_TYPE_MONEY_GOOD) {
                         $productJson = $post['product'] ?? '';
                         if (empty($productJson)) {
@@ -825,7 +851,14 @@ class RefundController extends BaseController
                         }
                         $post['product'] = $productList;
                     } else {
-                        $post['product'] = [];
+                        // 库存不退:金额已够,明细可选保留供对账
+                        $productJson = $post['product'] ?? '';
+                        if (!empty($productJson)) {
+                            $productList = is_array($productJson) ? $productJson : json_decode($productJson, true);
+                            $post['product'] = is_array($productList) ? $productList : [];
+                        } else {
+                            $post['product'] = [];
+                        }
                     }
                     $post['price'] = $post['price'] ?? 0;
                     if ($post['price'] <= 0) {

+ 9 - 6
biz-ghs/order/services/NextDayRefundService.php

@@ -211,15 +211,18 @@ class NextDayRefundService
         $sjId = intval($refund->sjId ?? 0);
         $customName = $refund->customName ?? '';
 
-        // 退货退款:按明细回库(无原单行,不校验可退数量
-        if ($refundType === RefundOrderClass::REFUND_TYPE_MONEY_GOOD) {
-            $refundItemList = RefundOrderItemClass::getAllByCondition(['orderSn' => $refundSn], null, '*', null, true);
-            if (empty($refundItemList)) {
-                util::fail('没有找到退款花材');
-            }
+        // 有明细则置通过;仅「退货退款」回库(库存不退只记账不改库存
+        $refundItemList = RefundOrderItemClass::getAllByCondition(['orderSn' => $refundSn], null, '*', null, true);
+        if ($refundType === RefundOrderClass::REFUND_TYPE_MONEY_GOOD && empty($refundItemList)) {
+            util::fail('没有找到退款花材');
+        }
+        if (!empty($refundItemList)) {
             foreach ($refundItemList as $val) {
                 $val->status = 1;
                 $val->save();
+                if ($refundType !== RefundOrderClass::REFUND_TYPE_MONEY_GOOD) {
+                    continue;
+                }
                 $productId = intval($val->productId ?? 0);
                 $ptItemId = intval($val->itemId ?? 0);
                 $num = bcadd((string)($val->xhNum ?? '0'), '0', 2);

+ 35 - 4
biz-ghs/order/services/RefundOrderService.php

@@ -284,13 +284,43 @@ class RefundOrderService extends BaseService
             util::fail('请填写退款金额');
         }
 
-        $refundType = intval($post['refundType'] ?? RefundOrderClass::REFUND_TYPE_MONEY_GOOD);
+        // 前端 returnWay:0库存不退→仅退款;1库存退回→退货退款
+        $returnWay = intval($post['returnWay'] ?? -1);
+        if ($returnWay === 0) {
+            $refundType = RefundOrderClass::REFUND_TYPE_MONEY;
+        } elseif ($returnWay === 1) {
+            $refundType = RefundOrderClass::REFUND_TYPE_MONEY_GOOD;
+        } else {
+            $refundType = intval($post['refundType'] ?? RefundOrderClass::REFUND_TYPE_MONEY_GOOD);
+        }
+
+        // 前端 toBalance:1返充余额→fundType2;0否→仅记账3
+        $toBalance = intval($post['toBalance'] ?? -1);
+        if ($toBalance === 1) {
+            $post['fundType'] = NextDayRefundService::FUND_BALANCE;
+        } elseif ($toBalance === 0) {
+            $post['fundType'] = NextDayRefundService::FUND_NONE;
+        }
         $fundType = NextDayRefundService::resolveFundType($post['fundType'] ?? 0, null, false);
 
         $sjId = intval($post['sjId'] ?? 0);
         $shopId = intval($post['shopId'] ?? 0);
         $orderSn = orderSn::getGhsRefundSn();
 
+        // xhRefund 暂无 payWay 字段:退款方式写入备注便于追溯
+        $payWay = intval($post['payWay'] ?? -1);
+        $payWayNameMap = [
+            0 => '线下微信',
+            1 => '线下支付宝',
+            4 => '现金',
+            5 => '银行卡',
+        ];
+        $remark = trim((string)($post['remark'] ?? ''));
+        if (isset($payWayNameMap[$payWay])) {
+            $payTag = '退款方式:' . $payWayNameMap[$payWay];
+            $remark = $remark === '' ? $payTag : ($remark . ';' . $payTag);
+        }
+
         $data = [
             'status' => RefundOrderClass::STATUS_UN_COMPLETE,
             'orderSn' => $orderSn,
@@ -309,7 +339,7 @@ class RefundOrderService extends BaseService
             'customMobile' => $custom->mobile ?? '',
             'orderTime' => date('Y-m-d H:i:s'),
             'imgList' => $post['imgList'] ?? '',
-            'remark' => $post['remark'] ?? '',
+            'remark' => $remark,
             'refundPrice' => $refundPrice,
             'refundType' => $refundType,
             'sameDay' => RefundOrderClass::SAME_DAY_NO,
@@ -317,6 +347,7 @@ class RefundOrderService extends BaseService
         ];
 
         $postProduct = $post['product'] ?? [];
+        // 库存退回必须有花材;库存不退可只退金额,有花材时仍落明细便于对账
         if ($refundType === RefundOrderClass::REFUND_TYPE_MONEY_GOOD) {
             if (empty($postProduct) || !is_array($postProduct)) {
                 util::fail('请选择花材');
@@ -325,8 +356,8 @@ class RefundOrderService extends BaseService
 
         $refund = RefundOrderClass::add($data, true);
 
-        // 无原单明细:按商品主档写售后行,orderItemId=0
-        if ($refundType === RefundOrderClass::REFUND_TYPE_MONEY_GOOD) {
+        // 有花材则写售后行(orderItemId=0);是否回库由 passFreeRefund 按 refundType 决定
+        if (!empty($postProduct) && is_array($postProduct)) {
             foreach ($postProduct as $currentProduct) {
                 $productId = intval($currentProduct['productId'] ?? 0);
                 if ($productId <= 0) {