|
|
@@ -3,13 +3,10 @@
|
|
|
namespace bizGhs\clear\classes;
|
|
|
|
|
|
use bizGhs\base\classes\BaseClass;
|
|
|
-use bizGhs\clear\models\Clear;
|
|
|
use bizGhs\order\classes\OrderClass;
|
|
|
use bizGhs\order\classes\PurchaseOrderClass;
|
|
|
use bizHd\purchase\classes\PurchaseClass;
|
|
|
use bizHd\purchase\classes\PurchaseClearClass;
|
|
|
-use common\components\dict;
|
|
|
-use Yii;
|
|
|
|
|
|
class OrderCgClearClass extends BaseClass
|
|
|
{
|
|
|
@@ -25,16 +22,16 @@ class OrderCgClearClass extends BaseClass
|
|
|
if (empty($orderList)) {
|
|
|
return [];
|
|
|
}
|
|
|
- $purchaseIds = [];
|
|
|
+ $hdPurchaseIds = [];
|
|
|
foreach ($orderList as $order) {
|
|
|
$purchaseId = is_array($order) ? ($order['purchaseId'] ?? 0) : ($order->purchaseId ?? 0);
|
|
|
if (!empty($purchaseId)) {
|
|
|
- $purchaseIds[] = $purchaseId;
|
|
|
+ $hdPurchaseIds[] = $purchaseId;
|
|
|
}
|
|
|
}
|
|
|
$cgMap = [];
|
|
|
- if (!empty($purchaseIds)) {
|
|
|
- $cgList = PurchaseClass::getByIds(array_unique($purchaseIds));
|
|
|
+ if (!empty($hdPurchaseIds)) {
|
|
|
+ $cgList = PurchaseClass::getByIds(array_unique($hdPurchaseIds));
|
|
|
if (!empty($cgList)) {
|
|
|
$cgMap = array_column($cgList, null, 'id');
|
|
|
}
|
|
|
@@ -65,16 +62,16 @@ class OrderCgClearClass extends BaseClass
|
|
|
if (empty($purchaseList)) {
|
|
|
return [];
|
|
|
}
|
|
|
- $saleIds = [];
|
|
|
+ $ghsOrderIds = [];
|
|
|
foreach ($purchaseList as $purchase) {
|
|
|
$saleId = is_array($purchase) ? ($purchase['saleId'] ?? 0) : ($purchase->saleId ?? 0);
|
|
|
if (!empty($saleId)) {
|
|
|
- $saleIds[] = $saleId;
|
|
|
+ $ghsOrderIds[] = $saleId;
|
|
|
}
|
|
|
}
|
|
|
$orderMap = [];
|
|
|
- if (!empty($saleIds)) {
|
|
|
- $orderList = OrderClass::getByIds(array_unique($saleIds));
|
|
|
+ if (!empty($ghsOrderIds)) {
|
|
|
+ $orderList = OrderClass::getByIds(array_unique($ghsOrderIds));
|
|
|
if (!empty($orderList)) {
|
|
|
$orderMap = array_column($orderList, null, 'id');
|
|
|
}
|
|
|
@@ -101,7 +98,7 @@ class OrderCgClearClass extends BaseClass
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * gys2KmGys:purchaseIds 为 xhGhsCgOrder,cgId 存基地采购单 id,orderId=0
|
|
|
+ * gys2KmGys:cgId 存 xhGhsCgOrder.id,orderId=0
|
|
|
*/
|
|
|
public static function buildPairsFromGhsCgOrders($cgList)
|
|
|
{
|
|
|
@@ -126,55 +123,6 @@ class OrderCgClearClass extends BaseClass
|
|
|
return $pairs;
|
|
|
}
|
|
|
|
|
|
- public static function getRelationClearStyles()
|
|
|
- {
|
|
|
- return [
|
|
|
- intval(dict::getDict('clearStyle', 'hd2Gys')),
|
|
|
- intval(dict::getDict('clearStyle', 'gys2Hd')),
|
|
|
- intval(dict::getDict('clearStyle', 'gys2KmGys')),
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- public static function isRelationClearStyle($clearStyle)
|
|
|
- {
|
|
|
- return in_array(intval($clearStyle), self::getRelationClearStyles(), true);
|
|
|
- }
|
|
|
-
|
|
|
- public static function buildPairsFromClear($clear)
|
|
|
- {
|
|
|
- $clearStyle = intval(is_object($clear) ? ($clear->clearStyle ?? 0) : ($clear['clearStyle'] ?? 0));
|
|
|
- if (!self::isRelationClearStyle($clearStyle)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $saleIds = is_object($clear) ? ($clear->saleIds ?? '') : ($clear['saleIds'] ?? '');
|
|
|
- $purchaseIds = is_object($clear) ? ($clear->purchaseIds ?? '') : ($clear['purchaseIds'] ?? '');
|
|
|
- $gys2KmGys = intval(dict::getDict('clearStyle', 'gys2KmGys'));
|
|
|
- if ($clearStyle === $gys2KmGys) {
|
|
|
- $cgArr = self::parseIds($purchaseIds);
|
|
|
- if (empty($cgArr)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $cgList = PurchaseOrderClass::getAllByCondition(['id' => ['in', $cgArr]], null, '*', null, true);
|
|
|
- return self::buildPairsFromGhsCgOrders($cgList);
|
|
|
- }
|
|
|
- $saleArr = self::parseIds($saleIds);
|
|
|
- if (!empty($saleArr)) {
|
|
|
- $orderList = OrderClass::getByIds($saleArr);
|
|
|
- if (!empty($orderList)) {
|
|
|
- return self::buildPairsFromOrders($orderList);
|
|
|
- }
|
|
|
- }
|
|
|
- $cgArr = self::parseIds($purchaseIds);
|
|
|
- if (empty($cgArr)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $purchaseList = PurchaseClass::getAllByCondition(['id' => ['in', $cgArr]], null, '*', null, true);
|
|
|
- if (empty($purchaseList)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- return self::buildPairsFromPurchases($purchaseList);
|
|
|
- }
|
|
|
-
|
|
|
public static function bindRelations($clear, $pairs, $status = self::STATUS_AWAIT_PAY)
|
|
|
{
|
|
|
$clearId = is_object($clear) ? ($clear->id ?? 0) : ($clear['id'] ?? 0);
|
|
|
@@ -294,393 +242,6 @@ class OrderCgClearClass extends BaseClass
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- public static function backfillFromClear($clear, $skipExistsCheck = false)
|
|
|
- {
|
|
|
- $clearId = is_object($clear) ? ($clear->id ?? 0) : ($clear['id'] ?? 0);
|
|
|
- if (empty($clearId)) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (!$skipExistsCheck) {
|
|
|
- $exists = self::getByCondition(['clearId' => $clearId], true);
|
|
|
- if (!empty($exists)) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- if (!self::isRelationClearStyle(is_object($clear) ? ($clear->clearStyle ?? 0) : ($clear['clearStyle'] ?? 0))) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $clearStyle = intval(is_object($clear) ? ($clear->clearStyle ?? 0) : ($clear['clearStyle'] ?? 0));
|
|
|
- if ($clearStyle === intval(dict::getDict('clearStyle', 'gys2KmGys'))) {
|
|
|
- self::migrateLegacyGys2KmGysRowsByClearId($clearId, false);
|
|
|
- }
|
|
|
- $pairs = self::buildPairsFromClear($clear);
|
|
|
- if (empty($pairs)) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $status = intval(is_object($clear) ? ($clear->status ?? 0) : ($clear['status'] ?? 0));
|
|
|
- if (!in_array($status, [self::STATUS_AWAIT_PAY, self::STATUS_HAS_PAY, self::STATUS_EXPIRE], true)) {
|
|
|
- $status = self::STATUS_AWAIT_PAY;
|
|
|
- }
|
|
|
- self::bindRelations($clear, $pairs, $status);
|
|
|
- return count($pairs);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 从 xhClear 估算应有关系行数(saleIds 优先,否则 purchaseIds 个数)
|
|
|
- */
|
|
|
- public static function expectedRelationCountFromClear($clear)
|
|
|
- {
|
|
|
- $saleIds = is_object($clear) ? ($clear->saleIds ?? '') : ($clear['saleIds'] ?? '');
|
|
|
- $purchaseIds = is_object($clear) ? ($clear->purchaseIds ?? '') : ($clear['purchaseIds'] ?? '');
|
|
|
- $saleArr = self::parseIds($saleIds);
|
|
|
- if (!empty($saleArr)) {
|
|
|
- return count($saleArr);
|
|
|
- }
|
|
|
- return count(self::parseIds($purchaseIds));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * @param int[] $clearIds
|
|
|
- * @return array<int,int> clearId => 关系行数
|
|
|
- */
|
|
|
- public static function getRelationCountMap(array $clearIds)
|
|
|
- {
|
|
|
- $clearIds = array_values(array_unique(array_filter(array_map('intval', $clearIds))));
|
|
|
- if (empty($clearIds)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $table = self::$baseFile::tableName();
|
|
|
- $rows = Yii::$app->db->createCommand(
|
|
|
- 'SELECT clearId, COUNT(*) AS cnt FROM ' . $table
|
|
|
- . ' WHERE clearId IN (' . implode(',', $clearIds) . ')'
|
|
|
- . ' GROUP BY clearId'
|
|
|
- )->queryAll();
|
|
|
- $map = [];
|
|
|
- foreach ($rows as $row) {
|
|
|
- $map[intval($row['clearId'])] = intval($row['cnt']);
|
|
|
- }
|
|
|
- return $map;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否可跳过回填:关系行数已满、金额非空、无 gys2KmGys 旧格式
|
|
|
- */
|
|
|
- public static function shouldSkipBackfill($clear, $relationCount, array $emptyAmountClearIds, array $legacyGys2KmGysClearIds)
|
|
|
- {
|
|
|
- $clearId = intval(is_object($clear) ? ($clear->id ?? 0) : ($clear['id'] ?? 0));
|
|
|
- if ($clearId <= 0) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- if (in_array($clearId, $legacyGys2KmGysClearIds, true)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (in_array($clearId, $emptyAmountClearIds, true)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- $expected = self::expectedRelationCountFromClear($clear);
|
|
|
- if ($expected <= 0) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- return $relationCount >= $expected;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检测结账单关系表问题,无问题返回 null
|
|
|
- * @param bool $checkEmptyAmount 是否把 amount 为空/0 视为问题(抽样检查传 false)
|
|
|
- * @return array|null ['reason'=>string, 'relationCount'=>int, 'expected'=>int]
|
|
|
- */
|
|
|
- public static function detectBackfillIssue($clear, $relationCount, array $emptyAmountClearIds, array $legacyGys2KmGysClearIds, $checkEmptyAmount = true)
|
|
|
- {
|
|
|
- $clearId = intval(is_object($clear) ? ($clear->id ?? 0) : ($clear['id'] ?? 0));
|
|
|
- if ($clearId <= 0) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- $expected = self::expectedRelationCountFromClear($clear);
|
|
|
- $relationCount = intval($relationCount);
|
|
|
- if ($expected <= 0 && $relationCount <= 0) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- if (in_array($clearId, $legacyGys2KmGysClearIds, true)) {
|
|
|
- return [
|
|
|
- 'reason' => 'gys2KmGys旧格式(orderId>0,cgId=0)',
|
|
|
- 'relationCount' => $relationCount,
|
|
|
- 'expected' => $expected,
|
|
|
- ];
|
|
|
- }
|
|
|
- if ($checkEmptyAmount && in_array($clearId, $emptyAmountClearIds, true)) {
|
|
|
- return [
|
|
|
- 'reason' => 'amount为空或0',
|
|
|
- 'relationCount' => $relationCount,
|
|
|
- 'expected' => $expected,
|
|
|
- ];
|
|
|
- }
|
|
|
- if ($relationCount <= 0) {
|
|
|
- return [
|
|
|
- 'reason' => '无关系行',
|
|
|
- 'relationCount' => 0,
|
|
|
- 'expected' => $expected,
|
|
|
- ];
|
|
|
- }
|
|
|
- if ($expected > 0 && $relationCount < $expected) {
|
|
|
- return [
|
|
|
- 'reason' => '关系行不足',
|
|
|
- 'relationCount' => $relationCount,
|
|
|
- 'expected' => $expected,
|
|
|
- ];
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 批量查询关系表已存在的 clearId(避免逐条 SELECT)
|
|
|
- * @param int[] $clearIds
|
|
|
- * @return int[]
|
|
|
- */
|
|
|
- public static function getExistingClearIds(array $clearIds)
|
|
|
- {
|
|
|
- $clearIds = array_values(array_unique(array_filter(array_map('intval', $clearIds))));
|
|
|
- if (empty($clearIds)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $list = self::getAllByCondition(['clearId' => ['in', $clearIds]], null, 'clearId', null);
|
|
|
- if (empty($list)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- return array_values(array_unique(array_map('intval', array_column($list, 'clearId'))));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 关系行已存在但 amount 为空/0 的 clearId(用于回填补金额)
|
|
|
- * @param int[] $clearIds
|
|
|
- * @return int[]
|
|
|
- */
|
|
|
- public static function getClearIdsWithEmptyAmount(array $clearIds)
|
|
|
- {
|
|
|
- $clearIds = array_values(array_unique(array_filter(array_map('intval', $clearIds))));
|
|
|
- if (empty($clearIds)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $table = self::$baseFile::tableName();
|
|
|
- $rows = Yii::$app->db->createCommand(
|
|
|
- 'SELECT DISTINCT clearId FROM ' . $table
|
|
|
- . ' WHERE clearId IN (' . implode(',', $clearIds) . ')'
|
|
|
- . ' AND (amount IS NULL OR amount = 0 OR amount = \'0\' OR amount = \'0.00\')'
|
|
|
- )->queryColumn();
|
|
|
- if (empty($rows)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- return array_values(array_unique(array_map('intval', $rows)));
|
|
|
- }
|
|
|
-
|
|
|
- const LEGACY_UNIQUE_INDEX = 'order_id_clear_id';
|
|
|
- const RELATION_UNIQUE_INDEX = 'uk_clear_cg_order';
|
|
|
-
|
|
|
- /**
|
|
|
- * gys2KmGys 旧数据:orderId 误存基地采购单 id、cgId=0 的 clearId
|
|
|
- * @param int[] $clearIds
|
|
|
- * @return int[]
|
|
|
- */
|
|
|
- public static function getClearIdsWithLegacyGys2KmGysRows(array $clearIds)
|
|
|
- {
|
|
|
- $clearIds = array_values(array_unique(array_filter(array_map('intval', $clearIds))));
|
|
|
- if (empty($clearIds)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $gys2KmGys = intval(dict::getDict('clearStyle', 'gys2KmGys'));
|
|
|
- $relTable = self::$baseFile::tableName();
|
|
|
- $clearTable = Clear::tableName();
|
|
|
- $rows = Yii::$app->db->createCommand(
|
|
|
- 'SELECT DISTINCT r.clearId FROM ' . $relTable . ' r'
|
|
|
- . ' INNER JOIN ' . $clearTable . ' c ON c.id = r.clearId AND c.clearStyle = :style'
|
|
|
- . ' WHERE r.clearId IN (' . implode(',', $clearIds) . ')'
|
|
|
- . ' AND r.cgId = 0 AND r.orderId > 0'
|
|
|
- )->bindValue(':style', $gys2KmGys)->queryColumn();
|
|
|
- if (empty($rows)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- return array_values(array_unique(array_map('intval', $rows)));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 将 gys2KmGys 关系行从旧格式(orderId=基地采购单id,cgId=0)迁到新格式(cgId=基地采购单id,orderId=0)
|
|
|
- * 需在删除旧唯一索引 (clearId,orderId) 之后执行,或首次迁移时由 rebuildRelationUniqueIndex 串联
|
|
|
- */
|
|
|
- public static function migrateLegacyGys2KmGysRows($dryRun = false, $batchSize = 500, $sleepMs = 50)
|
|
|
- {
|
|
|
- $gys2KmGys = intval(dict::getDict('clearStyle', 'gys2KmGys'));
|
|
|
- $relTable = self::$baseFile::tableName();
|
|
|
- $clearTable = Clear::tableName();
|
|
|
- $migrated = 0;
|
|
|
- $lastId = 0;
|
|
|
-
|
|
|
- while (true) {
|
|
|
- $rows = Yii::$app->db->createCommand(
|
|
|
- 'SELECT r.id, r.clearId, r.orderId, r.orderSn, r.cgSn FROM ' . $relTable . ' r'
|
|
|
- . ' INNER JOIN ' . $clearTable . ' c ON c.id = r.clearId AND c.clearStyle = :style'
|
|
|
- . ' WHERE r.id > :lastId AND r.cgId = 0 AND r.orderId > 0'
|
|
|
- . ' ORDER BY r.id ASC LIMIT ' . intval($batchSize)
|
|
|
- )->bindValues([
|
|
|
- ':style' => $gys2KmGys,
|
|
|
- ':lastId' => $lastId,
|
|
|
- ])->queryAll();
|
|
|
-
|
|
|
- if (empty($rows)) {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- foreach ($rows as $row) {
|
|
|
- $lastId = intval($row['id']);
|
|
|
- $relId = $lastId;
|
|
|
- $clearId = intval($row['clearId']);
|
|
|
- $cgId = intval($row['orderId']);
|
|
|
- $cgSn = trim($row['cgSn'] ?? '');
|
|
|
- if ($cgSn === '') {
|
|
|
- $cgSn = trim($row['orderSn'] ?? '');
|
|
|
- }
|
|
|
-
|
|
|
- if (!$dryRun) {
|
|
|
- $target = self::getByCondition([
|
|
|
- 'clearId' => $clearId,
|
|
|
- 'orderId' => 0,
|
|
|
- 'cgId' => $cgId,
|
|
|
- ], true);
|
|
|
- if (!empty($target)) {
|
|
|
- Yii::$app->db->createCommand()->delete($relTable, ['id' => $relId])->execute();
|
|
|
- } else {
|
|
|
- Yii::$app->db->createCommand()->update($relTable, [
|
|
|
- 'cgId' => $cgId,
|
|
|
- 'cgSn' => $cgSn,
|
|
|
- 'orderId' => 0,
|
|
|
- 'orderSn' => '',
|
|
|
- ], ['id' => $relId])->execute();
|
|
|
- }
|
|
|
- }
|
|
|
- $migrated++;
|
|
|
- }
|
|
|
-
|
|
|
- if ($sleepMs > 0 && !$dryRun) {
|
|
|
- usleep($sleepMs * 1000);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return $migrated;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 迁移单个 gys2KmGys 结账单下的旧格式关系行
|
|
|
- */
|
|
|
- public static function migrateLegacyGys2KmGysRowsByClearId($clearId, $dryRun = false)
|
|
|
- {
|
|
|
- $clearId = intval($clearId);
|
|
|
- if ($clearId <= 0) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $gys2KmGys = intval(dict::getDict('clearStyle', 'gys2KmGys'));
|
|
|
- $clear = Clear::find()->where(['id' => $clearId, 'clearStyle' => $gys2KmGys])->one();
|
|
|
- if (empty($clear)) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $relTable = self::$baseFile::tableName();
|
|
|
- $rows = Yii::$app->db->createCommand(
|
|
|
- 'SELECT id, clearId, orderId, orderSn, cgSn FROM ' . $relTable
|
|
|
- . ' WHERE clearId = :clearId AND cgId = 0 AND orderId > 0'
|
|
|
- )->bindValue(':clearId', $clearId)->queryAll();
|
|
|
- if (empty($rows)) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $migrated = 0;
|
|
|
- foreach ($rows as $row) {
|
|
|
- $relId = intval($row['id']);
|
|
|
- $cgId = intval($row['orderId']);
|
|
|
- $cgSn = trim($row['cgSn'] ?? '');
|
|
|
- if ($cgSn === '') {
|
|
|
- $cgSn = trim($row['orderSn'] ?? '');
|
|
|
- }
|
|
|
- if (!$dryRun) {
|
|
|
- $target = self::getByCondition([
|
|
|
- 'clearId' => $clearId,
|
|
|
- 'orderId' => 0,
|
|
|
- 'cgId' => $cgId,
|
|
|
- ], true);
|
|
|
- if (!empty($target)) {
|
|
|
- Yii::$app->db->createCommand()->delete($relTable, ['id' => $relId])->execute();
|
|
|
- } else {
|
|
|
- Yii::$app->db->createCommand()->update($relTable, [
|
|
|
- 'cgId' => $cgId,
|
|
|
- 'cgSn' => $cgSn,
|
|
|
- 'orderId' => 0,
|
|
|
- 'orderSn' => '',
|
|
|
- ], ['id' => $relId])->execute();
|
|
|
- }
|
|
|
- }
|
|
|
- $migrated++;
|
|
|
- }
|
|
|
- return $migrated;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 重建关系表唯一索引:(clearId,cgId,orderId)
|
|
|
- * 顺序:删旧索引 -> 迁 gys2KmGys 旧行 -> 建新索引
|
|
|
- */
|
|
|
- public static function rebuildRelationUniqueIndex($dryRun = false)
|
|
|
- {
|
|
|
- $table = self::$baseFile::tableName();
|
|
|
- $indexMap = self::getTableIndexMap($table);
|
|
|
- $hasLegacy = isset($indexMap[self::LEGACY_UNIQUE_INDEX]);
|
|
|
- $hasNew = isset($indexMap[self::RELATION_UNIQUE_INDEX]);
|
|
|
- $legacyRows = intval(Yii::$app->db->createCommand(
|
|
|
- 'SELECT COUNT(*) FROM ' . $table . ' r'
|
|
|
- . ' INNER JOIN ' . Clear::tableName() . ' c ON c.id = r.clearId AND c.clearStyle = :style'
|
|
|
- . ' WHERE r.cgId = 0 AND r.orderId > 0'
|
|
|
- )->bindValue(':style', intval(dict::getDict('clearStyle', 'gys2KmGys')))->queryScalar());
|
|
|
-
|
|
|
- if ($dryRun) {
|
|
|
- return [
|
|
|
- 'hasLegacyIndex' => $hasLegacy,
|
|
|
- 'hasNewIndex' => $hasNew,
|
|
|
- 'legacyRows' => $legacyRows,
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- if ($hasLegacy) {
|
|
|
- Yii::$app->db->createCommand(
|
|
|
- 'ALTER TABLE ' . $table . ' DROP INDEX ' . self::LEGACY_UNIQUE_INDEX
|
|
|
- )->execute();
|
|
|
- }
|
|
|
-
|
|
|
- if ($legacyRows > 0) {
|
|
|
- self::migrateLegacyGys2KmGysRows(false, 500, 50);
|
|
|
- }
|
|
|
-
|
|
|
- if (!$hasNew) {
|
|
|
- Yii::$app->db->createCommand(
|
|
|
- 'ALTER TABLE ' . $table . ' ADD UNIQUE KEY ' . self::RELATION_UNIQUE_INDEX . ' (clearId, cgId, orderId)'
|
|
|
- )->execute();
|
|
|
- }
|
|
|
-
|
|
|
- return [
|
|
|
- 'droppedLegacyIndex' => $hasLegacy,
|
|
|
- 'addedNewIndex' => !$hasNew,
|
|
|
- 'migratedLegacyRows' => $legacyRows,
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- protected static function getTableIndexMap($table)
|
|
|
- {
|
|
|
- $rows = Yii::$app->db->createCommand('SHOW INDEX FROM ' . $table)->queryAll();
|
|
|
- $map = [];
|
|
|
- foreach ($rows as $row) {
|
|
|
- $name = $row['Key_name'] ?? '';
|
|
|
- if ($name !== '') {
|
|
|
- $map[$name] = true;
|
|
|
- }
|
|
|
- }
|
|
|
- return $map;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 关系行 amount 取订单/采购单 actPrice
|
|
|
- */
|
|
|
protected static function resolveDebtAmount($entity)
|
|
|
{
|
|
|
return self::normalizeAmount(self::readField($entity, 'actPrice'));
|
|
|
@@ -716,236 +277,4 @@ class OrderCgClearClass extends BaseClass
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- protected static function parseIds($idStr)
|
|
|
- {
|
|
|
- if ($idStr === '' || $idStr === null) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $arr = explode(',', (string)$idStr);
|
|
|
- return array_values(array_unique(array_filter(array_map('intval', $arr))));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * xhOrderCgClear.amount 是否视为 0(含 NULL、0.00)
|
|
|
- */
|
|
|
- protected static function isZeroAmountSql($alias = '')
|
|
|
- {
|
|
|
- $prefix = $alias !== '' ? $alias . '.' : '';
|
|
|
- return '(' . $prefix . 'amount IS NULL OR ' . $prefix . 'amount = 0 OR ' . $prefix . 'amount = \'0\' OR ' . $prefix . 'amount = \'0.00\')';
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 步骤1:只从 xhOrderCgClear 查 amount=0 的行
|
|
|
- * @return array[] id, clearId, orderId, cgId
|
|
|
- */
|
|
|
- public static function fetchZeroAmountRelationBatch($cursorId, $limit)
|
|
|
- {
|
|
|
- $relTable = self::$baseFile::tableName();
|
|
|
- $sql = 'SELECT id, clearId, orderId, cgId FROM ' . $relTable
|
|
|
- . ' WHERE ' . self::isZeroAmountSql();
|
|
|
- $params = [];
|
|
|
- if ($cursorId !== null) {
|
|
|
- $sql .= ' AND id < :cursorId';
|
|
|
- $params[':cursorId'] = intval($cursorId);
|
|
|
- }
|
|
|
- $sql .= ' ORDER BY id DESC LIMIT ' . intval($limit);
|
|
|
- return Yii::$app->db->createCommand($sql)->bindValues($params)->queryAll();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 步骤2 辅助:批量取 clearStyle(仅处理步骤1命中的 clearId)
|
|
|
- * @param int[] $clearIds
|
|
|
- * @return array<int,int> clearId => clearStyle
|
|
|
- */
|
|
|
- public static function getClearStyleMap(array $clearIds)
|
|
|
- {
|
|
|
- $clearIds = array_values(array_unique(array_filter(array_map('intval', $clearIds))));
|
|
|
- if (empty($clearIds)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $rows = Yii::$app->db->createCommand(
|
|
|
- 'SELECT id, clearStyle FROM ' . Clear::tableName()
|
|
|
- . ' WHERE id IN (' . implode(',', $clearIds) . ')'
|
|
|
- )->queryAll();
|
|
|
- $map = [];
|
|
|
- foreach ($rows as $row) {
|
|
|
- $map[intval($row['id'])] = intval($row['clearStyle'] ?? 0);
|
|
|
- }
|
|
|
- return $map;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 步骤2:反查本行 amount 应写入的值(源单 actPrice)
|
|
|
- */
|
|
|
- public static function resolveAmountForRelationRowDirect(array $row)
|
|
|
- {
|
|
|
- $clearStyle = intval($row['clearStyle'] ?? 0);
|
|
|
- $orderId = intval($row['orderId'] ?? 0);
|
|
|
- $cgId = intval($row['cgId'] ?? 0);
|
|
|
- $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;
|
|
|
- }
|
|
|
- }
|
|
|
- if ($clearStyle === $hd2Gys && $cgId > 0) {
|
|
|
- $amount = self::amountFromHdPurchaseId($cgId);
|
|
|
- if ($amount !== null) {
|
|
|
- return $amount;
|
|
|
- }
|
|
|
- }
|
|
|
- if ($orderId > 0) {
|
|
|
- $amount = self::amountFromGhsOrderId($orderId);
|
|
|
- if ($amount !== null) {
|
|
|
- return $amount;
|
|
|
- }
|
|
|
- }
|
|
|
- if ($cgId > 0) {
|
|
|
- $amount = self::amountFromHdPurchaseId($cgId);
|
|
|
- if ($amount !== null) {
|
|
|
- return $amount;
|
|
|
- }
|
|
|
- return self::amountFromGhsCgOrderId($cgId);
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- protected static function amountFromGhsOrderId($orderId)
|
|
|
- {
|
|
|
- $orderId = intval($orderId);
|
|
|
- if ($orderId <= 0) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- $order = OrderClass::getById($orderId);
|
|
|
- return self::amountFromEntity($order);
|
|
|
- }
|
|
|
-
|
|
|
- protected static function amountFromHdPurchaseId($cgId)
|
|
|
- {
|
|
|
- $cgId = intval($cgId);
|
|
|
- if ($cgId <= 0) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- $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;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 步骤1~3:xhOrderCgClear amount=0 → 反查应填金额 → 按 id 更新
|
|
|
- * @param array[] $rows fetchZeroAmountRelationBatch 的结果
|
|
|
- * @return array{updated:int,skipped:int,details:array[]}
|
|
|
- */
|
|
|
- public static function patchZeroAmountRows(array $rows, $dryRun = false, $logDetails = false)
|
|
|
- {
|
|
|
- if (empty($rows)) {
|
|
|
- return ['updated' => 0, 'skipped' => 0, 'details' => []];
|
|
|
- }
|
|
|
-
|
|
|
- $clearIds = array_values(array_unique(array_filter(array_map('intval', array_column($rows, 'clearId')))));
|
|
|
- $clearStyleMap = self::getClearStyleMap($clearIds);
|
|
|
-
|
|
|
- $table = self::$baseFile::tableName();
|
|
|
- $updated = 0;
|
|
|
- $skipped = 0;
|
|
|
- $details = [];
|
|
|
-
|
|
|
- foreach ($rows as $row) {
|
|
|
- $relId = intval($row['id'] ?? 0);
|
|
|
- $clearId = intval($row['clearId'] ?? 0);
|
|
|
- if ($relId <= 0) {
|
|
|
- $skipped++;
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- $row['clearStyle'] = $clearStyleMap[$clearId] ?? 0;
|
|
|
- $amount = self::resolveAmountForRelationRowDirect($row);
|
|
|
- if ($amount === null) {
|
|
|
- $skipped++;
|
|
|
- if ($logDetails) {
|
|
|
- $details[] = [
|
|
|
- 'id' => $relId,
|
|
|
- 'clearId' => $clearId,
|
|
|
- 'orderId' => intval($row['orderId'] ?? 0),
|
|
|
- 'cgId' => intval($row['cgId'] ?? 0),
|
|
|
- 'status' => 'skip',
|
|
|
- 'reason' => '反查不到有效 actPrice',
|
|
|
- ];
|
|
|
- }
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if (!$dryRun) {
|
|
|
- $affected = Yii::$app->db->createCommand(
|
|
|
- 'UPDATE ' . $table . ' SET amount = :amount WHERE id = :id AND ' . self::isZeroAmountSql()
|
|
|
- )->bindValues([
|
|
|
- ':amount' => $amount,
|
|
|
- ':id' => $relId,
|
|
|
- ])->execute();
|
|
|
- if ($affected > 0) {
|
|
|
- $updated++;
|
|
|
- if ($logDetails) {
|
|
|
- $details[] = [
|
|
|
- 'id' => $relId,
|
|
|
- 'clearId' => $clearId,
|
|
|
- 'amount' => $amount,
|
|
|
- 'status' => 'updated',
|
|
|
- ];
|
|
|
- }
|
|
|
- } else {
|
|
|
- $skipped++;
|
|
|
- if ($logDetails) {
|
|
|
- $details[] = [
|
|
|
- 'id' => $relId,
|
|
|
- 'status' => 'skip',
|
|
|
- 'reason' => '更新时 amount 已非 0',
|
|
|
- ];
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- $updated++;
|
|
|
- if ($logDetails) {
|
|
|
- $details[] = [
|
|
|
- 'id' => $relId,
|
|
|
- 'clearId' => $clearId,
|
|
|
- 'orderId' => intval($row['orderId'] ?? 0),
|
|
|
- 'cgId' => intval($row['cgId'] ?? 0),
|
|
|
- 'amount' => $amount,
|
|
|
- 'status' => 'would_update',
|
|
|
- ];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return ['updated' => $updated, 'skipped' => $skipped, 'details' => $details];
|
|
|
- }
|
|
|
-
|
|
|
}
|