Ver Fonte

批量修改价格

shish há 2 meses atrás
pai
commit
8f45b3270b
1 ficheiros alterados com 129 adições e 8 exclusões
  1. 129 8
      app-ghs/controllers/ProductController.php

+ 129 - 8
app-ghs/controllers/ProductController.php

@@ -768,7 +768,16 @@ class ProductController extends BaseController
         util::success(['list' => $data]);
     }
 
-    //批量改价
+    /**
+     * 职责:商家后台批量修改花材价格(批发价、零售价、会员价)
+     * 入参:HTTP POST 数据
+     * 返回:修改成功或失败消息的 JSON
+     * 副作用:会批量保存多条商品价格信息,一次性批量往 xhGhsPriceChange 表插入改价日志
+     * 关键边界:
+     * 1. 提取循环体内部关于分店管理员的重复 SQL 查询至外层并作 Map 映射。
+     * 2. 大批量合并商品查询,一次性拉出总店和分店下所有关联的商品数据。
+     * 3. 收集所有改价日志后采用 bulk-insert 方式一键提交,降低高并发下的事务锁冲突和 RTT 开销。
+     */
     public function actionBatchChangePrice()
     {
         $shop = $this->shop;
@@ -853,6 +862,54 @@ class ProductController extends BaseController
             }
 
             $productList = ProductClass::getAllByCondition(['id' => ['in', $ids]], null, '*', 'id', true);
+
+            // ==================== 【性能优化1】提前收集所有 mainId 和 itemId ====================
+            $ptItemIds = [];
+            foreach ($productList as $productInfo) {
+                if (!empty($productInfo->itemId)) {
+                    $ptItemIds[] = (int)$productInfo->itemId;
+                }
+            }
+            $ptItemIds = array_unique($ptItemIds);
+
+            $mainIds = [(int)$this->mainId];
+            if ($default == 1 && isset($shop->dataSync) && $shop->dataSync == 1) {
+                foreach ($chainShopList as $chain) {
+                    if ($chain->id != $shop->id && !empty($chain->mainId)) {
+                        $mainIds[] = (int)$chain->mainId;
+                    }
+                }
+            }
+            $mainIds = array_unique($mainIds);
+
+            // ==================== 【性能优化2】一次性查出总店及直营分店的所有相关商品记录 ====================
+            $productMap = []; // 存储结构:$productMap[mainId][itemId] = product_model
+            if (!empty($ptItemIds) && !empty($mainIds)) {
+                $allDbProducts = ProductClass::getAllByCondition([
+                    'itemId' => ['in', $ptItemIds],
+                    'mainId' => ['in', $mainIds],
+                    'delStatus' => 0
+                ], null, '*', 'id', true);
+                foreach ($allDbProducts as $p) {
+                    $productMap[(int)$p->mainId][(int)$p->itemId] = $p;
+                }
+            }
+
+            // ==================== 【性能优化3】外提并缓存直营分店的管理员信息,避免在循环内部重复 SELECT ====================
+            $chainStaffMap = [];
+            if ($default == 1 && isset($shop->dataSync) && $shop->dataSync == 1) {
+                foreach ($chainShopList as $chain) {
+                    if ($chain->id == $shop->id) {
+                        continue;
+                    }
+                    $chainMainId = $chain->mainId ?? 0;
+                    $staff = ShopAdminClass::getByCondition(['mainId' => $chainMainId, 'adminId' => $adminId], true);
+                    $chainStaffMap[$chain->id] = $staff;
+                }
+            }
+
+            $priceChangeRows = []; // 存储所有待批量写入的改价日志记录
+
             foreach ($arr as $product) {
 
                 $productId = $product['id'];
@@ -886,24 +943,88 @@ class ProductController extends BaseController
                 if ($price > $skPrice) {
                     util::fail($productName . ' 零售价要大于批发价');
                 }
-                $ptItemId = $productInfo->itemId;
-                ProductClass::changeSinglePrice($shop, $ptItemId, $price, $skPrice, $hjPrice, $changeParams);
+                $ptItemId = (int)$productInfo->itemId;
+
+                // ==================== 【性能优化4】内存更新商品价格,收集待批量插入的改价记录 ====================
+                $mainShopProduct = $productMap[(int)$this->mainId][$ptItemId] ?? null;
+                if (!empty($mainShopProduct)) {
+                    $mainShopProduct->price = $price;
+                    $mainShopProduct->skPrice = $skPrice;
+                    $mainShopProduct->hjPrice = $hjPrice;
+                    $mainShopProduct->save(false); // 避免多余的基础规则验证,提升存储性能
+
+                    $priceChangeRows[] = [
+                        'ptStyle' => 2,
+                        'sjId' => (int)$shop->sjId,
+                        'mainId' => (int)$this->mainId,
+                        'itemId' => (int)$mainShopProduct->id,
+                        'ptItemId' => $ptItemId,
+                        'price' => $price,
+                        'skPrice' => $skPrice,
+                        'hjPrice' => $hjPrice,
+                        'staffId' => (int)$shopAdmin->id,
+                        'staffName' => $shopAdmin->name ?? '',
+                        'name' => $mainShopProduct->name ?? '',
+                        'cover' => $mainShopProduct->cover ?? '',
+                        'event' => ($changeType == 'cg' ? '采购后修改' : '修改'),
+                        'type' => ($changeType == 'cg' ? 1 : 0),
+                        'targetId' => (int)$targetId,
+                        'addTime' => date('Y-m-d H:i:s'),
+                    ];
+                }
+
                 //在首店修改需要同步到所有直营店
                 if ($default == 1 && isset($shop->dataSync) && $shop->dataSync == 1) {
                     foreach ($chainShopList as $chain) {
                         if ($chain->id == $shop->id) {
                             continue;
                         }
-                        $chainMainId = $chain->mainId ?? 0;
-                        $staff = ShopAdminClass::getByCondition(['mainId' => $chainMainId, 'adminId' => $adminId], true);
+                        $chainMainId = (int)($chain->mainId ?? 0);
+                        
+                        $staff = $chainStaffMap[$chain->id] ?? null;
                         $staffId = $staff->id ?? 0;
                         $staffName = $staff->name ?? '';
-                        $changeParams2 = ['staffId' => $staffId, 'staffName' => $staffName, 'changeType' => $changeType, 'targetId' => $targetId];
-                        ProductClass::changeSinglePrice($chain, $ptItemId, $price, $skPrice, $hjPrice, $changeParams2);
+
+                        $chainProduct = $productMap[$chainMainId][$ptItemId] ?? null;
+                        if (!empty($chainProduct)) {
+                            $chainProduct->price = $price;
+                            $chainProduct->skPrice = $skPrice;
+                            $chainProduct->hjPrice = $hjPrice;
+                            $chainProduct->save(false);
+
+                            $priceChangeRows[] = [
+                                'ptStyle' => 2,
+                                'sjId' => (int)$chain->sjId,
+                                'mainId' => $chainMainId,
+                                'itemId' => (int)$chainProduct->id,
+                                'ptItemId' => $ptItemId,
+                                'price' => $price,
+                                'skPrice' => $skPrice,
+                                'hjPrice' => $hjPrice,
+                                'staffId' => (int)$staffId,
+                                'staffName' => $staffName,
+                                'name' => $chainProduct->name ?? '',
+                                'cover' => $chainProduct->cover ?? '',
+                                'event' => ($changeType == 'cg' ? '采购后修改' : '修改'),
+                                'type' => ($changeType == 'cg' ? 1 : 0),
+                                'targetId' => (int)$targetId,
+                                'addTime' => date('Y-m-d H:i:s'),
+                            ];
+                        }
                     }
                 }
             }
 
+            // ==================== 【性能优化5】大批量合并 INSERT 写入,避免循环体内频繁单条写入数据库 ====================
+            if (!empty($priceChangeRows)) {
+                $fieldNames = array_keys($priceChangeRows[0]);
+                Yii::$app->db->createCommand()->batchInsert(
+                    'xhGhsPriceChange',
+                    $fieldNames,
+                    $priceChangeRows
+                )->execute();
+            }
+
             $mainId = $shop->mainId ?? 0;
             if (!empty($mainId)) {
                 //提醒零售收银台界面要刷新,多处要修改,关键词 modify_price_remind_cashier
@@ -931,7 +1052,7 @@ class ProductController extends BaseController
             $msg = $e->getMessage();
             Yii::info("修改失败原因:" . $msg);
             noticeUtil::push("修改价格出现失败情况,原因:" . $msg, '15280215347');
-            util::fail('修改失败');
+            util::fail('修改失败' . $msg);
         }
 
     }