Explorar o código

Merge remote-tracking branch 'origin/dev' into dev

ouyang hai 1 mes
pai
achega
14428718b1

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

@@ -174,6 +174,7 @@ class ConsoleController extends BaseController
             }
         }
 
+
         //$notice[] = ['title' => '客户多个订单开始支持一键分享', 'action' => '查看', 'page' => '/admin/book/detail?id=calc'];
         //$notice[] = ['title' => '如果你发现一个问题很重要,一直没给你处理,在小群多反应几次,用反应次数强调重要性,目前批发店多反应问题多,都在排队。', 'action' => '', 'page' => ''];
         //$notice[] = ['title' => '新功能:客户端和后台使用跑腿的流程', 'action' => '', 'page' => '/admin/book/detail?id=use_pt'];

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

@@ -1100,6 +1100,7 @@ class CustomController extends BaseController
         $homeNum = $get['homeNum'] ?? 0;
         $homeUnMeet = $get['homeUnMeet'] ?? 2;
         $homeUnFee = $get['homeUnFee'] ?? 0;
+        $homeRule = $get['homeRule'] ?? 0;
         if (isset($get['homeType'])) {
             //早期系统有带这个参数,来判断
             util::fail('请升级系统');
@@ -1120,11 +1121,13 @@ class CustomController extends BaseController
         $custom->homeNum = $homeNum;
         $custom->homeUnMeet = $homeUnMeet;
         $custom->homeUnFee = $homeUnFee;
+        $custom->homeRule = $homeRule;
         $custom->save();
         $ghs->homeAmount = $homeAmount;
         $ghs->homeNum = $homeNum;
         $ghs->homeUnMeet = $homeUnMeet;
         $ghs->homeUnFee = $homeUnFee;
+        $ghs->homeRule = $homeRule;
         $ghs->save();
         util::complete('修改成功');
     }

+ 9 - 3
app-ghs/controllers/ShopYeChangeController.php

@@ -27,6 +27,14 @@ class ShopYeChangeController extends BaseController
         if (!empty($tx)) {
             $where['tx'] = $tx;
         }
+        // 事件类型
+        if (isset($get['capitalType']) && $get['capitalType'] !== '') {
+            $where['capitalType'] = (int)$get['capitalType'];
+        }
+        // 收支类型筛选:1 收入,0 支出;未传参时不筛选
+        if (isset($get['io']) && $get['io'] !== '') {
+            $where['io'] = (int)$get['io'];
+        }
         $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : '';
         $startTime = $get['startTime'] ?? '';
         $endTime = $get['endTime'] ?? '';
@@ -38,7 +46,6 @@ class ShopYeChangeController extends BaseController
         }
         $list = ShopYeChangeClass::getChangeList($where);
         if ($export == 1) {
-
             ini_set('memory_limit', '2045M');
             set_time_limit(0);
             if (isset($where['addTime']) == false) {
@@ -58,5 +65,4 @@ class ShopYeChangeController extends BaseController
         }
         util::success($list);
     }
-
-}
+}

+ 1 - 0
app-ghs/controllers/TestController.php

@@ -62,6 +62,7 @@ class TestController extends BaseController
 //        stockConsumer::clearOrderItemLimitBuy($data);
     }
 
+
     public function actionFx()
     {
         $ghsShopId = 7855;

+ 4 - 1
app-hd/controllers/ApplyController.php

@@ -70,6 +70,9 @@ class ApplyController extends BaseController
         $ptStyle = Yii::$app->params['ptStyle'];
         $cacheKey = 'register_mobile_code_' . $ptStyle . '_' . $mobile;
         Yii::$app->redis->executeCommand('SETEX', [$cacheKey, 600, $rand]);
+
+        noticeUtil::push("注册验证码:{$rand},{$mobile} 申请注册", '15280215347');
+
         util::complete();
     }
 
@@ -326,4 +329,4 @@ class ApplyController extends BaseController
         util::success(['code' => rand(1111, 9999)]);
     }
 
-}
+}

+ 32 - 12
app-hd/controllers/CustomController.php

@@ -36,8 +36,12 @@ class CustomController extends BaseController
     {
         $get = Yii::$app->request->get();
         $customId = $get['customId'];
-        CustomClass::modifyBirthday($customId, $this->shopId, $get);
-        util::complete('修改成功');
+        list(, $updateResult) = CustomClass::modifyBirthday($customId, $this->shopId, $get);
+        if ($updateResult) {
+            util::complete('生日修改成功');
+        } else {
+            util::complete('客户本人设置了,您不需要修改它');
+        }
     }
 
     public function actionChangeLevel()
@@ -197,7 +201,6 @@ class CustomController extends BaseController
     {
         $get = Yii::$app->request->get();
         $type = $get['type'] ?? 0;
-        $searchStyle = $get['searchStyle'] ?? 0;
         $where = ['shopId' => $this->shopId];
         $all = CustomClass::getCount($where);
 
@@ -223,6 +226,31 @@ class CustomController extends BaseController
             $sort = 'visitTime DESC';
         }
 
+        $where = array_merge($where, $this->getListSearchWhere($get));
+        $list = CustomService::getCustomList($where, $sort);
+        $list['all'] = $all; //全部的总人数
+        $list['balance'] = $all; //余额排行的总人数
+        $list['buyAmount'] = $all; //消费排行的总人数
+        $list['birth'] = CustomClass::getCount(array_merge(['shopId' => $this->shopId], ['birthdayTime>' => 0])); //有设置生日的总人数
+        $list['deleted'] = CustomClass::getCount(array_merge(['shopId' => $this->shopId], ['delStatus' => 1])); //被删除的总人数
+        $list['vip'] = CustomClass::getCount(array_merge(['shopId' => $this->shopId], ['vip' => 1])); //是vip的总人数
+
+        util::success($list);
+    }
+
+    //客户余额统计 ssh 20260708
+    public function actionBalanceStat()
+    {
+        $get = Yii::$app->request->get();
+        $where = array_merge(['shopId' => $this->shopId], $this->getListSearchWhere($get));
+        $respond = CustomClass::getBalanceStat($where);
+        util::success($respond);
+    }
+
+    private function getListSearchWhere($get)
+    {
+        $where = [];
+        $searchStyle = $get['searchStyle'] ?? 0;
         $name = $get['name'] ?? '';
         if (empty($name)) {
             $name = $get['keyword'] ?? '';
@@ -241,15 +269,7 @@ class CustomController extends BaseController
                 }
             }
         }
-        $list = CustomService::getCustomList($where, $sort);
-        $list['all'] = $all; //全部的总人数
-        $list['balance'] = $all; //余额排行的总人数
-        $list['buyAmount'] = $all; //消费排行的总人数
-        $list['birth'] = CustomClass::getCount(array_merge(['shopId' => $this->shopId], ['birthdayTime>' => 0])); //有设置生日的总人数
-        $list['deleted'] = CustomClass::getCount(array_merge(['shopId' => $this->shopId], ['delStatus' => 1])); //被删除的总人数
-        $list['vip'] = CustomClass::getCount(array_merge(['shopId' => $this->shopId], ['vip' => 1])); //是vip的总人数
-
-        util::success($list);
+        return $where;
     }
 
     //获取客户信息 ssh 20250510

+ 30 - 12
app-hd/controllers/NoticeController.php

@@ -192,13 +192,17 @@ class NoticeController extends PublicController
                         Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                     }
                 } else {
+                    //标记当天发快递方式已收一次包装费/运费,岭南批发市场用的功能,关键词 sh_method_area,只要有成功单就标记,不再要求金额必须>0
+                    $customId = $cg->customId ?? 0;
+                    $current = date("Y_m_d");
                     if (isset($cg->sendType) && $cg->sendType == 4) {
-                        //标记当天发快递方式已收一次包装费,岭南批发市场用的功能
-                        $customId = $cg->customId ?? 0;
-                        $current = date("Y_m_d");
                         $key = 'ghs_custom_today_has_get_pack_cost_' . $current . '_' . $customId;
                         Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                     }
+                    if (isset($cg->sendType) && $cg->sendType == 0) {
+                        $sendKey = 'ghs_custom_today_has_get_send_cost_' . $current . '_' . $customId;
+                        Yii::$app->redis->executeCommand('SETEX', [$sendKey, 86400, '1']);
+                    }
                 }
 
                 if (!empty($cg) && $cg->payStatus == 1) {
@@ -407,13 +411,17 @@ class NoticeController extends PublicController
                         Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                     }
                 } else {
+                    //标记当天发快递方式已收一次包装费/运费,岭南批发市场用的功能,关键词 sh_method_area,只要有成功单就标记,不再要求金额必须>0
+                    $customId = $cg->customId ?? 0;
+                    $current = date("Y_m_d");
                     if (isset($cg->sendType) && $cg->sendType == 4) {
-                        //标记当天发快递方式已收一次包装费,岭南批发市场用的功能
-                        $customId = $cg->customId ?? 0;
-                        $current = date("Y_m_d");
                         $key = 'ghs_custom_today_has_get_pack_cost_' . $current . '_' . $customId;
                         Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                     }
+                    if (isset($cg->sendType) && $cg->sendType == 0) {
+                        $sendKey = 'ghs_custom_today_has_get_send_cost_' . $current . '_' . $customId;
+                        Yii::$app->redis->executeCommand('SETEX', [$sendKey, 86400, '1']);
+                    }
                 }
 
                 if (!empty($cg) && $cg->payStatus == 1) {
@@ -570,13 +578,19 @@ class NoticeController extends PublicController
                         Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                     }
                 } else {
+
+                    //标记当天发快递方式已收一次包装费/运费,岭南批发市场用的功能,关键词 sh_method_area,只要有成功单就标记,不再要求金额必须>0
+                    $customId = $cg->customId ?? 0;
+                    $current = date("Y_m_d");
                     if (isset($cg->sendType) && $cg->sendType == 4) {
-                        //标记当天发快递方式已收一次包装费,岭南批发市场用的功能
-                        $customId = $cg->customId ?? 0;
-                        $current = date("Y_m_d");
                         $key = 'ghs_custom_today_has_get_pack_cost_' . $current . '_' . $customId;
                         Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                     }
+                    if (isset($cg->sendType) && $cg->sendType == 0) {
+                        $sendKey = 'ghs_custom_today_has_get_send_cost_' . $current . '_' . $customId;
+                        Yii::$app->redis->executeCommand('SETEX', [$sendKey, 86400, '1']);
+                    }
+
                 }
 
                 if (!empty($cg) && $cg->payStatus == 1) {
@@ -822,13 +836,17 @@ class NoticeController extends PublicController
                                 Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                             }
                         } else {
+                            //标记当天发快递方式已收一次包装费/运费,岭南批发市场用的功能,关键词 sh_method_area,只要有成功单就标记,不再要求金额必须>0
+                            $customId = $cg->customId ?? 0;
+                            $current = date("Y_m_d");
                             if (isset($cg->sendType) && $cg->sendType == 4) {
-                                //标记当天发快递方式已收一次包装费,岭南批发市场用的功能
-                                $customId = $cg->customId ?? 0;
-                                $current = date("Y_m_d");
                                 $key = 'ghs_custom_today_has_get_pack_cost_' . $current . '_' . $customId;
                                 Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                             }
+                            if (isset($cg->sendType) && $cg->sendType == 0) {
+                                $sendKey = 'ghs_custom_today_has_get_send_cost_' . $current . '_' . $customId;
+                                Yii::$app->redis->executeCommand('SETEX', [$sendKey, 86400, '1']);
+                            }
                         }
 
                         //微信通知

+ 202 - 167
app-hd/controllers/PurchaseController.php

@@ -11,6 +11,7 @@ use bizGhs\custom\classes\AccountMoneyClass;
 use bizGhs\custom\classes\CustomClass;
 use bizGhs\express\classes\GhsDeliveryOrderClass;
 use bizGhs\order\classes\OrderClass;
+use bizGhs\order\classes\ShMethodClass;
 use bizHd\cg\classes\CgMergeSnClass;
 use bizHd\purchase\classes\PurchaseClass;
 use bizHd\purchase\classes\PurchaseItemClass;
@@ -520,6 +521,9 @@ class PurchaseController extends BaseController
 
             $post['product'] = $productList;
 
+            // xhShMethod 门店下单前保留花材合计,供后续 packCost 计算(pfLevel==0 分支会 unset itemTotalAmount)
+            $shMethodItemAmount = $post['itemTotalAmount'] ?? 0;
+
             $sendType = $post['sendType'] ?? 0;
             $transType = $post['transType'] ?? 0;
             if ($sendType == dict::getDict('sendType', 'thirdSend')) {
@@ -627,211 +631,236 @@ class PurchaseController extends BaseController
                 //标记为昆明到地方订单
                 $post['localOrder'] = 1;
             } else {
-                //同城发货包装费和运费的计算
-                $sendCost = 0;
-                $sendDistance = 0;
-                //特别注意,这边取供货商的shop信息
-                $mapSet = ShopClass::hasIntraCity($ghsShopInfo);
-                $openIntraCity = $mapSet['openIntraCity'] ?? 0;
-                if ($sendType == dict::getDict('sendType', 'thirdSend')) {
-                    if ($openIntraCity == 2) {
-                        util::fail('不能使用跑腿');
+
+                // xhShMethod 门店:下单前按配置写入不满最低消费时的附加包装费/运费,关键词sh_method_area
+                if (in_array($ghsShopId, [36523])) {
+                    $shMethodBigNum = 0;
+                    foreach ($productList as $itemData) {
+                        $shMethodBigNum += floatval($itemData['bigNum'] ?? 0);
+                    }
+                    $additionalCosts = ShMethodClass::calcFee(
+                        $ghsShopId,
+                        $ghsMainId,
+                        $sendType,
+                        $shMethodItemAmount,
+                        $shMethodBigNum,
+                        $customId,
+                        $ghsInfo
+                    );
+
+                    // 如果产生了附加运费,与前面可能产生的 sendCost 进行累加或覆盖
+                    if ($additionalCosts['sendCost'] > 0) {
+                        $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $additionalCosts['sendCost'], 2);
                     }
-                    if ($openIntraCity == 1) {
-                        // 生成随机订单号,不要跟原来的混起来,跑腿-销售单-
-                        $prefix = 'PT-XSD-' . $this->mainId . '-';
-                        $orderSn = $prefix . round(microtime(true) * 1000);
 
-                        // 使用 DeliveryQuoteUtil 获取配送报价
-                        try {
+                    // 如果产生了附加包装费,覆盖前面赋值的 packCost
+                    if ($additionalCosts['packCost'] > 0) {
+                        $post['packCost'] = $additionalCosts['packCost'];
+                    }
+                }else{
 
-                            if (empty($post['deliveryPlatform'])) {
-                                util::fail('请选择跑腿');
-                            }
+                    //同城发货包装费和运费的计算
+                    $sendCost = 0;
+                    $sendDistance = 0;
+                    //特别注意,这边取供货商的shop信息
+                    $mapSet = ShopClass::hasIntraCity($ghsShopInfo);
+                    $openIntraCity = $mapSet['openIntraCity'] ?? 0;
+                    if ($sendType == dict::getDict('sendType', 'thirdSend')) {
+                        if ($openIntraCity == 2) {
+                            util::fail('不能使用跑腿');
+                        }
+                        if ($openIntraCity == 1) {
+                            // 生成随机订单号,不要跟原来的混起来,跑腿-销售单-
+                            $prefix = 'PT-XSD-' . $this->mainId . '-';
+                            $orderSn = $prefix . round(microtime(true) * 1000);
+
+                            // 使用 DeliveryQuoteUtil 获取配送报价
+                            try {
 
-                            $quoteResult = DeliveryQuoteUtil::getDeliveryQuote([
-                                'productList' => $productList,
-                                'deliveryPlatform' => $post['deliveryPlatform'],
-                                'deliveryBracketContent' => $post['deliveryBracketContent'], // 平台多报价识别id
-                                'ghsInfo' => $ghsInfo,
-                                'custom' => $custom,
-                                'order' => [
-                                    'orderSn' => $orderSn,
-                                    'goodsType' => 1, //商品类型:0花束 1花材
-                                    'itemTotalAmount' => $post['itemTotalAmount'] ?? 0,
-                                    'remark' => $post['remark'] ?? '',
-                                ],
-                                'mainId' => $this->mainId,
-                                'productCount' => $productCount,
-                            ]);
-
-                            $sendCost = $quoteResult['sendCost'];
-                            $sendDistance = $quoteResult['sendDistance'];
-                        } catch (\Exception $e) {
-                            util::fail($e->getMessage());
+                                if (empty($post['deliveryPlatform'])) {
+                                    util::fail('请选择跑腿');
+                                }
+
+                                $quoteResult = DeliveryQuoteUtil::getDeliveryQuote([
+                                    'productList' => $productList,
+                                    'deliveryPlatform' => $post['deliveryPlatform'],
+                                    'deliveryBracketContent' => $post['deliveryBracketContent'], // 平台多报价识别id
+                                    'ghsInfo' => $ghsInfo,
+                                    'custom' => $custom,
+                                    'order' => [
+                                        'orderSn' => $orderSn,
+                                        'goodsType' => 1, //商品类型:0花束 1花材
+                                        'itemTotalAmount' => $post['itemTotalAmount'] ?? 0,
+                                        'remark' => $post['remark'] ?? '',
+                                    ],
+                                    'mainId' => $this->mainId,
+                                    'productCount' => $productCount,
+                                ]);
+
+                                $sendCost = $quoteResult['sendCost'];
+                                $sendDistance = $quoteResult['sendDistance'];
+                            } catch (\Exception $e) {
+                                util::fail($e->getMessage());
+                            }
                         }
                     }
-                }
 
-                $post['sendCost'] = $sendCost;
-                $post['sendDistance'] = $sendDistance;
+                    $post['sendCost'] = $sendCost;
+                    $post['sendDistance'] = $sendDistance;
 
-                //出车、发快递、发物流可以算包装费
-                $packCost = 0;
-                if (isset($ghsInfo['mainId']) && $ghsInfo['mainId'] == 14499) {
-                    noticeUtil::push("走的pfLevel=0", '15280215347');
-                }
-                $itemTotalAmount = $post['itemTotalAmount'] ?? 0;
-                unset($post['itemTotalAmount']);
-                if ($sendType == dict::getDict('sendType', 'express')) {
-                    $needAdd = \bizHd\shop\classes\ShopClass::needAddPackCost($ghsShopInfo, $customId, $itemTotalAmount);
-                    if ($needAdd) {
-                        $packCost = $ghsShopInfo->packCost ?? 0;
+                    //出车、发快递、发物流可以算包装费
+                    $packCost = 0;
+                    if (isset($ghsInfo['mainId']) && $ghsInfo['mainId'] == 14499) {
+                        noticeUtil::push("走的pfLevel=0", '15280215347');
                     }
-                }
-                $post['packCost'] = $packCost;
-            }
+                    $itemTotalAmount = $post['itemTotalAmount'] ?? 0;
+                    unset($post['itemTotalAmount']);
+                    if ($sendType == dict::getDict('sendType', 'express')) {
+                        $needAdd = \bizHd\shop\classes\ShopClass::needAddPackCost($ghsShopInfo, $customId, $itemTotalAmount);
+                        if ($needAdd) {
+                            $packCost = $ghsShopInfo->packCost ?? 0;
+                        }
+                    }
+                    $post['packCost'] = $packCost;
 
-            if (isset($ghsInfo['mainId']) && $ghsInfo['mainId'] == 14499) {
-                noticeUtil::push("包装费:" . $packCost, '15280215347');
+                }
             }
 
             $respond = PurchaseService::createPurchase($post, $ghsInfo);
 
-            if ($sendType == 0) {
-                if (getenv('YII_ENV') == 'production') {
-                    //杭州斗南鲜花批发部,满500,10公里内免费配送,满1000,20公里免费配送
-                    if ($ghsShopId == 4608) {
-                        if ($respond->actPrice < 500) {
-                            $transaction->rollBack();
-                            util::fail('满500元支持免费配送');
+            if (in_array($ghsShopId, [36523])) {
+                // 使用 xhShMethod 配置校验配送限制,替代旧版门店硬编码规则,关键词sh_method_area
+                $shMethodError = ShMethodClass::checkLimit(
+                    $ghsShopId,
+                    $ghsMainId,
+                    $sendType,
+                    $respond->actPrice ?? 0,
+                    $respond->bigNum ?? 0,
+                    $post['packCost'] ?? 0,
+                    $post['sendCost'] ?? 0,
+                    $post['wlName'] ?? '',
+                    $customId,
+                    $ghsInfo
+                );
+                if ($shMethodError !== '') {
+                    $transaction->rollBack();
+                    util::fail($shMethodError);
+                }
+            } else {
+
+                if ($sendType == 0) {
+                    if (getenv('YII_ENV') == 'production') {
+                        //杭州斗南鲜花批发部,满500,10公里内免费配送,满1000,20公里免费配送
+                        if ($ghsShopId == 4608) {
+                            if ($respond->actPrice < 500) {
+                                $transaction->rollBack();
+                                util::fail('满500元支持免费配送');
+                            }
                         }
-                    }
-                    //叶上花,满500元市区免费配送
-                    if ($ghsShopId == 4804) {
-                        if ($respond->actPrice < 500) {
-                            $transaction->rollBack();
-                            util::fail('满500元支持免费配送');
+                        //叶上花,满500元市区免费配送
+                        if ($ghsShopId == 4804) {
+                            if ($respond->actPrice < 500) {
+                                $transaction->rollBack();
+                                util::fail('满500元支持免费配送');
+                            }
                         }
-                    }
-                    //花悠星 国恋 勇记 万丽 陆丰暂时不支持免费配送
-                    if ($ghsShopId == 7687 || $ghsShopId == 7831 || $ghsShopId == 7778 || $ghsShopId == 12003 || $ghsShopId == 38128) {
-                        util::fail('暂不支持送货上门,请选其它配送方式!');
-                    }
-
-                    //广州鑫源花卉,选择送货上门必须选必选商品
-                    if ($ghsShopId == 12439) {
-                        $hasMust = array_intersect($ids, [3446945, 3446970, 3446973, 3446979, 3446995, 3447010, 3447023, 3459983, 4333184, 4317745, 1585738]);
-                        if (empty($hasMust)) {
-                            util::fail('请返回选择 必选商品');
+                        //花悠星 国恋 勇记 万丽 陆丰暂时不支持免费配送
+                        if ($ghsShopId == 7687 || $ghsShopId == 7831 || $ghsShopId == 7778 || $ghsShopId == 12003 || $ghsShopId == 38128) {
+                            util::fail('暂不支持送货上门,请选其它配送方式!');
                         }
-                    }
 
-                    //三明易批花
-                    if ($ghsShopId == 82200) {
-                        if ($respond->actPrice < 100 || $respond->bigNum < 15) {
-                            $hasMust = array_intersect($ids, [4283478]);
+                        //广州鑫源花卉,选择送货上门必须选必选商品
+                        if ($ghsShopId == 12439) {
+                            $hasMust = array_intersect($ids, [3446945, 3446970, 3446973, 3446979, 3446995, 3447010, 3447023, 3459983, 4333184, 4317745, 1585738]);
                             if (empty($hasMust)) {
-                                util::fail('没满100元且15扎,请返回选运费');
+                                util::fail('请返回选择 必选商品');
                             }
                         }
-                        // 按当天计时,把 sendTimeWant 要限制在两天的时间范围之内
-                        $future = date("Y-m-d", strtotime('+2 day'));
-                        if (strtotime($respond->sendTimeWant) > strtotime($future)) {
-                            util::fail('配送日期只能选最近二天');
-                        }
-                    }
 
-                    if ($ghsShopId == 77703) {
-                        //天天鲜花思明店,暂时关闭送货上门
-                        if ($respond->sendType == 0) {
-                            //util::fail('节日暂停送货上门,请选到店自取');
+                        //三明易批花
+                        if ($ghsShopId == 82200) {
+                            if ($respond->actPrice < 100 || $respond->bigNum < 15) {
+                                $hasMust = array_intersect($ids, [4283478]);
+                                if (empty($hasMust)) {
+                                    util::fail('没满100元且15扎,请返回选运费');
+                                }
+                            }
+                            // 按当天计时,把 sendTimeWant 要限制在两天的时间范围之内
+                            $future = date("Y-m-d", strtotime('+2 day'));
+                            if (strtotime($respond->sendTimeWant) > strtotime($future)) {
+                                util::fail('配送日期只能选最近二天');
+                            }
                         }
-                    }
 
-                    if ($ghsShopId == 86726) {
-                        //藏花林
-                        if ($respond->transType != 4 && $respond->transType != 5) {
-                            util::fail('请选同城配送或到店自取');
+                        if ($ghsShopId == 77703) {
+                            //天天鲜花思明店,暂时关闭送货上门
+                            if ($respond->sendType == 0) {
+                                //util::fail('节日暂停送货上门,请选到店自取');
+                            }
                         }
-                    }
-
-                } else {
-
-                    //好运鲜花批发,选择送货上门必须选必选商品
-//                    if ($ghsShopId == 36523) {
-//                        if ($respond->transType != 4 && $respond->transType != 5) {
-//                            util::fail('请选同城配送或到店自取');
-//                        }
-//                    }
 
-//                    if ($ghsShopId == 36523) {
-//                        if ($respond->actPrice < 50 || $respond->bigNum < 10) {
-//                            $hasMust = array_intersect($ids, [85295]);
-//                            if (empty($hasMust)) {
-//                                util::fail('没满50元且满10扎,请运费必选商品');
-//                            }
-//                        }
-//                        // 按当天计时,把 sendTimeWant 要限制在两天的时间范围之内
-//                        $future = date("Y-m-d", strtotime('+2 day'));
-//                        if (strtotime($respond->sendTimeWant) > strtotime($future)) {
-//                            util::fail('配送日期只能选最近二天');
-//                        }
-//                    }
-
-                }
+                        if ($ghsShopId == 86726) {
+                            //藏花林
+                            if ($respond->transType != 4 && $respond->transType != 5) {
+                                util::fail('请选同城配送或到店自取');
+                            }
+                        }
 
-                if (isset($ghsInfo['home'])) {
-                    if ($ghsInfo['home'] == 0) {
-                        util::fail('暂不支持送货上门,请选其它配送方式');
                     }
-                    $homeAmount = $ghsInfo['homeAmount'] ? floatval($ghsInfo['homeAmount']) : 0;
-                    $homeNum = $ghsInfo['homeNum'] ? floatval($ghsInfo['homeNum']) : 0;
-                    if ($homeAmount > 0 && $homeAmount > $respond->actPrice) {
-                        util::fail("满{$homeAmount}元 可送货上门");
-                    }
-                    if ($homeNum > 0 && $homeNum > $respond->bigNum) {
-                        util::fail("满{$homeNum}扎 可送货上门");
+
+                    if (isset($ghsInfo['home'])) {
+                        if ($ghsInfo['home'] == 0) {
+                            util::fail('暂不支持送货上门,请选其它配送方式');
+                        }
+                        $homeAmount = $ghsInfo['homeAmount'] ? floatval($ghsInfo['homeAmount']) : 0;
+                        $homeNum = $ghsInfo['homeNum'] ? floatval($ghsInfo['homeNum']) : 0;
+                        if ($homeAmount > 0 && $homeAmount > $respond->actPrice) {
+                            util::fail("满{$homeAmount}元 可送货上门");
+                        }
+                        if ($homeNum > 0 && $homeNum > $respond->bigNum) {
+                            util::fail("满{$homeNum}扎 可送货上门");
+                        }
                     }
-                }
 
-            }
+                }
 
-            if ($sendType == 2) {
-                //温州易批花,跑腿,不满100,要选10元的补运费商品
-                if ($ghsShopId == 91115) {
-                    if ($respond->actPrice < 100) {
-                        $transaction->rollBack();
-                        $hasMust = array_intersect($ids, [4449812, 4449811]);
-                        if (empty($hasMust)) {
-                            util::fail('不满100,必选商品 补运费10元');
+                if ($sendType == 2) {
+                    //温州易批花,跑腿,不满100,要选10元的补运费商品
+                    if ($ghsShopId == 91115) {
+                        if ($respond->actPrice < 100) {
+                            $transaction->rollBack();
+                            $hasMust = array_intersect($ids, [4449812, 4449811]);
+                            if (empty($hasMust)) {
+                                util::fail('不满100,必选商品 补运费10元');
+                            }
                         }
                     }
                 }
-            }
-            if ($sendType == 4) {
-                //温州易批花,快递,不满100,要选10元的补运费商品
-                if ($ghsShopId == 91115) {
-                    if ($respond->actPrice < 100) {
-                        $transaction->rollBack();
-                        $hasMust = array_intersect($ids, [4449812, 4449811]);
-                        if (empty($hasMust)) {
-                            util::fail('不满100,必选商品 补运费10元');
+                if ($sendType == 4) {
+                    //温州易批花,快递,不满100,要选10元的补运费商品
+                    if ($ghsShopId == 91115) {
+                        if ($respond->actPrice < 100) {
+                            $transaction->rollBack();
+                            $hasMust = array_intersect($ids, [4449812, 4449811]);
+                            if (empty($hasMust)) {
+                                util::fail('不满100,必选商品 补运费10元');
+                            }
                         }
                     }
                 }
-            }
-            if ($sendType == 3) {
-                //温州易批花,物流,不满200,要选10元的补运费商品
-                if ($ghsShopId == 91115) {
-                    if ($respond->actPrice < 200) {
-                        $transaction->rollBack();
-                        $hasMust = array_intersect($ids, [4449812, 4449811]);
-                        if (empty($hasMust)) {
-                            util::fail('不满200,必选商品 补运费10元');
+                if ($sendType == 3) {
+                    //温州易批花,物流,不满200,要选10元的补运费商品
+                    if ($ghsShopId == 91115) {
+                        if ($respond->actPrice < 200) {
+                            $transaction->rollBack();
+                            $hasMust = array_intersect($ids, [4449812, 4449811]);
+                            if (empty($hasMust)) {
+                                util::fail('不满200,必选商品 补运费10元');
+                            }
                         }
                     }
                 }
+
             }
 
             $transaction->commit();
@@ -922,12 +951,18 @@ class PurchaseController extends BaseController
                     Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                 }
             } else {
+                //标记当天已收一次包装费/运费,岭南批发市场用的功能,只要有成功订单就标记,不再要求金额必须>0
+                $current = date("Y_m_d");
                 if (isset($info->sendType) && $info->sendType == 4) {
-                    //标记当天已收一次包装费,岭南批发市场用的功能
-                    $current = date("Y_m_d");
                     $key = 'ghs_custom_today_has_get_pack_cost_' . $current . '_' . $customId;
                     Yii::$app->redis->executeCommand('SETEX', [$key, 86400, '1']);
                 }
+                noticeUtil::push("运费:" . $info->sendCost . ' sendType:' . $info->sendType, '15280215347');
+                if (isset($info->sendType) && $info->sendType == 0) {
+                    noticeUtil::push("执行到了", '15280215347');
+                    $sendKey = 'ghs_custom_today_has_get_send_cost_' . $current . '_' . $customId;
+                    Yii::$app->redis->executeCommand('SETEX', [$sendKey, 86400, '1']);
+                }
             }
 
             // 复杂分支/关键逻辑:不是预订单,且供货商配置为直接完成流程,则自动确认收货。

+ 52 - 8
app-hd/controllers/RechargeController.php

@@ -12,6 +12,7 @@ use bizHd\order\classes\OrderClass;
 use bizHd\recharge\classes\RechargeSqClass;
 use bizHd\wx\classes\WxOpenClass;
 use bizMall\wx\classes\WxMiniClass;
+use common\components\dateUtil;
 use common\components\dict;
 use common\components\imgUtil;
 use common\components\miniUtil;
@@ -230,18 +231,61 @@ class RechargeController extends BaseController
     {
         $get = Yii::$app->request->get();
         $customId = $get['customId'] ?? 0;
-        $custom = \bizHd\custom\classes\CustomClass::getById($customId, true);
-        if (empty($custom)) {
-            util::fail('没有找到客户');
+        $where = ['mainId' => $this->mainId, 'shopId' => $this->shopId, 'status' => 1];
+        if (!empty($customId)) {
+            $custom = \bizHd\custom\classes\CustomClass::getById($customId, true);
+            if (empty($custom)) {
+                util::fail('没有找到客户');
+            }
+            if ($custom->shopId != $this->shopId) {
+                util::fail('不是你的客户');
+            }
+            $where['customId'] = $customId;
         }
-        if ($custom->shopId != $this->shopId) {
-            util::fail('不是你的客户');
+
+        $searchTime = $get['searchTime'] ?? '';
+        if (!empty($searchTime)) {
+            $startTime = $get['startTime'] ?? '';
+            $endTime = $get['endTime'] ?? '';
+            $period = dateUtil::formatTime($searchTime, $startTime, $endTime);
+            $where['addTime'] = ['between', [$period['startTime'], $period['endTime']]];
         }
-        $where = ['shopId' => $this->shopId, 'customId' => $customId];
-        $list = RechargeClass::getRechargeList($where);
+
+        $channelKey = $get['channelKey'] ?? 'all';
+        $io = null;
+        if (isset($get['io']) && $get['io'] !== '') {
+            if (!in_array((string)$get['io'], ['0', '1'], true)) {
+                util::fail('io参数错误');
+            }
+            $io = (int)$get['io'];
+        }
+        $list = \bizHd\recharge\classes\RechargeClass::getRechargeList($where, $channelKey, $io);
         util::success($list);
     }
 
+    //充值统计
+    public function actionStat()
+    {
+        $lookMoney = \bizGhs\shop\classes\ShopAdminClass::lookMoneyPower($this->shopAdmin, $this->shop);
+        if ($lookMoney == 0) {
+            util::fail('无法查看');
+        }
+
+        $shopAdmin = $this->shopAdmin;
+        if (isset($shopAdmin->super) == false || $shopAdmin->super != 1) {
+            util::fail('超管才能查看');
+        }
+
+//        $adminId = $shopAdmin->adminId ?? 0;
+//        if (in_array($adminId, [2366, 2812, 4004, 3405, 3407])) {
+//            util::fail('暂无权限');
+//        }
+
+        $get = Yii::$app->request->get();
+        $data = \bizHd\recharge\classes\RechargeClass::getStatProfile($this->mainId, $this->shopId, $get);
+        util::success($data);
+    }
+
     //免费续期活动 ssh 2021.2.21
     public function actionRenew()
     {
@@ -454,4 +498,4 @@ class RechargeController extends BaseController
         util::success(['deadline' => $deadline]);
     }
 
-}
+}

+ 34 - 0
app-hd/controllers/ShMethodController.php

@@ -32,7 +32,41 @@ class ShMethodController extends BaseController
         }
 
         try {
+            $customId = $ghs['customId'] ?? 0;
             $configs = ShMethodClass::getAllConfigs($shopId, $mainId);
+
+            if (isset($ghs['homeRule']) && $ghs['homeRule'] == 1) {
+                foreach ($configs as &$config) {
+                    if ($config['style'] == 0) {
+                        $config['status'] = $ghs['home'] ?? 0;
+                        $config['minAmount'] = $ghs['homeAmount'] ?? 0;
+                        $config['minNum'] = $ghs['homeNum'] ?? 0;
+                        $config['unMeet'] = $ghs['homeUnMeet'] ?? 0;
+                        $config['unMeetFee'] = $ghs['homeUnFee'] ?? 0;
+                    }
+                }
+            }
+
+            if ($customId > 0) {
+                $hasPaidSendCost = ShMethodClass::isSendCostPaidToday($customId);
+                $hasPaidPackCost = ShMethodClass::isPaidToday($customId);
+                
+                foreach ($configs as &$config) {
+                    $unMeet = (int)($config['unMeet'] ?? 0);
+                    // 如果是加收运费或加收包装费,并且今天已经收过对应的费用
+                    // 则将前端展示的条件清空(设为0),从而不再显示要收附加费的提示
+                    if ($unMeet === 0 && $hasPaidSendCost) {
+                        $config['minAmount'] = 0;
+                        $config['minNum'] = 0;
+                        $config['unMeetFee'] = 0;
+                    } elseif ($unMeet === 2 && $hasPaidPackCost) {
+                        $config['minAmount'] = 0;
+                        $config['minNum'] = 0;
+                        $config['unMeetFee'] = 0;
+                    }
+                }
+            }
+
             util::success(['method' => $configs]);
         } catch (\Exception $e) {
             util::fail($e->getMessage());

+ 8 - 0
app-hd/controllers/ShopYeChangeController.php

@@ -25,6 +25,14 @@ class ShopYeChangeController extends BaseController
         if (!empty($tx)) {
             $where['tx'] = $tx;
         }
+        // 事件类型
+        if (isset($get['capitalType']) && $get['capitalType'] !== '') {
+            $where['capitalType'] = (int)$get['capitalType'];
+        }
+        // 收支类型筛选:1 收入,0 支出;未传参时不筛选
+        if (isset($get['io']) && $get['io'] !== '') {
+            $where['io'] = (int)$get['io'];
+        }
         $list = ShopYeChangeClass::getChangeList($where);
         util::success($list);
     }

+ 15 - 5
app-mall/controllers/OrderController.php

@@ -38,6 +38,16 @@ class OrderController extends BaseController
     //二维码收款使用
     public $guestAccess = ['order-relate', 'fast-pay'];
 
+    public function actionInform()
+    {
+        $get = Yii::$app->request->get();
+        $hdId = $get['hdId'] ?? 0;
+        $account = $get['account'] ?? 0;
+        $page = $get['page'] ?? '';
+        $userId = $this->userId;
+        noticeUtil::push("零售客户下单报错 hdId:{$hdId} account:{$account} userId:{$userId} page:{$page}", '15280215347');
+    }
+
     //记账单列表 ssh 20250627
     public function actionDebtList()
     {
@@ -493,8 +503,8 @@ class OrderController extends BaseController
                         util::fail("不满足最低消费金额{$hb->minConsume}元");
                     }
                     if ($this->shop->rechargeWeal == 3) {
-                        if(bccomp($custom->balance, $modifyPrice) == -1) {
-							//不要限制提交
+                        if (bccomp($custom->balance, $modifyPrice) == -1) {
+                            //不要限制提交
                             //util::fail('此红包非余额支付不可用(您的余额不足)');
                         }
                     }
@@ -826,7 +836,7 @@ class OrderController extends BaseController
                         util::fail("不满足最低消费金额{$hb->minConsume}元");
                     }
                     if ($this->shop->rechargeWeal == 3) {
-                        if($custom->balance < $modifyPrice) {
+                        if ($custom->balance < $modifyPrice) {
                             util::fail('此红包非余额支付不可用(您的余额不足)');
                         }
                     }
@@ -867,7 +877,7 @@ class OrderController extends BaseController
                 $hb->orderId = $return->id;
                 $hb->save();
             }
-            
+
             $orderId = $return->id;
             $orderSn = $return->orderSn;
             $actPrice = $return->actPrice ?? 0;
@@ -921,7 +931,7 @@ class OrderController extends BaseController
             }
             //支付前验证订单有效性
             OrderService::checkBeforePay($order);
-            
+
             $payWay = dict::getDict('payWay', 'balancePay');
             \bizHd\order\classes\OrderClass::payAfter($order, $payWay);
             $transaction->commit();

+ 218 - 0
biz-ghs/order/classes/ShMethodClass.php

@@ -175,6 +175,224 @@ class ShMethodClass extends BaseClass
         return $result;
     }
 
+    /**
+     * 判断配送方式配置是否未达最低消费(金额或扎数任一不满足即视为未达标)
+     * 与 hdApp affirm-sh-method-panel.checkShMethodBelowMinimum 规则一致
+     *
+     * @param array $config xhShMethod 配置
+     * @param float $actPrice 实付花材金额
+     * @param int|float $bigNum 下单扎数
+     * @return bool
+     */
+    /**
+     * 采购下单后校验 xhShMethod 配送限制
+     * 供 hd PurchaseController::actionCreateOrder 在 createPurchase 之后调用,与旧版 else 分支门店硬编码限制同级
+     *
+     * @param int $shopId 供货商门店 ID
+     * @param int $mainId 供货商商户 ID
+     * @param int $sendType 配送方式,与 xhShMethod.style 一致
+     * @param float $actPrice 下单后实付花材金额
+     * @param int|float $bigNum 下单扎数
+     * @param float $packCost 已写入采购单的包装费
+     * @param float $sendCost 已写入采购单的运费
+     * @param string $wlName 物流公司名称(style=3 时必填)
+     * @param int $customId 客户ID,用于判断当天是否已收过
+     * @param array|object $ghsInfo 客户与该供货商的关系信息(xhGhs)
+     * @return string 空字符串表示通过,否则为需提示用户的错误文案
+     */
+    public static function checkLimit($shopId, $mainId, $sendType, $actPrice, $bigNum, $packCost = 0, $sendCost = 0, $wlName = '', $customId = 0, $ghsInfo = [])
+    {
+        $style = (int)$sendType;
+        if ($style < 0 || $style > 4) {
+            return '配送方式无效';
+        }
+
+        $config = self::getConfig($shopId, $mainId, $style);
+
+        if (empty($config)) {
+            return '配送方式配置异常';
+        }
+
+        if ($style === 0 && !empty($ghsInfo) && isset($ghsInfo['homeRule']) && $ghsInfo['homeRule'] == 1) {
+            // 如果 homeRule == 1,特定字段取xhGhs的设置(优先级最高),其余(如name)保留原配置
+            $config['status'] = $ghsInfo['home'] ?? 0;
+            $config['minAmount'] = $ghsInfo['homeAmount'] ?? 0;
+            $config['minNum'] = $ghsInfo['homeNum'] ?? 0;
+            $config['unMeet'] = $ghsInfo['homeUnMeet'] ?? 0;
+            $config['unMeetFee'] = $ghsInfo['homeUnFee'] ?? 0;
+        }
+
+        $methodName = !empty($config['name']) ? $config['name'] : '该配送方式';
+
+        // 配送方式已禁用,对齐旧逻辑「暂不支持送货上门,请选其它配送方式」
+        if (isset($config['status']) && (int)$config['status'] === 0) {
+            return "暂不支持{$methodName},请选其它配送方式";
+        }
+
+        // 物流需填物流公司,与 hdApp validateBeforeSubmit 一致
+        if ($style === 3 && trim((string)$wlName) === '') {
+            return '请填选物流';
+        }
+
+        $minAmount = isset($config['minAmount']) ? (float)$config['minAmount'] : 0.00;
+        $minNum = isset($config['minNum']) ? (int)$config['minNum'] : 0;
+        
+        // 必须金额和数量同时满足(如果设置了的话),才算“达标”
+        $isBelowMinimum = false;
+        if ($minAmount > 0 && $actPrice < $minAmount) {
+            $isBelowMinimum = true;
+        }
+        if ($minNum > 0 && (float)$bigNum < $minNum) {
+            $isBelowMinimum = true;
+        }
+
+        if (!$isBelowMinimum) {
+            return '';
+        }
+
+        $unMeet = isset($config['unMeet']) ? (int)$config['unMeet'] : 0;
+        $unMeetFee = isset($config['unMeetFee']) ? (float)$config['unMeetFee'] : 0;
+
+        // 不满最低消费且不允许下单
+        if ($unMeet === 1) {
+            if ($minAmount > 0 && (float)$actPrice < $minAmount) {
+                return "满{$minAmount}元 可{$methodName}";
+            }
+            if ($minNum > 0 && (float)$bigNum < $minNum) {
+                return "满{$minNum}扎 可{$methodName}";
+            }
+            return '未达到最低消费,不能下单';
+        }
+
+        // 不满最低消费但允许加收费用时,校验包装费/运费是否已写入采购单,防止前端绕过
+        if (($unMeet === 0 || $unMeet === 2) && $unMeetFee > 0) {
+            // unMeet === 0 加收运费, unMeet === 2 加收包装费
+            $feeToCheck = $unMeet === 2 ? $packCost : $sendCost;
+            
+            // 如果今天已经收过对应的附加费用,则直接通过校验
+            if ($unMeet === 2 && self::isPaidToday($customId)) {
+                return '';
+            }
+            if ($unMeet === 0 && self::isSendCostPaidToday($customId)) {
+                return '';
+            }
+            
+            if (bccomp((string)$feeToCheck, (string)$unMeetFee, 2) < 0) {
+                $feeLabel = $unMeet === 2 ? '包装费' : '运费';
+                return "未达最低消费,需加收{$feeLabel}{$unMeetFee}元";
+            }
+        }
+
+        return '';
+    }
+
+    /**
+     * 判断当天是否已经收过附加费(运费或包装费)
+     * 与其他逻辑共用同一个 Redis Key,保证一天只收一次
+     * @param int $customId 客户ID
+     * @return bool
+     */
+    public static function isPaidToday($customId)
+    {
+        if (empty($customId)) {
+            return false;
+        }
+        $current = date("Y_m_d");
+        $key = 'ghs_custom_today_has_get_pack_cost_' . $current . '_' . $customId;
+        $has = \Yii::$app->redis->executeCommand('GET', [$key]);
+        return (!empty($has) && $has == 1);
+    }
+
+    /**
+     * 判断当天是否已经收过运费
+     * @param int $customId 客户ID
+     * @return bool
+     */
+    public static function isSendCostPaidToday($customId)
+    {
+        if (empty($customId)) {
+            return false;
+        }
+        $current = date("Y_m_d");
+        $key = 'ghs_custom_today_has_get_send_cost_' . $current . '_' . $customId;
+        $has = \Yii::$app->redis->executeCommand('GET', [$key]);
+        return (!empty($has) && $has == 1);
+    }
+
+    /**
+     * 计算采购单应写入的附加费用(不满最低消费时按 unMeet 加收运费或包装费)
+     * 供 createPurchase 前写入 sendCost 和 packCost,与 hdApp syncPackCostByMethod 一致
+     *
+     * @param int $shopId 供货商门店 ID
+     * @param int $mainId 供货商商户 ID
+     * @param int $sendType 配送方式
+     * @param float $itemTotalAmount 花材合计金额(下单前,与前端 commodityPrice 一致)
+     * @param int|float $bigNum 下单扎数
+     * @param int $customId 客户ID,用于判断当天是否已收过
+     * @param array|object $ghsInfo 客户与该供货商的关系信息(xhGhs)
+     * @return array ['sendCost' => 运费, 'packCost' => 包装费]
+     */
+    public static function calcFee($shopId, $mainId, $sendType, $itemTotalAmount, $bigNum, $customId = 0, $ghsInfo = [])
+    {
+        $costs = ['sendCost' => 0, 'packCost' => 0];
+        
+        $style = (int)$sendType;
+        if ($style < 0 || $style > 4) {
+            return $costs;
+        }
+
+        $config = self::getConfig($shopId, $mainId, $style);
+
+        if (empty($config)) {
+            return $costs;
+        }
+
+        if ($style === 0 && !empty($ghsInfo) && isset($ghsInfo['homeRule']) && $ghsInfo['homeRule'] == 1) {
+            // 如果 homeRule == 1,特定字段取xhGhs的设置(优先级最高),其余(如name)保留原配置
+            $config['status'] = $ghsInfo['home'] ?? 0;
+            $config['minAmount'] = $ghsInfo['homeAmount'] ?? 0;
+            $config['minNum'] = $ghsInfo['homeNum'] ?? 0;
+            $config['unMeet'] = $ghsInfo['homeUnMeet'] ?? 0;
+            $config['unMeetFee'] = $ghsInfo['homeUnFee'] ?? 0;
+        }
+
+        // 直接合并 isBelowMinimum 的逻辑,方便理解,不再套用额外的方法
+        $minAmount = isset($config['minAmount']) ? (float)$config['minAmount'] : 0.00;
+        $minNum = isset($config['minNum']) ? (int)$config['minNum'] : 0;
+        
+        // 必须金额和数量同时满足(如果设置了的话),才算“达标”
+        $isBelowMinimum = false;
+        if ($minAmount > 0 && $itemTotalAmount < $minAmount) {
+            $isBelowMinimum = true;
+        }
+        if ($minNum > 0 && (float)$bigNum < $minNum) {
+            $isBelowMinimum = true;
+        }
+
+        // 如果已经达标,不收取附加费用
+        if (!$isBelowMinimum) {
+            return $costs;
+        }
+
+        $unMeet = isset($config['unMeet']) ? (int)$config['unMeet'] : 0;
+        $unMeetFee = isset($config['unMeetFee']) ? (float)$config['unMeetFee'] : 0;
+        
+        if ($unMeetFee > 0) {
+            // unMeet: 0 加收运费(默认),2 加收包装费
+            if ($unMeet === 0) {
+                if (!self::isSendCostPaidToday($customId)) {
+                    $costs['sendCost'] = $unMeetFee;
+                }
+            } elseif ($unMeet === 2) {
+                if (!self::isPaidToday($customId)) {
+                    $costs['packCost'] = $unMeetFee;
+                }
+            }
+        }
+
+        return $costs;
+    }
+
     /**
      * 保存配送方式配置,包含说明项和满减规则
      * @param int $shopId 门店ID

+ 4 - 4
biz-hd/birthday/classes/BirthdayGiftClass.php

@@ -440,7 +440,7 @@ class BirthdayGiftClass extends BaseClass
         $connection = Yii::$app->db;
         $transaction = $connection->beginTransaction();
         try {
-            $custom = CustomClass::modifyBirthday($customId, $shop->id, $params);
+            list($custom, $isUpdateBirthday) = CustomClass::modifyBirthday($customId, $shop->id, $params);
             $levelMap = self::getLevelBenefitMap($shop->mainId, $shop->id);
             $gift = self::createOrUpdateYearRecord($shop, $custom, $levelMap);
             $transaction->commit();
@@ -568,7 +568,7 @@ class BirthdayGiftClass extends BaseClass
                         }
                     }
                 }
-     
+
                 if ($statusFilter < 0 && intval($gift->status) == self::STATUS_NO_BIRTHDAY) {
                     // 全部 Tab 也展示未填写
                 }
@@ -806,7 +806,7 @@ class BirthdayGiftClass extends BaseClass
             return [false, '短信发送失败'];
         }
 
-        // TODO 记录到 xhSms
+        // 记录到 xhSms
         $sms = new SmsClass();
         $sms->add([
             'mainId' => $shop->mainId,
@@ -816,7 +816,7 @@ class BirthdayGiftClass extends BaseClass
             'content' => $msg,
             'type' => 1, // 0通知类型, 1营销类型
         ]);
-        
+
         return [true, ''];
     }
 

+ 38 - 2
biz-hd/custom/classes/CustomClass.php

@@ -27,7 +27,41 @@ class CustomClass extends BaseClass
 
     public static $baseFile = '\bizHd\custom\models\Custom';
 
-    //修改客户生日 ssh 20250814
+    public static function getBalanceStat($where)
+    {
+        $cacheKey = self::getBalanceStatCacheKey($where);
+        $cached = \Yii::$app->redis->executeCommand('GET', [$cacheKey]);
+        if ($cached !== false && $cached !== null && $cached !== '') {
+            $data = json_decode($cached, true);
+            if (is_array($data)) {
+                return $data;
+            }
+        }
+
+        $countWhere = array_merge($where, ['balance>' => 0]);
+        $count = self::getCount($countWhere);
+        $totalBalance = self::sum($where, 'balance');
+        $data = [
+            'count' => intval($count),
+            'totalBalance' => bcadd($totalBalance ?: '0', '0', 2),
+        ];
+        \Yii::$app->redis->executeCommand('SETEX', [$cacheKey, 60, json_encode($data)]);
+        return $data;
+    }
+
+    public static function getBalanceStatCacheKey($where)
+    {
+        return 'hd_custom_balance_stat:' . md5(json_encode($where, JSON_UNESCAPED_UNICODE));
+    }
+
+    /**
+     * 修改客户生日
+     * @param $customId
+     * @param $shopId
+     * @param $params
+     * @return array [custom, bool] custom表示客户数据,bool表示是否变动了生日
+     * @throws \Exception
+     */
     public static function modifyBirthday($customId, $shopId, $params)
     {
         date_default_timezone_set('PRC');
@@ -58,6 +92,8 @@ class CustomClass extends BaseClass
             util::fail('农历没有31号');
         }
 
+        $isUpdateBirthday = $user->birthdayTime == 0;
+
         // 如果 xhUser 中已经设置了生日,则直接取用
         if ($user->birthdayTime != 0) {
             $custom->lunar = $user->lunar;
@@ -122,7 +158,7 @@ class CustomClass extends BaseClass
             $birthdayGift->save();
         }
 
-        return $custom;
+        return [$custom, $isUpdateBirthday];
     }
 
     //用余额支付,客户余额减少 ssh 20250410

+ 256 - 1
biz-hd/recharge/classes/RechargeClass.php

@@ -17,17 +17,92 @@ use bizHd\shop\classes\ShopExtClass;
 use bizHd\shop\classes\MainClass;
 use bizHd\user\classes\UserGrowthClass;
 use bizHd\user\classes\UserIntegralClass;
+use common\components\dateUtil;
 use common\components\dict;
 use common\components\lakala\Lakala;
 use common\components\noticeUtil;
 use common\components\util;
 use Yii;
 use bizHd\base\classes\BaseClass;
+use yii\db\Expression;
 
 class RechargeClass extends BaseClass
 {
 
     public static $baseFile = '\bizHd\recharge\models\Recharge';
+    const STAT_CACHE_TTL = 300; //统计数据缓存时长
+
+    //充值记录
+    public static function getRechargeList($where, $channelKey = 'all', $io = null)
+    {
+        switch ($channelKey) {
+            case 'system':
+                $where['onlinePay'] = 2;
+                break;
+            case 'pay_0':
+                $where['onlinePay!='] = 2;
+                $where['payWay'] = 0;
+                break;
+            case 'pay_1':
+                $where['onlinePay!='] = 2;
+                $where['payWay'] = 1;
+                break;
+            case 'pay_4':
+                $where['onlinePay!='] = 2;
+                $where['payWay'] = 4;
+                break;
+            case 'pay_5':
+                $where['onlinePay!='] = 2;
+                $where['payWay'] = 5;
+                break;
+            case 'other':
+                $where['onlinePay!='] = 2;
+                $where['payWay'] = ['not in', [0, 1, 4, 5]];
+                break;
+            default:
+                break;
+        }
+
+        if ($io === null || $io === '') {
+            return self::getList('*', $where, 'addTime DESC,id DESC');
+        }
+
+        $model = self::getModel();
+        $query = $model->conditionQuery($where)->select('*');
+        if ((int)$io === 1) {
+            $query->andWhere('IFNULL(amount, 0) + IFNULL(giveAmount, 0) > 0');
+        } else {
+            $query->andWhere([
+                'or',
+                ['>', 'settleAmount', 0],
+                ['>', 'clearAmount', 0],
+            ]);
+        }
+
+        return self::getRechargePageList($query, 'addTime DESC,id DESC');
+    }
+
+    private static function getRechargePageList($query, $order = '')
+    {
+        $get = Yii::$app->request->get();
+        $page = isset($get['page']) ? $get['page'] : 1;
+        Yii::$app->params['page'] = $page;
+        $pageSize = isset($get['pageSize']) && !empty($get['pageSize']) ? $get['pageSize'] : Yii::$app->params['pageSize'];
+        $offset = ($page - 1) * $pageSize;
+
+        $clone = clone $query;
+        $count = $clone->count();
+        $totalPage = ceil($count / $pageSize);
+        $data['totalNum'] = $count;
+        $data['totalPage'] = $totalPage;
+        $data['moreData'] = $totalPage > $page ? 1 : 0;
+
+        if (!empty($order)) {
+            $query->orderBy($order);
+        }
+        $data['list'] = $query->offset($offset)->limit($pageSize)->asArray()->all();
+        return $data;
+    }
 
     public static function addRecharge($data)
     {
@@ -382,6 +457,11 @@ class RechargeClass extends BaseClass
             }
         }
 
+        $recharge->settleId = $settleId;
+        $recharge->settleAmount = $settleAmount;
+        $recharge->settleNo = $settleNo;
+        $recharge->save();
+
         $remark = $recharge->remark;
         $change = [
             'customId' => $customId,
@@ -533,4 +613,179 @@ class RechargeClass extends BaseClass
         }
     }
 
-}
+    public static function getStatProfile($mainId, $shopId, $params = [])
+    {
+        $searchTime = $params['searchTime'] ?? 'today';
+        $startTime = $params['startTime'] ?? '';
+        $endTime = $params['endTime'] ?? '';
+        $range = dateUtil::formatTime($searchTime, $startTime, $endTime);
+        $start = $range['startTime'];
+        $end = $range['endTime'];
+        $cacheKey = 'hd_recharge_stat:' . $shopId . '_' . md5($start . '_' . $end);
+        $cache = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
+        if (!empty($cache)) {
+            $data = json_decode($cache, true);
+            if (is_array($data)) {
+                return $data;
+            }
+        }
+
+        $summary = self::getRechargeStatSummary($mainId, $shopId, $start, $end);
+        $channelList = self::getRechargeStatChannelList($mainId, $shopId, $start, $end);
+        $customerList = self::getRechargeStatCustomerList($mainId, $shopId, $start, $end);
+
+        $data = [
+            'summary' => $summary,
+            'channelList' => $channelList,
+            'customerList' => $customerList,
+            'startTime' => $start,
+            'endTime' => $end,
+        ];
+        Yii::$app->redis->executeCommand('SETEX', [$cacheKey, self::STAT_CACHE_TTL, json_encode($data, JSON_UNESCAPED_UNICODE)]);
+        return $data;
+    }
+
+    private static function getPaidQuery($mainId, $shopId, $start, $end)
+    {
+        $model = self::getActiveRecord();
+        return $model::find()
+            ->where([
+                'mainId' => $mainId,
+                'shopId' => $shopId,
+                'payStatus' => 1,
+                'status' => 1,
+            ])
+            ->andWhere(['between', 'addTime', $start, $end]);
+    }
+
+    private static function getRechargeStatSummary($mainId, $shopId, $start, $end)
+    {
+        $row = self::getPaidQuery($mainId, $shopId, $start, $end)
+            ->select([
+                'rechargeCount' => new Expression('SUM(CASE WHEN IFNULL(amount, 0) + IFNULL(giveAmount, 0) > 0 THEN 1 ELSE 0 END)'),
+                'reduceCount' => new Expression('SUM(CASE WHEN IFNULL(settleAmount, 0) > 0 THEN 1 ELSE 0 END)'),
+                'realAmount' => new Expression('IFNULL(SUM(amount), 0)'),
+                'giveAmount' => new Expression('IFNULL(SUM(giveAmount), 0)'),
+                'reduceAmount' => new Expression('IFNULL(SUM(settleAmount), 0)'),
+            ])
+            ->asArray()
+            ->one();
+
+        $realAmount = $row['realAmount'] ?? 0;
+        $giveAmount = $row['giveAmount'] ?? 0;
+        $reduceAmount = $row['reduceAmount'] ?? 0;
+        return [
+            'rechargeAmount' => self::moneyAdd($realAmount, $giveAmount),
+            'rechargeCount' => intval($row['rechargeCount'] ?? 0),
+            'reduceAmount' => self::moneyValue($reduceAmount),
+            'reduceCount' => intval($row['reduceCount'] ?? 0),
+            'realAmount' => self::moneyValue($realAmount),
+        ];
+    }
+
+    private static function getRechargeStatChannelList($mainId, $shopId, $start, $end)
+    {
+        $rows = self::getPaidQuery($mainId, $shopId, $start, $end)
+            ->select([
+                'channelKey' => new Expression("IF(onlinePay = 2, 'system', CONCAT('pay_', payWay))"),
+                'rechargeCount' => new Expression('SUM(CASE WHEN IFNULL(amount, 0) + IFNULL(giveAmount, 0) > 0 THEN 1 ELSE 0 END)'),
+                'reduceCount' => new Expression('SUM(CASE WHEN IFNULL(settleAmount, 0) > 0 THEN 1 ELSE 0 END)'),
+                'realAmount' => new Expression('IFNULL(SUM(amount), 0)'),
+                'giveAmount' => new Expression('IFNULL(SUM(giveAmount), 0)'),
+                'reduceAmount' => new Expression('IFNULL(SUM(settleAmount), 0)'),
+            ])
+            ->groupBy(new Expression("IF(onlinePay = 2, 'system', CONCAT('pay_', payWay))"))
+            ->asArray()
+            ->all();
+
+        $payWayName = dict::getDict('payWayName');
+        $defaultList = [
+            'system' => '系统',
+            'pay_0' => '线下微信',
+            'pay_1' => '线下支付宝',
+            'pay_4' => '现金',
+            'pay_5' => '银行卡',
+        ];
+        $map = [];
+        foreach ($rows as $row) {
+            $key = $row['channelKey'] ?? '';
+            $payWay = intval(str_replace('pay_', '', $key));
+            $map[$key] = self::buildStatRow(
+                $defaultList[$key] ?? ($payWayName[$payWay] ?? '其它'),
+                $row
+            );
+        }
+
+        $list = [];
+        foreach ($defaultList as $key => $name) {
+            $list[] = $map[$key] ?? self::emptyStatRow($name);
+            unset($map[$key]);
+        }
+        foreach ($map as $item) {
+            $list[] = $item;
+        }
+        return $list;
+    }
+
+    private static function getRechargeStatCustomerList($mainId, $shopId, $start, $end)
+    {
+        $rows = self::getPaidQuery($mainId, $shopId, $start, $end)
+            ->select([
+                'customId',
+                'customName',
+                'rechargeCount' => new Expression('SUM(CASE WHEN IFNULL(amount, 0) + IFNULL(giveAmount, 0) > 0 THEN 1 ELSE 0 END)'),
+                'reduceCount' => new Expression('SUM(CASE WHEN IFNULL(settleAmount, 0) > 0 THEN 1 ELSE 0 END)'),
+                'realAmount' => new Expression('IFNULL(SUM(amount), 0)'),
+                'giveAmount' => new Expression('IFNULL(SUM(giveAmount), 0)'),
+                'reduceAmount' => new Expression('IFNULL(SUM(settleAmount), 0)'),
+            ])
+            ->groupBy(['customId', 'customName'])
+            ->orderBy(new Expression('IFNULL(SUM(amount), 0) + IFNULL(SUM(giveAmount), 0) DESC'))
+            ->limit(100)
+            ->asArray()
+            ->all();
+
+        $list = [];
+        foreach ($rows as $row) {
+            $list[] = self::buildStatRow($row['customName'] ?: '未命名', $row);
+        }
+        return $list;
+    }
+
+    private static function buildStatRow($name, $row)
+    {
+        $realAmount = $row['realAmount'] ?? 0;
+        $giveAmount = $row['giveAmount'] ?? 0;
+        return [
+            'customId' => $row['customId'] ?? 0,
+            'name' => $name,
+            'rechargeAmount' => self::moneyAdd($realAmount, $giveAmount),
+            'rechargeCount' => intval($row['rechargeCount'] ?? 0),
+            'reduceAmount' => self::moneyValue($row['reduceAmount'] ?? 0),
+            'reduceCount' => intval($row['reduceCount'] ?? 0),
+            'realAmount' => self::moneyValue($realAmount),
+        ];
+    }
+
+    private static function emptyStatRow($name)
+    {
+        return [
+            'name' => $name,
+            'rechargeAmount' => '0.00',
+            'rechargeCount' => 0,
+            'reduceAmount' => '0.00',
+            'reduceCount' => 0,
+            'realAmount' => '0.00',
+        ];
+    }
+
+    private static function moneyAdd($left, $right)
+    {
+        return self::moneyValue(bcadd((string)$left, (string)$right, 2));
+    }
+
+    private static function moneyValue($amount)
+    {
+        return number_format((float)$amount, 2, '.', '');
+    }
+}

+ 8 - 0
common/components/dateUtil.php

@@ -99,6 +99,14 @@ class dateUtil
                     $endTime = date("Ymd", strtotime($endTime));
                 }
                 break;
+            case 'all':
+                $startTime = "2015-01-01 00:00:00"; //用项目起始日期做开始时间
+                $endTime = date("Y-m-d 23:59:59");
+                if ($Stat) {
+                    $startTime = "20150101";
+                    $endTime = date("Ymd");
+                }
+                break;
             default:
                 //今天
                 $startTime = date("Y-m-d 00:00:00");

+ 2 - 2
common/components/sms.php

@@ -89,7 +89,7 @@ class sms
             util::fail('没有找到平台');
         }
         //$name = isset($open['name']) ? $open['name'] : '花卉宝';
-        $name = '花掌柜';
+        $name = '厦门中花汇';
         $sign = isset($merchant) == true ? "【{$merchant['name']}】" : "【{$name}】";
         $msg = $sign . $msg;
 
@@ -116,4 +116,4 @@ class sms
         $sms->sendVariableSMS($msg, $params);
     }
 
-}
+}