Răsfoiți Sursa

余额与消账

shish 8 ore în urmă
părinte
comite
40bc996b3c

+ 32 - 5
biz-ghs/custom/classes/CustomClass.php

@@ -9,6 +9,7 @@ use bizGhs\book\classes\BookCustomClass;
 use bizGhs\book\classes\BookItemCustomClass;
 use bizGhs\book\classes\BookItemCustomClass;
 use bizGhs\custom\classes\AccountMoneyClass;
 use bizGhs\custom\classes\AccountMoneyClass;
 use bizGhs\custom\models\Custom;
 use bizGhs\custom\models\Custom;
+use bizGhs\custom\services\GhsRechargeSettleService;
 use bizGhs\ghs\classes\GhsBalanceChangeClass;
 use bizGhs\ghs\classes\GhsBalanceChangeClass;
 use bizGhs\shop\classes\MainClass;
 use bizGhs\shop\classes\MainClass;
 use bizGhs\shop\classes\ShopMoneyClass;
 use bizGhs\shop\classes\ShopMoneyClass;
@@ -697,7 +698,8 @@ class CustomClass extends BaseClass
     }
     }
 
 
     /**
     /**
-     * 隔天冲销返充余额:成对账户加余额,不改订单 actPrice;流水挂售后单。
+     * 隔天冲销/无原单返充余额:成对账户加余额,不改订单 actPrice;流水挂售后单。
+     * 入账后按本次金额 FIFO 销挂账(与客户详情充值消欠一致)。
      * 调用方须已 lockAccountPair。
      * 调用方须已 lockAccountPair。
      */
      */
     public static function nextDayRefundReturnBalance($custom, $ghs, $refund, $order)
     public static function nextDayRefundReturnBalance($custom, $ghs, $refund, $order)
@@ -711,7 +713,9 @@ class CustomClass extends BaseClass
         if (bccomp($refundPrice, '0', 2) <= 0) {
         if (bccomp($refundPrice, '0', 2) <= 0) {
             util::fail('返充金额必须大于0');
             util::fail('返充金额必须大于0');
         }
         }
-        $newBalance = bcadd((string)($custom->balance ?? '0'), $refundPrice, 2);
+        // 入账前净余额:供 FIFO 结账单 payWay 判定
+        $balanceBefore = bcadd((string)($custom->balance ?? '0'), '0', 2);
+        $newBalance = bcadd($balanceBefore, $refundPrice, 2);
         self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
         self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
 
 
         $refundSn = $refund->orderSn ?? '';
         $refundSn = $refund->orderSn ?? '';
@@ -743,12 +747,15 @@ class CustomClass extends BaseClass
             'remark' => '',
             'remark' => '',
         ], true);
         ], true);
         self::addGhsRefundBalanceChange($custom, $ghs, $refund, $order, $refundPrice, $newBalance);
         self::addGhsRefundBalanceChange($custom, $ghs, $refund, $order, $refundPrice, $newBalance);
-        return $newBalance;
+        // 有挂账欠款时:本次返充金额去消欠(与充值 merchantRechargeWithAutoClear 一致)
+        self::fifoClearAfterRefundCredit($custom, $ghs, $refund, $refundPrice, $balanceBefore);
+        $custom = CustomClass::getById(intval($custom->id ?? 0), true);
+        return bcadd((string)($custom->balance ?? $newBalance), '0', 2);
     }
     }
 
 
     /**
     /**
      * 花店采购余额付售后:成对账户原路退回(与 payToChangeBalance 对称)。
      * 花店采购余额付售后:成对账户原路退回(与 payToChangeBalance 对称)。
-     * 调用方须已 lockAccountPair;同时写客户余额明细与 xhGhs 余额明细(hdApp 可查)
+     * 钱退回余额后同样 FIFO 销挂账;调用方须已 lockAccountPair。
      */
      */
     public static function refundBalancePayToPair($custom, $ghs, $refund, $order)
     public static function refundBalancePayToPair($custom, $ghs, $refund, $order)
     {
     {
@@ -761,7 +768,8 @@ class CustomClass extends BaseClass
         if (bccomp($refundPrice, '0', 2) <= 0) {
         if (bccomp($refundPrice, '0', 2) <= 0) {
             return;
             return;
         }
         }
-        $newBalance = bcadd((string)($custom->balance ?? '0'), $refundPrice, 2);
+        $balanceBefore = bcadd((string)($custom->balance ?? '0'), '0', 2);
+        $newBalance = bcadd($balanceBefore, $refundPrice, 2);
         self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
         self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
 
 
         $relateId = $refund->id ?? 0;
         $relateId = $refund->id ?? 0;
@@ -793,6 +801,25 @@ class CustomClass extends BaseClass
         ];
         ];
         CustomBalanceChangeClass::add($change, true);
         CustomBalanceChangeClass::add($change, true);
         self::addGhsRefundBalanceChange($custom, $ghs, $refund, $order, $refundPrice, $newBalance);
         self::addGhsRefundBalanceChange($custom, $ghs, $refund, $order, $refundPrice, $newBalance);
+        // 余额付原路退回 = 加余额,有挂账时一并消欠
+        self::fifoClearAfterRefundCredit($custom, $ghs, $refund, $refundPrice, $balanceBefore);
+    }
+
+    /**
+     * 售后加余额后的 FIFO 销挂账封装:组装门店/操作人后交给 GhsRechargeSettleService。
+     */
+    protected static function fifoClearAfterRefundCredit($custom, $ghs, $refund, $amount, $balanceBefore)
+    {
+        $shopId = intval($refund->shopId ?? 0);
+        $shop = $shopId > 0 ? ShopClass::getById($shopId, true) : null;
+        $staff = (object)[
+            'id' => intval($refund->shopAdminId ?? 0),
+            'name' => (string)($refund->shopAdminName ?? ''),
+        ];
+        GhsRechargeSettleService::afterCreditFifoClear($custom, $ghs, $amount, $shop, $staff, [
+            'balanceBeforeRecharge' => $balanceBefore,
+            'payWay' => dict::getDict('payWay', 'balancePay'),
+        ]);
     }
     }
 
 
     /** 花店采购余额退款:记 xhGhs 余额变动(与 addGhsOrderBalanceChange 对称,hdApp 余额明细展示) */
     /** 花店采购余额退款:记 xhGhs 余额变动(与 addGhsOrderBalanceChange 对称,hdApp 余额明细展示) */

+ 53 - 1
biz-ghs/custom/services/GhsRechargeSettleService.php

@@ -9,6 +9,7 @@ use bizGhs\custom\classes\CustomClass;
 use bizGhs\ghs\classes\GhsBalanceChangeClass;
 use bizGhs\ghs\classes\GhsBalanceChangeClass;
 use bizGhs\order\classes\OrderClearClass;
 use bizGhs\order\classes\OrderClearClass;
 use bizGhs\order\classes\OrderClass;
 use bizGhs\order\classes\OrderClass;
+use bizGhs\shop\classes\ShopClass;
 use common\components\dict;
 use common\components\dict;
 use common\components\noticeUtil;
 use common\components\noticeUtil;
 use common\components\util;
 use common\components\util;
@@ -23,7 +24,7 @@ use common\components\util;
  * 4. 用账面正余额销账:无来款,FIFO 后 balance -= 实销额,可记「结账」流水。
  * 4. 用账面正余额销账:无来款,FIFO 后 balance -= 实销额,可记「结账」流水。
  *
  *
  * 入口:merchantRechargeWithAutoClear / onlinePayFifoClear / confirmClearBillWithIncoming /
  * 入口:merchantRechargeWithAutoClear / onlinePayFifoClear / confirmClearBillWithIncoming /
- *       consumePositiveBalanceFifo
+ *       consumePositiveBalanceFifo / afterCreditFifoClear
  */
  */
 class GhsRechargeSettleService
 class GhsRechargeSettleService
 {
 {
@@ -178,6 +179,57 @@ class GhsRechargeSettleService
         return true;
         return true;
     }
     }
 
 
+    /**
+     * 售后等「已入账」来款后的 FIFO 销挂账(对齐客户详情充值消欠)。
+     * 调用时机:余额已加完;本方法只用本次金额作资金池销 remainDebtPrice,不再扣 balance。
+     * 场景:隔天/无原单返充余额、当天余额付原路退回。
+     *
+     * @param object $custom 客户
+     * @param object|null $ghs 成对供货商账户,空则按 custom.ghsId 加锁
+     * @param string|float $amount 本次入账金额
+     * @param object|null $shop 供货商门店;空则取 ghs.shopId
+     * @param object|null $staff 操作人(结账单记录用)
+     * @param array $options balanceBeforeRecharge|payWay
+     * @return array 与 fifoSettleWithPool 相同结构
+     */
+    public static function afterCreditFifoClear($custom, $ghs, $amount, $shop = null, $staff = null, $options = [])
+    {
+        $pair = self::lockAccountPair($custom, $ghs);
+        $pool = self::money($amount);
+        if (bccomp($pool, '0', 2) <= 0) {
+            return self::emptyAllocateResult($pair['custom'], $pair['ghs']);
+        }
+
+        if (empty($shop)) {
+            $ghsShopId = intval($pair['ghs']->shopId ?? 0);
+            $shop = ShopClass::getById($ghsShopId, true);
+        }
+        if (empty($shop)) {
+            util::fail('没有找到供货商门店,无法销挂账');
+        }
+
+        // 未传则用「当前余额 - 本次入账」还原入账前净余额,供结账单 payWay/onlinePay 判定
+        if (!array_key_exists('balanceBeforeRecharge', $options)) {
+            $options['balanceBeforeRecharge'] = bcsub(
+                self::money($pair['custom']->balance ?? 0),
+                $pool,
+                2
+            );
+        }
+        if (!isset($options['payWay'])) {
+            $options['payWay'] = dict::getDict('payWay', 'balancePay');
+        }
+        if (!isset($options['rechargeSource'])) {
+            $options['rechargeSource'] = 'merchant';
+        }
+        // 钱已进余额,销账不再二次扣减
+        $options['deduct_balance'] = false;
+
+        self::voidAwaitPayClearBills($pair['custom']->id ?? 0);
+
+        return self::fifoSettleWithPool($pair, $shop, $staff, $pool, $options);
+    }
+
     /**
     /**
      * FIFO 分配计划:按订单 id 升序,资金池用尽即停止。
      * FIFO 分配计划:按订单 id 升序,资金池用尽即停止。
      *
      *