Pārlūkot izejas kodu

采购单 与 脚本 问题

shish 2 mēneši atpakaļ
vecāks
revīzija
971216c68a

+ 8 - 1
app-ghs/controllers/GhsController.php

@@ -256,10 +256,17 @@ class GhsController extends BaseController
             if (!empty($list['list'])) {
                 foreach ($list['list'] as $key => $val) {
                     $list['list'][$key]['debtAmount'] = 0;
+                    $list['list'][$key]['debtNum'] = 0;
+                    $list['list'][$key]['remainDebtAmount'] = '0.00';
+                    // 净余额协议下待结体现在负 balance,无财务权限时一并隐藏
+                    if (bccomp($list['list'][$key]['balance'] ?? '0', '0', 2) < 0) {
+                        $list['list'][$key]['balance'] = '0.00';
+                        $list['list'][$key]['displayBalance'] = '0.00';
+                    }
                 }
             }
         } else {
-            // 总欠款:各供货商 balance 字段之和
+            // 总待结:各供货商净 balance 为负部分的合计
             $totalDebtAmount = GhsClass::sumTotalOutstandingDebt($this->shopId, 0);
         }
         $list['totalDebtAmount'] = $totalDebtAmount;

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

@@ -13,7 +13,8 @@ use Yii;
  *
  * 背景:原 debtAmount=挂账累计、balance=充值余额,现统一为净 balance(正=有余额,负=待结)。
  * 合并(客户/批发关系行):balance = 原 balance - 原 debtAmount,debtAmount 置 0,balanceMerged=1。
- * 合并(ghsApp 采购供货商 ownShop 行):按待结采购单 actPrice 合计重算净 balance,debtAmount 置 0(mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded)。
+ * 合并(ghsApp 采购供货商行,ownPtStyle=ghs/kmGhs):按待结采购单 actPrice 合计重算净 balance,debtAmount 置 0。
+ * 合并(hd 花店侧供货商行,ownPtStyle=hd):balance -= debtAmount 旧逻辑(mergeGhsDebtIntoBalanceIfNeeded);二者不可混用。
  * 写业务前调 ensureCustomMoneyReady / ensureGhsMoneyReady;列表/详情返回前调 formatMoneyForClient。
  * 旧 App(appVersion<3)由 formatMoneyForClient 拆回待结+余额双字段;新 App 只读净 balance。
  *
@@ -346,6 +347,32 @@ class AccountMoneyClass
         return $custom;
     }
 
+    /**
+     * 【用途】判断 xhGhs 是否为 ghsApp「采购供货商」行(批发商向上游采购),而非 hd 花店侧供货商行。
+     * 【规则】同一表 xhGhs:ownPtStyle=hd(1) 为花店买方;ownPtStyle=ghs(2)/kmGhs(4) 为 ghsApp 采购买方。
+     */
+    public static function isGhsAppPurchaseSupplierRow($ghs)
+    {
+        $ownShopId = intval(is_array($ghs) ? ($ghs['ownShopId'] ?? 0) : ($ghs->ownShopId ?? 0));
+        if ($ownShopId <= 0) {
+            return false;
+        }
+        $ownPtStyle = intval(is_array($ghs) ? ($ghs['ownPtStyle'] ?? 0) : ($ghs->ownPtStyle ?? 0));
+        if ($ownPtStyle <= 0) {
+            $shop = \biz\shop\classes\ShopClass::getById($ownShopId);
+            if (!empty($shop)) {
+                $ownPtStyle = intval(is_array($shop) ? ($shop['ptStyle'] ?? 0) : ($shop->ptStyle ?? 0));
+            }
+        }
+        $hdPt = (int)dict::getDict('ptStyle', 'hd');
+        if ($ownPtStyle === $hdPt) {
+            return false;
+        }
+        $ghsPt = (int)dict::getDict('ptStyle', 'ghs');
+        $kmGhsPt = (int)dict::getDict('ptStyle', 'kmGhs');
+        return in_array($ownPtStyle, [$ghsPt, $kmGhsPt], true);
+    }
+
     /**
      * 【用途】仅处理 xhGhs 关系行(无 custom 对象时),逻辑同 ensureCustomMoneyReady 的 ghs 部分。
      * 【调用时机】hd 采购挂账/结账/退款、ghs 采购单改供货商金额、CgRefund 等只拿到 $ghs 的场景。
@@ -362,6 +389,9 @@ class AccountMoneyClass
         if (empty($ghs)) {
             return $ghs;
         }
+        if (!self::isMerged($ghs) && self::isGhsAppPurchaseSupplierRow($ghs)) {
+            return self::mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded($ghs, $writeMergeChange);
+        }
         return self::mergeGhsDebtIntoBalanceIfNeeded($ghs, $writeMergeChange);
     }
 
@@ -409,6 +439,9 @@ class AccountMoneyClass
         if (empty($ghs)) {
             return $ghs;
         }
+        if (!self::isGhsAppPurchaseSupplierRow($ghs)) {
+            return self::mergeGhsDebtIntoBalanceIfNeeded($ghs, $writeBalanceChange);
+        }
         if (self::isMerged($ghs)) {
             if (bccomp($ghs->debtAmount ?? '0', '0', 2) != 0) {
                 $ghs->debtAmount = '0.00';
@@ -480,7 +513,7 @@ class AccountMoneyClass
     }
 
     /**
-     * 【用途】供货商列表分页时,对 ownShop 采购供货商 xhGhs 按采购待结订单重算净余额(读路径懒合并)
+     * 【用途】供货商列表分页时的读路径懒合并:ghsApp 采购行按采购单重算,hd 花店行走 debtAmount 合并
      * 【调用时机】bizGhs\ghs\classes\GhsClass::groupBaseInfo。
      */
     public static function mergeGhsRowFromListIfNeeded($ghsId)
@@ -489,8 +522,13 @@ class AccountMoneyClass
             return;
         }
         $ghs = BizGhsClass::getLockById($ghsId);
-        if (!empty($ghs)) {
+        if (empty($ghs)) {
+            return;
+        }
+        if (self::isGhsAppPurchaseSupplierRow($ghs)) {
             self::mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded($ghs, true);
+            return;
         }
+        self::mergeGhsDebtIntoBalanceIfNeeded($ghs, true);
     }
 }

+ 18 - 12
biz-ghs/ghs/classes/GhsClass.php

@@ -4,7 +4,6 @@ namespace bizGhs\ghs\classes;
 
 use bizGhs\base\classes\BaseClass;
 use bizGhs\custom\classes\AccountMoneyClass;
-use bizGhs\order\classes\PurchaseOrderClass;
 use bizGhs\shop\classes\ShopClass;
 use common\components\imgUtil;
 use Yii;
@@ -50,8 +49,19 @@ class GhsClass extends BaseClass
         if (empty($shopId)) {
             return '0.00';
         }
-        $sum = self::sum(['ownShopId' => $shopId, 'delStatus' => $delStatus], 'balance');
-        return bcadd($sum ?: '0', '0', 2);
+        // 总待结:各行净 balance 为负时的待结金额之和(合并后 debtNum/balance 已为真相源)
+        $rows = self::getAllByCondition(
+            ['ownShopId' => $shopId, 'delStatus' => $delStatus],
+            null,
+            'balance,debtAmount,balanceMerged'
+        );
+        $total = '0.00';
+        if (!empty($rows)) {
+            foreach ($rows as $row) {
+                $total = bcadd($total, AccountMoneyClass::getOutstandingDebt($row), 2);
+            }
+        }
+        return $total;
     }
 
 
@@ -63,7 +73,7 @@ class GhsClass extends BaseClass
         $ids = array_column($list, 'shopId');
         $shopInfo = ShopClass::getByIds($ids, null, 'id');
         foreach ($list as $key => $val) {
-            // 列表读:xhGhs 未合并的挂账先懒合并(待结订单笔数/金额仍用采购单统计,见下方
+            // 列表读:未合并行懒合并(ghsApp 采购行按采购单重算,hd 行走 debtAmount 合并
             $ghsId = $val['id'] ?? 0;
             if (!empty($ghsId) && empty($val['balanceMerged'])) {
                 AccountMoneyClass::mergeGhsRowFromListIfNeeded($ghsId);
@@ -96,10 +106,8 @@ class GhsClass extends BaseClass
             $list[$key]['openStartTime'] = $shopInfo[$currentShopId]['openStartTime'] ?? '';
             $list[$key]['openEndTime'] = $shopInfo[$currentShopId]['openEndTime'] ?? '';
 
-            $count = PurchaseOrderClass::getCount(['ghsId' => $val['id'], 'debt' => PurchaseOrderClass::DEBT_YES]);
-            $debtAmount = PurchaseOrderClass::sum(['ghsId' => $val['id'], 'debt' => PurchaseOrderClass::DEBT_YES], 'actPrice');
-            $list[$key]['debtNum'] = $count;
-            $list[$key]['debtAmount'] = $debtAmount;
+            // 待结笔数/金额:合并后直接使用 xhGhs.debtNum 与净 balance,不再查采购单表
+            $list[$key] = AccountMoneyClass::formatMoneyForClient($list[$key]);
 
         }
         return $list;
@@ -111,10 +119,8 @@ class GhsClass extends BaseClass
         $ghsList = GhsClass::getAllByCondition(['ownMainId' => $mainId], null, '*');
         if (!empty($ghsList)) {
             foreach ($ghsList as $key => $ghs) {
-                $count = PurchaseOrderClass::getCount(['ghsId' => $ghs['id'], 'debt' => PurchaseOrderClass::DEBT_YES]);
-                $debtAmount = PurchaseOrderClass::sum(['ghsId' => $ghs['id'], 'debt' => PurchaseOrderClass::DEBT_YES], 'actPrice');
-                $ghsList[$key]['debtNum'] = $count ?? 0;
-                $ghsList[$key]['debtAmount'] = $debtAmount ?? 0;
+                $ghsList[$key]['debtNum'] = intval($ghs['debtNum'] ?? 0);
+                $ghsList[$key]['debtAmount'] = AccountMoneyClass::getOutstandingDebt($ghs);
             }
         }
 

+ 19 - 2
biz-ghs/order/classes/PurchaseOrderClass.php

@@ -137,7 +137,17 @@ class PurchaseOrderClass extends BaseClass
         AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
         $ghsNewBalance = bcadd($ghs->balance ?? '0.00', $amount, 2);
         $ghs->balance = $ghsNewBalance;
-        $ghs->save(false, ['balance']);
+
+        // 待结采购单售后:净 balance 增加;若该单待结金额已退尽则 debtNum 减 1
+        $wasDebtOrder = intval($order->debt ?? 0) === self::DEBT_YES;
+        $clearOrderDebt = $wasDebtOrder && bccomp($order->actPrice ?? '0', '0', 2) <= 0;
+        if ($clearOrderDebt) {
+            $ghs->debtNum = max(0, intval($ghs->debtNum ?? 0) - 1);
+            $order->debt = self::DEBT_NO;
+            $order->save(false, ['debt']);
+        }
+        $ghs->debt = bccomp($ghsNewBalance, '0', 2) < 0 ? GhsClass::DEBT_YES : GhsClass::DEBT_NO;
+        $ghs->save(false, ['balance', 'debtNum', 'debt']);
 
         $orderSn = $order->orderSn ?? '';
         $refundSn = $refund->refundSn ?? '';
@@ -164,8 +174,15 @@ class PurchaseOrderClass extends BaseClass
                 AccountMoneyClass::ensureCustomMoneyReady($custom, true);
                 $customNewBalance = bcadd($custom->balance ?? '0.00', $amount, 2);
                 $custom->balance = $customNewBalance;
+                if ($clearOrderDebt) {
+                    $custom->debtNum = max(0, intval($custom->debtNum ?? 0) - 1);
+                }
                 $custom->isDebt = bccomp($customNewBalance, '0', 2) < 0 ? CustomClass::IS_DEBT_YES : CustomClass::IS_DEBT_NO;
-                $custom->save(false, ['balance', 'isDebt']);
+                $saveAttrs = ['balance', 'isDebt'];
+                if ($clearOrderDebt) {
+                    $saveAttrs[] = 'debtNum';
+                }
+                $custom->save(false, $saveAttrs);
             }
         }
 

+ 44 - 15
console/controllers/GhsPurchaseBalanceMergeController.php

@@ -4,14 +4,16 @@ namespace console\controllers;
 
 use biz\ghs\classes\GhsClass as BizGhsClass;
 use bizGhs\custom\classes\AccountMoneyClass;
+use common\components\dict;
 use yii\console\Controller;
 
 /**
- * 采购供货商 xhGhs 余额合并(按采购待结订单重算)
+ * ghsApp 采购供货商 xhGhs 余额合并(按采购待结订单重算)
  *
- * 【用途】批量处理 ghsApp 采购供货商(ownShopId>0)未 merge 的 xhGhs 行:
- *         净 balance = max(原正余额,0) - 待结采购单 actPrice 合计,debtAmount 清 0。
- * 【与线上一致】调用 AccountMoneyClass::mergeOwnShopGhsBalanceFromPurchaseOrdersIfNeeded。
+ * 【用途】仅处理 ghsApp 采购供货商行(ownPtStyle=ghs/kmGhs),不处理 hd 花店侧 xhGhs 行(ownPtStyle=hd)。
+ * 【公式】净 balance = max(原正余额,0) - 待结 ghs 采购单 actPrice 合计,debtAmount 清 0。
+ *
+ * hd 花店侧供货商请用:php yii balance-merge/run
  *
  * 用法:php yii ghs-purchase-balance-merge/run
  * 预览:php yii ghs-purchase-balance-merge/run --dryRun=1
@@ -22,7 +24,7 @@ class GhsPurchaseBalanceMergeController extends Controller
     /** 1=只预览不写库 */
     public $dryRun = 0;
 
-    /** 指定 xhGhs.id,0=扫全表符合条件的 ownShop 行 */
+    /** 指定 xhGhs.id,0=扫全表符合条件的 ghsApp 采购供货商行 */
     public $ghsId = 0;
 
     public function options($actionID)
@@ -31,13 +33,13 @@ class GhsPurchaseBalanceMergeController extends Controller
     }
 
     /**
-     * 执行或预览:按采购待结订单重算 ownShop 供货商净余额。
+     * 执行或预览:仅 ghsApp 采购供货商(ownPtStyle=ghs/kmGhs)按采购待结订单重算净余额。
      */
     public function actionRun()
     {
         $dry = (int)$this->dryRun === 1;
         $ghsId = intval($this->ghsId);
-        echo $dry ? "【预览:采购供货商按订单重算余额】\n" : "【执行:采购供货商按订单重算余额】\n";
+        echo $dry ? "【预览:ghsApp 采购供货商按订单重算余额】\n" : "【执行:ghsApp 采购供货商按订单重算余额】\n";
 
         if ($ghsId > 0) {
             $count = $this->mergeOneGhs($ghsId, $dry) ? 1 : 0;
@@ -46,22 +48,47 @@ class GhsPurchaseBalanceMergeController extends Controller
         }
 
         $count = 0;
-        $where = ['and', ['>', 'ownShopId', 0]];
+        $purchasePtStyles = $this->getGhsAppPurchasePtStyles();
+        $where = ['and', ['>', 'ownShopId', 0], ['in', 'ownPtStyle', $purchasePtStyles]];
         if ($this->columnExists('xhGhs', 'balanceMerged')) {
-            $where = ['and', ['>', 'ownShopId', 0], ['balanceMerged' => 0]];
+            $where = ['and', ['>', 'ownShopId', 0], ['in', 'ownPtStyle', $purchasePtStyles], ['balanceMerged' => 0]];
         } else {
-            $where = ['and', ['>', 'ownShopId', 0], ['>', 'debtAmount', 0]];
+            $where = ['and', ['>', 'ownShopId', 0], ['in', 'ownPtStyle', $purchasePtStyles], ['>', 'debtAmount', 0]];
         }
 
-        $list = BizGhsClass::getAllByCondition($where, null, 'id,ownShopId,balance,debtAmount,balanceMerged', null, true);
+        $list = BizGhsClass::getAllByCondition($where, null, 'id,ownShopId,ownPtStyle,balance,debtAmount,balanceMerged', null, true);
         foreach ($list as $ghs) {
             if ($this->mergeOneGhs(intval($ghs->id ?? 0), $dry)) {
                 $count++;
             }
         }
+
+        // ownPtStyle 未回填的历史行:再扫 ownPtStyle=0,由 isGhsAppPurchaseSupplierRow 按门店 ptStyle 判定
+        $legacyWhere = ['and', ['>', 'ownShopId', 0], ['ownPtStyle' => 0]];
+        if ($this->columnExists('xhGhs', 'balanceMerged')) {
+            $legacyWhere = ['and', ['>', 'ownShopId', 0], ['ownPtStyle' => 0], ['balanceMerged' => 0]];
+        }
+        $legacyList = BizGhsClass::getAllByCondition($legacyWhere, null, 'id,ownShopId,ownPtStyle,balance,debtAmount,balanceMerged', null, true);
+        foreach ($legacyList as $ghs) {
+            if ($this->mergeOneGhs(intval($ghs->id ?? 0), $dry)) {
+                $count++;
+            }
+        }
+
         echo "完成:处理 {$count} 条,dryRun=" . ($dry ? '1' : '0') . PHP_EOL;
     }
 
+    /**
+     * ghsApp 采购买方平台类型:二级批发(2)、基地端(4);不含 hd 花店(1)。
+     */
+    protected function getGhsAppPurchasePtStyles()
+    {
+        return [
+            (int)dict::getDict('ptStyle', 'ghs'),
+            (int)dict::getDict('ptStyle', 'kmGhs'),
+        ];
+    }
+
     /**
      * 合并单行;预览模式只打印将写入的金额。
      */
@@ -75,19 +102,21 @@ class GhsPurchaseBalanceMergeController extends Controller
             echo "[跳过] id={$ghsId} 不存在" . PHP_EOL;
             return false;
         }
-        $ownShopId = intval($ghs->ownShopId ?? 0);
-        if ($ownShopId <= 0) {
-            echo "[跳过] id={$ghsId} 非采购供货商行(无 ownShopId)" . PHP_EOL;
+        if (!AccountMoneyClass::isGhsAppPurchaseSupplierRow($ghs)) {
+            $ownPtStyle = intval($ghs->ownPtStyle ?? 0);
+            echo "[跳过] id={$ghsId} 非 ghsApp 采购供货商行(ownPtStyle={$ownPtStyle},hd 行请用 balance-merge)" . PHP_EOL;
             return false;
         }
 
+        $ownShopId = intval($ghs->ownShopId ?? 0);
         $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}"
+            echo "[ghsApp采购供货商] id={$ghsId} ownShopId={$ownShopId} ownPtStyle={$ghs->ownPtStyle}"
+                . " balance={$ghs->balance} debtAmount={$ghs->debtAmount}"
                 . " 采购待结合计={$orderDebt} => 新balance={$newBalance}" . PHP_EOL;
             return true;
         }