Просмотр исходного кода

Merge branch 'clear-cg' into dev

shish 2 месяцев назад
Родитель
Сommit
4525cc7766

+ 102 - 3
biz-ghs/custom/classes/AccountMoneyClass.php

@@ -4,6 +4,7 @@ namespace bizGhs\custom\classes;
 
 use biz\ghs\classes\GhsClass as BizGhsClass;
 use bizGhs\ghs\classes\GhsBalanceChangeClass;
+use bizGhs\order\classes\PurchaseOrderClass;
 use common\components\dict;
 use Yii;
 
@@ -11,7 +12,8 @@ use Yii;
  * 客户/供货商账户金额(表 xhGhsCustom、xhGhs)
  *
  * 背景:原 debtAmount=挂账累计、balance=充值余额,现统一为净 balance(正=有余额,负=待结)。
- * 合并:balance = 原 balance - 原 debtAmount,debtAmount 置 0,balanceMerged=1 表示已合并且勿重复写说明流水。
+ * 合并(客户/批发关系行):balance = 原 balance - 原 debtAmount,debtAmount 置 0,balanceMerged=1。
+ * 合并(ghsApp 采购供货商 ownShop 行):按待结采购单 actPrice 合计重算净 balance,debtAmount 置 0(mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded)。
  * 写业务前调 ensureCustomMoneyReady / ensureGhsMoneyReady;列表/详情返回前调 formatMoneyForClient。
  * 旧 App(appVersion<3)由 formatMoneyForClient 拆回待结+余额双字段;新 App 只读净 balance。
  *
@@ -381,7 +383,104 @@ class AccountMoneyClass
     }
 
     /**
-     * 【用途】供货商列表分页时,对 xhGhs 仍有 debtAmount 未合并的单行触发懒合并(读路径补刀)。
+     * 【用途】汇总某采购供货商(xhGhs.id)下仍待结的 ghs 采购单金额。
+     * 【规则】debt=DEBT_YES 的订单 actPrice 之和,与供货商列表/小票统计一致。
+     */
+    public static function sumPurchaseOrderDebtForGhs($ghsId)
+    {
+        $ghsId = intval($ghsId);
+        if ($ghsId <= 0) {
+            return '0.00';
+        }
+        $sum = PurchaseOrderClass::sum(
+            ['ghsId' => $ghsId, 'debt' => PurchaseOrderClass::DEBT_YES],
+            'actPrice'
+        );
+        return bcadd((string)($sum ?: '0'), '0', 2);
+    }
+
+    /**
+     * 【用途】按采购待结订单重算 ownShop 侧 xhGhs 净 balance(ghsApp 采购供货商列表专用)。
+     * 【公式】净余额 = max(原 balance 正数部分, 0) - 采购待结合计;debtAmount 置 0;debtNum 与待结单数对齐。
+     * 【说明】不用「balance - debtAmount」旧字段合并,以待结采购单为待结真相源。
+     */
+    public static function mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded($ghs, $writeBalanceChange = true)
+    {
+        if (empty($ghs)) {
+            return $ghs;
+        }
+        if (self::isMerged($ghs)) {
+            if (bccomp($ghs->debtAmount ?? '0', '0', 2) != 0) {
+                $ghs->debtAmount = '0.00';
+                $ghs->save(false, ['debtAmount']);
+            }
+            return $ghs;
+        }
+
+        $ghsId = intval($ghs->id ?? 0);
+        $orderDebt = self::sumPurchaseOrderDebtForGhs($ghsId);
+        $orderDebtNum = (int)PurchaseOrderClass::getCount([
+            'ghsId' => $ghsId,
+            'debt' => PurchaseOrderClass::DEBT_YES,
+        ]);
+
+        $rawBalance = bcadd((string)($ghs->balance ?? '0'), '0', 2);
+        $positiveCredit = bccomp($rawBalance, '0', 2) > 0 ? $rawBalance : '0.00';
+        $newBalance = bcsub($positiveCredit, $orderDebt, 2);
+
+        $ghs->balance = $newBalance;
+        $ghs->debtAmount = '0.00';
+        $ghs->debtNum = $orderDebtNum;
+        $ghs->debt = bccomp($newBalance, '0', 2) < 0 ? BizGhsClass::DEBT_YES : BizGhsClass::DEBT_NO;
+
+        $saveAttrs = ['balance', 'debtAmount', 'debtNum', 'debt'];
+        if (self::hasMergeFlagField($ghs)) {
+            $ghs->balanceMerged = 1;
+            $saveAttrs[] = 'balanceMerged';
+        }
+        $ghs->save(false, $saveAttrs);
+
+        if ($writeBalanceChange && bccomp($orderDebt, '0', 2) > 0) {
+            self::addPurchaseOrderMergeBalanceChange($ghs, $orderDebt, $newBalance);
+        }
+
+        return $ghs;
+    }
+
+    /**
+     * 【用途】采购供货商按订单重算合并时写一条余额说明流水。
+     */
+    protected static function addPurchaseOrderMergeBalanceChange($row, $orderDebt, $newBalance)
+    {
+        $capitalType = dict::getDict('capitalType', 'balanceMerge', 'id');
+        $event = '账户合并:按采购待结订单合计 ' . floatval($orderDebt) . ' 元重算净余额';
+        $gbData = [
+            'ghsId' => $row->id ?? 0,
+            'relateId' => 0,
+            'ptStyle' => dict::getDict('ptStyle', 'ghs'),
+            'capitalType' => $capitalType,
+            'amount' => $orderDebt,
+            'balance' => $newBalance,
+            'io' => 0,
+            'side' => 0,
+            'onlinePay' => 0,
+            'payWay' => 0,
+            'fromType' => dict::getDict('fromType', 'shop'),
+            'event' => $event,
+            'mainId' => $row->ownMainId ?? ($row->mainId ?? 0),
+            'shopId' => $row->ownShopId ?? ($row->shopId ?? 0),
+            'sjId' => $row->sjId ?? 0,
+            'remark' => '系统按采购待结订单重算余额',
+        ];
+        if (class_exists('\bizHd\ghs\classes\GhsBalanceChangeClass')) {
+            \bizHd\ghs\classes\GhsBalanceChangeClass::add($gbData, true);
+        } else {
+            GhsBalanceChangeClass::add($gbData, true);
+        }
+    }
+
+    /**
+     * 【用途】供货商列表分页时,对 ownShop 采购供货商 xhGhs 按采购待结订单重算净余额(读路径懒合并)。
      * 【调用时机】bizGhs\ghs\classes\GhsClass::groupBaseInfo。
      */
     public static function mergeGhsRowFromListIfNeeded($ghsId)
@@ -391,7 +490,7 @@ class AccountMoneyClass
         }
         $ghs = BizGhsClass::getLockById($ghsId);
         if (!empty($ghs)) {
-            self::ensureGhsMoneyReady($ghs, true);
+            self::mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded($ghs, true);
         }
     }
 }

+ 1 - 1
biz-ghs/ghs/classes/GhsClass.php

@@ -65,7 +65,7 @@ class GhsClass extends BaseClass
         foreach ($list as $key => $val) {
             // 列表读:xhGhs 未合并的挂账先懒合并(待结订单笔数/金额仍用采购单统计,见下方)
             $ghsId = $val['id'] ?? 0;
-            if (!empty($ghsId) && bccomp($val['debtAmount'] ?? '0', '0', 2) != 0 && empty($val['balanceMerged'])) {
+            if (!empty($ghsId) && empty($val['balanceMerged'])) {
                 AccountMoneyClass::mergeGhsRowFromListIfNeeded($ghsId);
                 $fresh = self::getById($ghsId);
                 if (!empty($fresh)) {

+ 110 - 0
console/controllers/GhsPurchaseBalanceMergeController.php

@@ -0,0 +1,110 @@
+<?php
+
+namespace console\controllers;
+
+use biz\ghs\classes\GhsClass as BizGhsClass;
+use bizGhs\custom\classes\AccountMoneyClass;
+use yii\console\Controller;
+
+/**
+ * 采购供货商 xhGhs 余额合并(按采购待结订单重算)
+ *
+ * 【用途】批量处理 ghsApp 采购供货商(ownShopId>0)未 merge 的 xhGhs 行:
+ *         净 balance = max(原正余额,0) - 待结采购单 actPrice 合计,debtAmount 清 0。
+ * 【与线上一致】调用 AccountMoneyClass::mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded。
+ *
+ * 用法:php yii ghs-purchase-balance-merge/run
+ * 预览:php yii ghs-purchase-balance-merge/run --dryRun=1
+ * 单户:php yii ghs-purchase-balance-merge/run --ghsId=123
+ */
+class GhsPurchaseBalanceMergeController extends Controller
+{
+    /** 1=只预览不写库 */
+    public $dryRun = 0;
+
+    /** 指定 xhGhs.id,0=扫全表符合条件的 ownShop 行 */
+    public $ghsId = 0;
+
+    public function options($actionID)
+    {
+        return array_merge(parent::options($actionID), ['dryRun', 'ghsId']);
+    }
+
+    /**
+     * 执行或预览:按采购待结订单重算 ownShop 供货商净余额。
+     */
+    public function actionRun()
+    {
+        $dry = (int)$this->dryRun === 1;
+        $ghsId = intval($this->ghsId);
+        echo $dry ? "【预览:采购供货商按订单重算余额】\n" : "【执行:采购供货商按订单重算余额】\n";
+
+        if ($ghsId > 0) {
+            $count = $this->mergeOneGhs($ghsId, $dry) ? 1 : 0;
+            echo "完成:处理 {$count} 条,dryRun=" . ($dry ? '1' : '0') . PHP_EOL;
+            return;
+        }
+
+        $count = 0;
+        $where = ['and', ['>', 'ownShopId', 0]];
+        if ($this->columnExists('xhGhs', 'balanceMerged')) {
+            $where = ['and', ['>', 'ownShopId', 0], ['balanceMerged' => 0]];
+        } else {
+            $where = ['and', ['>', 'ownShopId', 0], ['>', 'debtAmount', 0]];
+        }
+
+        $list = BizGhsClass::getAllByCondition($where, null, 'id,ownShopId,balance,debtAmount,balanceMerged', null, true);
+        foreach ($list as $ghs) {
+            if ($this->mergeOneGhs(intval($ghs->id ?? 0), $dry)) {
+                $count++;
+            }
+        }
+        echo "完成:处理 {$count} 条,dryRun=" . ($dry ? '1' : '0') . PHP_EOL;
+    }
+
+    /**
+     * 合并单行;预览模式只打印将写入的金额。
+     */
+    protected function mergeOneGhs($ghsId, $dry)
+    {
+        if ($ghsId <= 0) {
+            return false;
+        }
+        $ghs = BizGhsClass::getById($ghsId, true);
+        if (empty($ghs)) {
+            echo "[跳过] id={$ghsId} 不存在" . PHP_EOL;
+            return false;
+        }
+        $ownShopId = intval($ghs->ownShopId ?? 0);
+        if ($ownShopId <= 0) {
+            echo "[跳过] id={$ghsId} 非采购供货商行(无 ownShopId)" . PHP_EOL;
+            return false;
+        }
+
+        $orderDebt = AccountMoneyClass::sumPurchaseOrderDebtForGhs($ghsId);
+        $rawBalance = bcadd((string)($ghs->balance ?? '0'), '0', 2);
+        $positiveCredit = bccomp($rawBalance, '0', 2) > 0 ? $rawBalance : '0.00';
+        $newBalance = bcsub($positiveCredit, $orderDebt, 2);
+
+        if ($dry) {
+            echo "[供货商] id={$ghsId} ownShopId={$ownShopId} balance={$ghs->balance} debtAmount={$ghs->debtAmount}"
+                . " 采购待结合计={$orderDebt} => 新balance={$newBalance}" . PHP_EOL;
+            return true;
+        }
+
+        $locked = BizGhsClass::getLockById($ghsId);
+        AccountMoneyClass::mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded($locked, true);
+        echo "[已合并] id={$ghsId} 采购待结={$orderDebt} 新balance={$newBalance}" . PHP_EOL;
+        return true;
+    }
+
+    /**
+     * 判断 xhGhs 是否已有 balanceMerged 字段。
+     */
+    protected function columnExists($table, $column)
+    {
+        $db = \Yii::$app->db;
+        $schema = $db->getTableSchema($table, true);
+        return $schema && isset($schema->columns[$column]);
+    }
+}