shish 2 месяцев назад
Родитель
Сommit
b65b959c92
2 измененных файлов с 100 добавлено и 104 удалено
  1. 95 95
      biz-ghs/clear/classes/OrderCgClearClass.php
  2. 5 9
      console/controllers/ClearController.php

+ 95 - 95
biz-ghs/clear/classes/OrderCgClearClass.php

@@ -740,104 +740,114 @@ class OrderCgClearClass extends BaseClass
         return '(' . $prefix . 'amount IS NULL OR ' . $prefix . 'amount = 0 OR ' . $prefix . 'amount = \'0\' OR ' . $prefix . 'amount = \'0.00\')';
     }
 
-    protected static function pairAmountKey($orderId, $cgId)
-    {
-        return intval($orderId) . '_' . intval($cgId);
-    }
-
     /**
-     * @return array<string,string> orderId_cgId => amount
+     * 只查 amount=0 的关系行(带 clearStyle,避免再查整单 xhClear)
+     * @return array[] id, clearId, orderId, cgId, clearStyle
      */
-    public static function buildPairAmountMap($clear)
+    public static function fetchZeroAmountRelationBatch($cursorId, $limit)
     {
-        $pairs = self::buildPairsFromClear($clear);
-        $map = [];
-        foreach ($pairs as $pair) {
-            $amount = self::normalizeAmount($pair['amount'] ?? 0);
-            if (bccomp($amount, '0', 2) <= 0) {
-                continue;
-            }
-            $map[self::pairAmountKey($pair['orderId'] ?? 0, $pair['cgId'] ?? 0)] = $amount;
+        $relTable = self::$baseFile::tableName();
+        $clearTable = Clear::tableName();
+        $sql = 'SELECT r.id, r.clearId, r.orderId, r.cgId, c.clearStyle FROM ' . $relTable . ' r'
+            . ' INNER JOIN ' . $clearTable . ' c ON c.id = r.clearId'
+            . ' WHERE ' . self::zeroAmountWhereSql('r');
+        $params = [];
+        if ($cursorId !== null) {
+            $sql .= ' AND r.id < :cursorId';
+            $params[':cursorId'] = intval($cursorId);
         }
-        return $map;
+        $sql .= ' ORDER BY r.id DESC LIMIT ' . intval($limit);
+        return Yii::$app->db->createCommand($sql)->bindValues($params)->queryAll();
     }
 
-    public static function resolveAmountForRelationRow(array $row, array $pairAmountMap)
+    /**
+     * 按关系行 orderId/cgId + clearStyle 反查应对应的 actPrice(不展开整单 saleIds/purchaseIds)
+     */
+    public static function resolveAmountForRelationRowDirect(array $row)
     {
+        $clearStyle = intval($row['clearStyle'] ?? 0);
         $orderId = intval($row['orderId'] ?? 0);
         $cgId = intval($row['cgId'] ?? 0);
-        $key = self::pairAmountKey($orderId, $cgId);
-        if (isset($pairAmountMap[$key])) {
-            return $pairAmountMap[$key];
-        }
-        if ($cgId === 0 && $orderId > 0) {
-            $legacyKey = self::pairAmountKey(0, $orderId);
-            if (isset($pairAmountMap[$legacyKey])) {
-                return $pairAmountMap[$legacyKey];
+        $gys2KmGys = intval(dict::getDict('clearStyle', 'gys2KmGys'));
+        $gys2Hd = intval(dict::getDict('clearStyle', 'gys2Hd'));
+        $hd2Gys = intval(dict::getDict('clearStyle', 'hd2Gys'));
+
+        if ($clearStyle === $gys2KmGys) {
+            $ghsCgId = $cgId > 0 ? $cgId : $orderId;
+            return self::amountFromGhsCgOrderId($ghsCgId);
+        }
+        if ($clearStyle === $gys2Hd && $orderId > 0) {
+            $amount = self::amountFromGhsOrderId($orderId);
+            if ($amount !== null) {
+                return $amount;
             }
-            $cg = PurchaseOrderClass::getById($orderId);
-            if (!empty($cg)) {
-                $amount = self::resolveDebtAmount($cg);
-                if (bccomp($amount, '0', 2) > 0) {
-                    return $amount;
-                }
+        }
+        if ($clearStyle === $hd2Gys && $cgId > 0) {
+            $amount = self::amountFromHdPurchaseId($cgId);
+            if ($amount !== null) {
+                return $amount;
             }
         }
         if ($orderId > 0) {
-            $order = OrderClass::getById($orderId);
-            if (!empty($order)) {
-                $amount = self::resolveDebtAmount($order);
-                if (bccomp($amount, '0', 2) > 0) {
-                    return $amount;
-                }
+            $amount = self::amountFromGhsOrderId($orderId);
+            if ($amount !== null) {
+                return $amount;
             }
         }
         if ($cgId > 0) {
-            $purchase = PurchaseClass::getById($cgId);
-            if (!empty($purchase)) {
-                $amount = self::resolveDebtAmount($purchase);
-                if (bccomp($amount, '0', 2) > 0) {
-                    return $amount;
-                }
-            }
-            $ghsCg = PurchaseOrderClass::getById($cgId);
-            if (!empty($ghsCg)) {
-                $amount = self::resolveDebtAmount($ghsCg);
-                if (bccomp($amount, '0', 2) > 0) {
-                    return $amount;
-                }
+            $amount = self::amountFromHdPurchaseId($cgId);
+            if ($amount !== null) {
+                return $amount;
             }
+            return self::amountFromGhsCgOrderId($cgId);
         }
         return null;
     }
 
-    public static function countZeroAmountRelationRows()
+    protected static function amountFromGhsOrderId($orderId)
     {
-        $table = self::$baseFile::tableName();
-        return intval(Yii::$app->db->createCommand(
-            'SELECT COUNT(*) FROM ' . $table . ' WHERE ' . self::zeroAmountWhereSql()
-        )->queryScalar());
+        $orderId = intval($orderId);
+        if ($orderId <= 0) {
+            return null;
+        }
+        $order = OrderClass::getById($orderId);
+        return self::amountFromEntity($order);
     }
 
-    /**
-     * @return array[] id, clearId, orderId, cgId
-     */
-    public static function fetchZeroAmountRelationBatch($cursorId, $limit)
+    protected static function amountFromHdPurchaseId($cgId)
     {
-        $table = self::$baseFile::tableName();
-        $sql = 'SELECT id, clearId, orderId, cgId FROM ' . $table
-            . ' WHERE ' . self::zeroAmountWhereSql();
-        $params = [];
-        if ($cursorId !== null) {
-            $sql .= ' AND id < :cursorId';
-            $params[':cursorId'] = intval($cursorId);
+        $cgId = intval($cgId);
+        if ($cgId <= 0) {
+            return null;
         }
-        $sql .= ' ORDER BY id DESC LIMIT ' . intval($limit);
-        return Yii::$app->db->createCommand($sql)->bindValues($params)->queryAll();
+        $purchase = PurchaseClass::getById($cgId);
+        return self::amountFromEntity($purchase);
+    }
+
+    protected static function amountFromGhsCgOrderId($cgId)
+    {
+        $cgId = intval($cgId);
+        if ($cgId <= 0) {
+            return null;
+        }
+        $cg = PurchaseOrderClass::getById($cgId);
+        return self::amountFromEntity($cg);
+    }
+
+    protected static function amountFromEntity($entity)
+    {
+        if (empty($entity)) {
+            return null;
+        }
+        $amount = self::resolveDebtAmount($entity);
+        if (bccomp($amount, '0', 2) <= 0) {
+            return null;
+        }
+        return $amount;
     }
 
     /**
-     * @param array[] $rows
+     * @param array[] $rows fetchZeroAmountRelationBatch 的结果
      * @return array{updated:int,skipped:int}
      */
     public static function patchZeroAmountRows(array $rows, $dryRun = false)
@@ -845,45 +855,35 @@ class OrderCgClearClass extends BaseClass
         if (empty($rows)) {
             return ['updated' => 0, 'skipped' => 0];
         }
-        $clearIds = array_values(array_unique(array_filter(array_map('intval', array_column($rows, 'clearId')))));
-        $clearList = ClearClass::getAllByCondition(['id' => ['in', $clearIds]], null, '*', null);
-        $clearMap = [];
-        if (!empty($clearList)) {
-            foreach ($clearList as $clear) {
-                $id = is_array($clear) ? ($clear['id'] ?? 0) : ($clear->id ?? 0);
-                if ($id > 0) {
-                    $clearMap[intval($id)] = $clear;
-                }
-            }
-        }
-        $pairMaps = [];
-        foreach ($clearIds as $clearId) {
-            if (isset($clearMap[$clearId])) {
-                $pairMaps[$clearId] = self::buildPairAmountMap($clearMap[$clearId]);
-            } else {
-                $pairMaps[$clearId] = [];
-            }
-        }
-
         $table = self::$baseFile::tableName();
         $updated = 0;
         $skipped = 0;
         foreach ($rows as $row) {
             $relId = intval($row['id'] ?? 0);
-            $clearId = intval($row['clearId'] ?? 0);
-            if ($relId <= 0 || $clearId <= 0) {
+            if ($relId <= 0) {
                 $skipped++;
                 continue;
             }
-            $amount = self::resolveAmountForRelationRow($row, $pairMaps[$clearId] ?? []);
-            if ($amount === null || bccomp($amount, '0', 2) <= 0) {
+            $amount = self::resolveAmountForRelationRowDirect($row);
+            if ($amount === null) {
                 $skipped++;
                 continue;
             }
             if (!$dryRun) {
-                Yii::$app->db->createCommand()->update($table, ['amount' => $amount], ['id' => $relId])->execute();
+                $affected = Yii::$app->db->createCommand(
+                    'UPDATE ' . $table . ' SET amount = :amount WHERE id = :id AND ' . self::zeroAmountWhereSql()
+                )->bindValues([
+                    ':amount' => $amount,
+                    ':id' => $relId,
+                ])->execute();
+                if ($affected > 0) {
+                    $updated++;
+                } else {
+                    $skipped++;
+                }
+            } else {
+                $updated++;
             }
-            $updated++;
         }
         return ['updated' => $updated, 'skipped' => $skipped];
     }

+ 5 - 9
console/controllers/ClearController.php

@@ -108,7 +108,7 @@ class ClearController extends Controller
     }
 
     /**
-     * 补写 xhOrderCgClear 中 amount=0 的行(取关联订单/采购单 actPrice)
+     * 补写 xhOrderCgClear 中 amount=0 的行:只查零金额行 → 按 orderId/cgId 反查 actPrice → 按 id 更新
      *
      * 用法:
      *   php yii clear/patch-order-cg-clear-amount --dryRun=1 --limit=1000
@@ -125,7 +125,6 @@ class ClearController extends Controller
         }
 
         $this->backfillProgressKey = 'amount';
-        $pending = OrderCgClearClass::countZeroAmountRelationRows();
 
         if ($this->reset) {
             $this->clearBackfillProgress();
@@ -139,8 +138,7 @@ class ClearController extends Controller
         $batchNo = 0;
 
         $this->stdout(sprintf(
-            "补写 amount | 待处理约 %d 行 | dryRun=%d batchSize=%d sleepMs=%d limit=%d | 续跑 id<%s | 进度=%s\n",
-            $pending,
+            "补写 amount(仅查 amount=0 行)| dryRun=%d batchSize=%d sleepMs=%d limit=%d | 续跑 id<%s | 进度=%s\n",
             (int)$this->dryRun,
             $this->batchSize,
             $this->sleepMs,
@@ -185,7 +183,7 @@ class ClearController extends Controller
             }
 
             $this->stdout(sprintf(
-                "第 %d 批:扫描 %d 行,补写 %d,跳过 %d,checkpoint id=%d\n",
+                "第 %d 批:amount=0 行 %d 条,补写 %d,跳过 %d,checkpoint id=%d\n",
                 $batchNo,
                 count($rows),
                 $batchUpdated,
@@ -202,13 +200,11 @@ class ClearController extends Controller
         if (!$this->dryRun && $cursorId !== null) {
             $this->stdout("进度已保存,下次从 id < {$cursorId} 继续\n");
         }
-        $remaining = OrderCgClearClass::countZeroAmountRelationRows();
         $this->stdout(sprintf(
-            "完成:处理 %d 行,补写 %d,跳过 %d,剩余 amount=0 约 %d 行\n",
+            "完成:处理 amount=0 行 %d 条,补写 %d,跳过 %d\n",
             $total,
             $updated,
-            $skipped,
-            $remaining
+            $skipped
         ));
         return ExitCode::OK;
     }