Преглед на файлове

Merge remote-tracking branch 'origin/redesign‌-260706' into redesign‌-260706

ouyang преди 15 часа
родител
ревизия
9ba1cc4fee

+ 75 - 3
app-mall/controllers/HomePageConfigController.php

@@ -2,17 +2,22 @@
 
 namespace mall\controllers;
 
+use biz\shop\classes\ShopClass;
+use bizHd\custom\classes\CustomClass;
 use bizHd\homePageConfig\classes\HomePageConfigClass;
 use bizHd\homePageConfig\classes\HomePageDisplayClass;
 use bizHd\homePageConfig\classes\HomePageModuleClass;
+use bizMall\hd\classes\HdClass;
 use common\components\util;
 use mall\models\homePageConfig\GetSectionGoodsForm;
+use Yii;
 
 /**
  * 商城端首页配置读取接口
  * mallApp 通过 account(shopId) 获取配置,与 hd 管理端共用 Redis。
  * 具体的格式化/真实商品解析逻辑统一收敛在 HomePageDisplayClass,
  * 保证与 app-hd 的预览接口返回结构完全一致。
+ * 登录态会解析/创建顾客与门店的 hd 绑定,把 hdId 带回给 mallApp 缓存并拼到跳转链接。
  */
 class HomePageConfigController extends BaseController
 {
@@ -29,19 +34,44 @@ class HomePageConfigController extends BaseController
     ];
 
     /**
-     * 一次拉取首页全部模块配置,便于 mallApp 首页组装
+     * 一次拉取首页全部模块配置,便于 mallApp 首页组装。
+     * 已登录情况下,会解析当前门店的 hd 绑定:已有则直接返回 hdId,没有则建客建 hd。
      */
     public function actionGetHome()
     {
-        $mainId = intval($this->mainId);
         $shopId = intval($this->shopId);
         if ($shopId <= 0) {
             util::fail('shopId不存在');
         }
+
+        $shop = $this->shop;
+        if (empty($shop)) {
+            // BaseController 在请求 hdId 与当前用户不匹配时会清空 shop,这里按 account 重新取门店
+            $shop = ShopClass::getById($shopId, true);
+        }
+        if (empty($shop)) {
+            util::fail('无效门店');
+        }
+        $mainId = intval($this->mainId);
+        if ($mainId <= 0) {
+            $mainId = intval($shop->mainId);
+        }
         if ($mainId <= 0) {
             util::fail('mainId不存在');
         }
-        util::success(HomePageDisplayClass::buildHome($this->requireMainId(), $this->requireShopId()));
+
+        $hdId = 0;
+        $inviteBound = 0;
+        if (intval($this->userId) > 0) {
+            $resolved = $this->resolveLoggedInHd($shop, $shopId);
+            $hdId = $resolved['hdId'];
+            $inviteBound = $resolved['inviteBound'];
+        }
+
+        $re = HomePageDisplayClass::buildHome($mainId, $shopId);
+        $re['hdId'] = $hdId;
+        $re['inviteBound'] = $inviteBound;
+        util::success($re);
     }
 
     public function actionGetBanner()
@@ -96,6 +126,48 @@ class HomePageConfigController extends BaseController
         ));
     }
 
+    /**
+     * 登录态解析当前门店 hdId。
+     * 已有 xhHd(门店已绑定该顾客)则直接取 id;没有则走 CustomClass::buildRelation,
+     * 与 ShopController::actionInfo 在无 hdId 时的建客路径一致,避免首页先建客却漏掉分享拉新。
+     * @param object|null $shop 门店对象,建客时必须有
+     * @param int $shopId 门店 id(xhShop.id)
+     * @return array{hdId:int,inviteBound:int}
+     * @throws \yii\db\IntegrityException
+     */
+    private function resolveLoggedInHd($shop, $shopId)
+    {
+        $hd = HdClass::getByCondition(
+            ['shopId' => $shopId, 'userId' => $this->userId],
+            false,
+            null,
+            'id, customId'
+        );
+        if (!empty($hd)) {
+            return [
+                'hdId' => intval($hd['id']),
+                'inviteBound' => 0,
+            ];
+        }
+
+        $user = $this->user;
+        if (empty($shop) || empty($user)) {
+            return ['hdId' => 0, 'inviteBound' => 0];
+        }
+
+        $inviterCustomId = (int)Yii::$app->request->get('inviterCustomId', 0);
+        $respond = CustomClass::buildRelation($shop, $user, $inviterCustomId);
+        if (empty($respond) || empty($respond['hd'])) {
+            return ['hdId' => 0, 'inviteBound' => 0];
+        }
+
+        $hd = $respond['hd'];
+        return [
+            'hdId' => intval(is_object($hd) ? $hd->id : ($hd['id'] ?? 0)),
+            'inviteBound' => !empty($respond['inviteBound']) ? (int)$respond['inviteBound'] : 0,
+        ];
+    }
+
     private function requireMainId()
     {
         $mainId = intval($this->mainId);

+ 14 - 2
app-mall/controllers/OrderController.php

@@ -5,6 +5,7 @@ namespace mall\controllers;
 use biz\product\classes\ProductClass;
 use biz\shop\classes\ShopClass;
 use biz\wx\classes\WxMessageClass;
+use bizHd\groupBuy\classes\GroupBuyClass;
 use bizHd\custom\classes\HdClass;
 use bizHd\distribution\classes\DistributionOrderClass;
 use bizHd\express\classes\HdDeliveryOrderClass;
@@ -1932,7 +1933,10 @@ class OrderController extends BaseController
         }
     }
 
-    //订单列表 ssh 2019.12.12
+    /**
+     * 订单列表
+     * 拼团单含 groupBuyStatus,供 mallApp 订单 Tab / 店铺订单控制履约按钮与状态文案
+     */
     public function actionList()
     {
         $get = Yii::$app->request->get();
@@ -1971,7 +1975,10 @@ class OrderController extends BaseController
         util::complete('提交成功');
     }
 
-    // 订单详情:含 canApplyRefund / refundApplyId,供底部申请售后、查看申请
+    /**
+     * 订单详情:含 canApplyRefund / refundApplyId / groupBuyStatus
+     * 拼团单不能只看 status、payStatus,前端须结合 groupBuyStatus(1拼团中 2成功 3失败 4已取消)
+     */
     public function actionDetail()
     {
         $id = Yii::$app->request->get('id', 0);
@@ -2051,6 +2058,11 @@ class OrderController extends BaseController
         if (in_array($status, [HdOrderClass::ORDER_STATUS_UN_PAY, HdOrderClass::ORDER_STATUS_CANCEL, 6], true)) {
             return false;
         }
+        // 拼团单须成团成功才开放售后;拼团中/失败/已取消走自动退款或不可履约
+        if ((int)($order['groupBuyId'] ?? 0) > 0
+            && (int)($order['groupBuyStatus'] ?? 0) !== GroupBuyClass::STATUS_SUCCESS) {
+            return false;
+        }
         if ((int)($order['forward'] ?? 0) === 1) {
             return false;
         }

+ 13 - 0
app-mall/controllers/RefundController.php

@@ -8,6 +8,7 @@
 namespace mall\controllers;
 
 use bizHd\distribution\classes\DistributionOrderClass;
+use bizHd\groupBuy\classes\GroupBuyClass;
 use bizHd\order\classes\OrderClass as HdOrderClass;
 use bizHd\refund\classes\HdRefundClass;
 use bizHd\refund\classes\HdRefundMallClass;
@@ -105,6 +106,13 @@ class RefundController extends BaseController
         if ((int)($order->forward ?? 0) === 1) {
             util::fail('售后收入单无法申请售后');
         }
+        // 拼团未成功:失败会自动退款,拼团中尚未履约,不允许走普通售后
+        if (intval($order->groupBuyId ?? 0) > 0) {
+            $groupBuyStatus = GroupBuyClass::getStatusById(intval($order->groupBuyId));
+            if ($groupBuyStatus !== GroupBuyClass::STATUS_SUCCESS) {
+                util::fail('拼团未成功,暂无法申请售后');
+            }
+        }
         if (HdRefundClass::hasPendingByOrderId($id)) {
             util::fail('已有待审核的售后申请,请勿重复提交');
         }
@@ -232,6 +240,11 @@ class RefundController extends BaseController
         if ((int)($order['forward'] ?? 0) === 1) {
             return 0;
         }
+        // 拼团单须成团成功才允许新开售后
+        if ((int)($order['groupBuyId'] ?? 0) > 0
+            && (int)($order['groupBuyStatus'] ?? 0) !== GroupBuyClass::STATUS_SUCCESS) {
+            return 0;
+        }
         if (!empty($apply) && (int)($apply['status'] ?? -1) === HdRefundClass::STATUS_PENDING) {
             return 0;
         }

+ 35 - 0
biz-hd/groupBuy/classes/GroupBuyClass.php

@@ -702,4 +702,39 @@ class GroupBuyClass extends BaseClass
         }
         return $result;
     }
+
+    /**
+     * 按团 id 取拼团状态,供订单列表/详情附带
+     * 团不存在或 id 无效返回 0,避免把普通单误标成拼团
+     * @param int $groupBuyId
+     * @return int 0=非拼团或团不存在;1拼团中 2成功 3失败 4已取消
+     */
+    public static function getStatusById($groupBuyId)
+    {
+        $groupBuyId = intval($groupBuyId);
+        if ($groupBuyId <= 0) {
+            return 0;
+        }
+        $groupBuy = self::getById($groupBuyId);
+        return intval($groupBuy['status'] ?? 0);
+    }
+
+    /**
+     * 批量取拼团状态,避免订单列表逐条查团
+     * @param array $ids 拼团 id 列表
+     * @return array [groupBuyId => status]
+     */
+    public static function getStatusMapByIds($ids)
+    {
+        $ids = array_values(array_filter(array_unique(array_map('intval', (array)$ids))));
+        if (empty($ids)) {
+            return [];
+        }
+        $list = self::getByIds($ids, null, 'id', 'id,status');
+        $map = [];
+        foreach ($list as $id => $row) {
+            $map[intval($id)] = intval($row['status'] ?? 0);
+        }
+        return $map;
+    }
 }

+ 1 - 1
biz-hd/hb/classes/HbAutoRuleClass.php

@@ -277,7 +277,7 @@ class HbAutoRuleClass extends BaseClass
                 util::fail('红包金额和数量必须大于0');
             }
             $out[] = [
-                'name' => trim((string)($item['name'] ?? '')),
+                'name' => '红包',
                 'hbAmount' => $amount,
                 'hbNum' => $num,
                 'miniCost' => $minConsume,

+ 2 - 2
biz-hd/homePageConfig/classes/HomePageDisplayClass.php

@@ -19,10 +19,10 @@ class HomePageDisplayClass
 {
     /**
      * 一次性组装首页全部模块的展示数据
-     *
      * @param int $mainId
      * @param int $shopId
      * @return array
+     * @throws \Exception
      */
     public static function buildHome($mainId, $shopId)
     {
@@ -44,10 +44,10 @@ class HomePageDisplayClass
 
     /**
      * 格式化顶部导航:门店名称不落 Redis,实时取 xhShop.merchantName
-     *
      * @param int $shopId 门店 id(xhShop.id,即 mall account)
      * @param array $data HomePageConfigClass::getTopNav 返回值
      * @return array
+     * @throws \Exception
      */
     public static function formatTopNav($shopId, $data)
     {

+ 24 - 1
biz-mall/order/classes/OrderClass.php

@@ -1,5 +1,10 @@
 <?php
 
+/**
+ * 商城订单核心类
+ * 用途:mallApp 订单详情/列表组装;拼团单附带 groupBuyStatus 供前端结合 status/payStatus 展示
+ */
+
 namespace bizMall\order\classes;
 
 use biz\stat\classes\StatOrderCountClass;
@@ -13,6 +18,7 @@ use common\components\mapUtil;
 use common\components\miniUtil;
 use common\components\dict;
 use common\components\orderSn;
+use bizHd\groupBuy\classes\GroupBuyClass;
 use bizMall\base\classes\BaseClass;
 use common\components\util;
 
@@ -221,7 +227,7 @@ class OrderClass extends BaseClass
             }
         }
         $order['itemList'] = $itemList;
-        return $order;
+        return self::attachGroupBuyStatus($order);
     }
 
     //根据订单查询 ssh 2020.1.4
@@ -249,6 +255,23 @@ class OrderClass extends BaseClass
             }
         }
         $order['itemList'] = $itemList;
+        return self::attachGroupBuyStatus($order);
+    }
+
+    /**
+     * 给订单附带拼团状态,供商城详情展示与售后判断
+     * 非拼团单 groupBuyStatus=0;拼团单为 1拼团中 2成功 3失败 4已取消
+     * @param array $order 订单数组
+     * @return array
+     */
+    public static function attachGroupBuyStatus($order)
+    {
+        if (empty($order) || !is_array($order)) {
+            return $order;
+        }
+        $groupBuyId = intval($order['groupBuyId'] ?? 0);
+        $order['groupBuyId'] = $groupBuyId;
+        $order['groupBuyStatus'] = $groupBuyId > 0 ? GroupBuyClass::getStatusById($groupBuyId) : 0;
         return $order;
     }
 

+ 40 - 2
biz-mall/order/services/OrderService.php

@@ -1,5 +1,10 @@
 <?php
 
+/**
+ * 商城订单服务
+ * 用途:mallApp 下单与订单列表组装;列表为拼团单批量附带 groupBuyStatus
+ */
+
 namespace bizMall\order\services;
 
 use bizMall\base\services\BaseService;
@@ -7,6 +12,7 @@ use bizMall\goods\classes\GoodsClass;
 use bizMall\hd\classes\HdClass;
 use bizMall\item\classes\ItemClass;
 use bizMall\merchant\services\MerchantCapitalService;
+use bizHd\groupBuy\classes\GroupBuyClass;
 use bizMall\order\classes\OrderClass;
 use bizMall\order\classes\OrderGoodsClass;
 use bizMall\order\classes\OrderItemClass;
@@ -224,11 +230,17 @@ class OrderService extends BaseService
         return OrderClass::addOrder($data);
     }
 
-    //获取订单信息 TODO 重新实现,要限制查询字段与返回字段,性能第一???? -- 商品项(商品规格)、商品数量
+    /**
+     * 商城顾客订单列表
+     * 拼团单批量附带 groupBuyStatus(1拼团中 2成功 3失败 4已取消),并按成团结果覆盖 statusDesc
+     * @param array $where
+     * @return array
+     */
     public static function getOrderList($where)
     {
         // customId:订单列表「联系客服」进 chatPage 所需
-        $fields = 'id, shopId, hdId, customId, orderSn, groupBuyId, orderType, actPrice,orderPrice, goodsNum, reachDate, reachPeriod, status, addTime';
+        // payStatus + groupBuyId:拼团单不能只看 status,需结合支付与成团结果控制履约
+        $fields = 'id, shopId, hdId, customId, orderSn, groupBuyId, orderType, actPrice,orderPrice, goodsNum, reachDate, reachPeriod, status, payStatus, addTime';
         $data = self::getList($fields, $where, 'addTime DESC');
         if (empty($data['list'])) {
             return $data;
@@ -243,6 +255,14 @@ class OrderService extends BaseService
         // 花束明细在 xhOrderGoods,花材明细在 xhOrderItem;列表按实际明细合并,避免 orderType=0/错标导致空列表
         $goodsListMap = OrderGoodsService::getGoodsListByOrderSns($orderSns);
         $itemListMap = OrderItemService::getItemListByOrderSns($orderSns);
+        $groupBuyIds = [];
+        foreach ($list as $val) {
+            $gid = intval($val['groupBuyId'] ?? 0);
+            if ($gid > 0) {
+                $groupBuyIds[] = $gid;
+            }
+        }
+        $groupBuyStatusMap = GroupBuyClass::getStatusMapByIds($groupBuyIds);
         $periodData = [0 => '上午', 1 => '下午', 2 => '晚上'];
         foreach ($data['list'] as $key => $val) {
             $orderSn = $val['orderSn'] ?? '';
@@ -268,6 +288,24 @@ class OrderService extends BaseService
             }
             $data['list'][$key]['requireReachTime'] = $requireTime;
             $data['list'][$key]['smallHdAvatar'] = imgUtil::groupImg('') . "?x-oss-process=image/resize,m_fill,h_80,w_80";
+
+            // 拼团单附带团状态:1拼团中 2成功 3失败 4已取消,供列表控制履约按钮与状态文案
+            $groupBuyId = intval($val['groupBuyId'] ?? 0);
+            $groupBuyStatus = $groupBuyId > 0 ? intval($groupBuyStatusMap[$groupBuyId] ?? 0) : 0;
+            $data['list'][$key]['groupBuyId'] = $groupBuyId;
+            $data['list'][$key]['groupBuyStatus'] = $groupBuyStatus;
+            // 已付款但未成团时覆盖 statusDesc,避免把拼团中误显示成待配送
+            if ($groupBuyId > 0) {
+                if ($groupBuyStatus === GroupBuyClass::STATUS_ONGOING
+                    && $orderStatus !== OrderClass::ORDER_STATUS_UN_PAY
+                    && $orderStatus !== OrderClass::ORDER_STATUS_CANCEL) {
+                    $data['list'][$key]['statusDesc'] = '拼团中';
+                } elseif ($groupBuyStatus === GroupBuyClass::STATUS_FAIL) {
+                    $data['list'][$key]['statusDesc'] = '拼团失败';
+                } elseif ($groupBuyStatus === GroupBuyClass::STATUS_CANCEL) {
+                    $data['list'][$key]['statusDesc'] = '拼团已取消';
+                }
+            }
         }
         return $data;
     }