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

+ 221 - 2
biz-ghs/custom/classes/CustomBalanceChangeClass.php

@@ -2,6 +2,9 @@
 
 namespace bizGhs\custom\classes;
 
+use bizGhs\order\classes\OrderClearClass;
+use bizHd\purchase\classes\PurchaseClearClass;
+use common\components\dict;
 use common\components\util;
 use bizHd\base\classes\BaseClass;
 use Yii;
@@ -20,21 +23,237 @@ class CustomBalanceChangeClass extends BaseClass
         $data = self::getList('*', $where, 'addTime DESC,id DESC');
         if (!empty($data['list'])) {
             foreach ($data['list'] as $k => $v) {
-                $clearAmount = $v['clearAmount'] ?? 0; // 本笔来款中用于销挂账的金额,列见 add_clear_audit_fields.sql
+                $v = self::fillClearAuditFromRecharge($v);
+                $clearAmount = $v['clearAmount'] ?? 0;
                 $amount = $v['amount'] ?? 0;
                 $io = $v['io'] ?? 0;
                 $becomeBalance = 0;
                 if ($io == 1) {
-                    // 仅入账方向计算「充完销账后还剩多少余额」
                     $becomeBalance = bcsub($amount, $clearAmount, 2);
                     $becomeBalance = floatval($becomeBalance);
                 }
+                $data['list'][$k] = $v;
                 $data['list'][$k]['becomeBalance'] = $becomeBalance;
             }
         }
         return $data;
     }
 
+    /**
+     * 入账流水补全结账单(充值清账、选订单销账-客户已转账 等)
+     */
+    public static function fillClearAuditFromRecharge($row)
+    {
+        if (empty($row) || !is_array($row)) {
+            return $row;
+        }
+        if (intval($row['clearId'] ?? 0) > 0) {
+            return self::normalizeClearAuditRow($row);
+        }
+        if (intval($row['io'] ?? 0) !== 1) {
+            return $row;
+        }
+        $relateId = intval($row['relateId'] ?? 0);
+        if ($relateId <= 0) {
+            return $row;
+        }
+
+        // 旧流水:relateId 即结账单 id
+        if (self::isClearIncomeCapitalType($row['capitalType'] ?? 0)) {
+            return self::attachClearMetaFromClearId($row, $relateId);
+        }
+
+        if (!self::isRechargeCapitalType($row['capitalType'] ?? 0)) {
+            return $row;
+        }
+
+        $recharge = CustomRechargeClass::getById($relateId, true);
+        if (!empty($recharge)) {
+            $clearId = intval(is_object($recharge) ? ($recharge->clearId ?? 0) : ($recharge['clearId'] ?? 0));
+            if ($clearId > 0) {
+                $row['clearId'] = $clearId;
+                $row['clearSn'] = is_object($recharge) ? ($recharge->clearSn ?? '') : ($recharge['clearSn'] ?? '');
+                $row['clearAmount'] = is_object($recharge) ? ($recharge->clearAmount ?? 0) : ($recharge['clearAmount'] ?? 0);
+                return self::normalizeClearAuditRow($row);
+            }
+        }
+
+        // 选订单销账:充值单未落库 clearId 时,按客户+金额+时间匹配已付结账单
+        return self::fillClearAuditByPaidClearMatch($row, $recharge ?? null);
+    }
+
+    /** 写入流水/充值单时带上结账单(有字段才写,对照 hd 充值即带 settleId) */
+    public static function mergeClearAuditIntoRowData(array $data, array $audit)
+    {
+        $clearId = intval($audit['clearId'] ?? 0);
+        if ($clearId <= 0) {
+            return $data;
+        }
+        $probe = new \bizGhs\custom\models\CustomBalanceChange();
+        if (!method_exists($probe, 'hasAttribute') || !$probe->hasAttribute('clearId')) {
+            return $data;
+        }
+        $data['clearId'] = $clearId;
+        $data['clearSn'] = (string)($audit['clearSn'] ?? '');
+        $data['clearAmount'] = bcadd((string)($audit['clearAmount'] ?? 0), '0', 2);
+        if ($probe->hasAttribute('giveAmount')) {
+            $data['giveAmount'] = '0.00';
+        }
+        return $data;
+    }
+
+    public static function mergeClearAuditIntoRechargeData(array $data, array $audit)
+    {
+        $clearId = intval($audit['clearId'] ?? 0);
+        if ($clearId <= 0) {
+            return $data;
+        }
+        $probe = new \bizGhs\custom\models\CustomRecharge();
+        if (!method_exists($probe, 'hasAttribute') || !$probe->hasAttribute('clearId')) {
+            return $data;
+        }
+        $data['clearId'] = $clearId;
+        $data['clearSn'] = (string)($audit['clearSn'] ?? '');
+        $data['clearAmount'] = bcadd((string)($audit['clearAmount'] ?? 0), '0', 2);
+        return $data;
+    }
+
+    protected static function attachClearMetaFromClearId(array $row, $clearId)
+    {
+        $clearId = intval($clearId);
+        if ($clearId <= 0) {
+            return $row;
+        }
+        $clear = OrderClearClass::getById($clearId, true);
+        if (empty($clear)) {
+            return $row;
+        }
+        $row['clearId'] = $clearId;
+        $row['clearSn'] = is_object($clear) ? ($clear->orderSn ?? '') : ($clear['orderSn'] ?? '');
+        $actPrice = is_object($clear) ? ($clear->actPrice ?? 0) : ($clear['actPrice'] ?? 0);
+        $row['clearAmount'] = bcadd((string)$actPrice, '0', 2);
+        return self::normalizeClearAuditRow($row);
+    }
+
+    /**
+     * 充值入账与结账单关联:同客户、同实收金额、付款时间接近的已付结账单
+     */
+    protected static function fillClearAuditByPaidClearMatch(array $row, $recharge = null)
+    {
+        $customId = intval($row['customId'] ?? 0);
+        if ($customId <= 0) {
+            return $row;
+        }
+        $amount = bcadd((string)($row['amount'] ?? 0), '0', 2);
+        $anchorTime = (string)($row['addTime'] ?? '');
+        if (!empty($recharge)) {
+            $amount = bcadd((string)(is_object($recharge) ? ($recharge->amount ?? $amount) : ($recharge['amount'] ?? $amount)), '0', 2);
+            $payTime = is_object($recharge) ? ($recharge->payTime ?? '') : ($recharge['payTime'] ?? '');
+            if (!empty($payTime) && $payTime !== '0000-00-00 00:00:00') {
+                $anchorTime = $payTime;
+            }
+        }
+        $list = OrderClearClass::getAllByCondition([
+            'customId' => $customId,
+            'status' => PurchaseClearClass::STATUS_HAS_PAY,
+            'actPrice' => $amount,
+        ], 'payTime DESC,id DESC', '*', null, true);
+        if (empty($list)) {
+            return $row;
+        }
+        $best = null;
+        $bestDiff = null;
+        $anchorTs = !empty($anchorTime) ? strtotime($anchorTime) : 0;
+        foreach ($list as $clear) {
+            $clearId = intval(is_object($clear) ? ($clear->id ?? 0) : ($clear['id'] ?? 0));
+            if ($clearId <= 0) {
+                continue;
+            }
+            if ($anchorTs <= 0) {
+                $best = $clear;
+                break;
+            }
+            $payTime = is_object($clear) ? ($clear->payTime ?? '') : ($clear['payTime'] ?? '');
+            $payTs = !empty($payTime) ? strtotime($payTime) : 0;
+            if ($payTs <= 0) {
+                continue;
+            }
+            $diff = abs($anchorTs - $payTs);
+            if ($bestDiff === null || $diff < $bestDiff) {
+                $bestDiff = $diff;
+                $best = $clear;
+            }
+        }
+        if (empty($best) || $bestDiff === null || $bestDiff > 300) {
+            return $row;
+        }
+        $clearId = intval(is_object($best) ? ($best->id ?? 0) : ($best['id'] ?? 0));
+        return self::attachClearMetaFromClearId($row, $clearId);
+    }
+
+    protected static function normalizeClearAuditRow(array $row)
+    {
+        if (intval($row['clearId'] ?? 0) > 0 && (empty($row['clearSn']) || bccomp((string)($row['clearAmount'] ?? 0), '0', 2) <= 0)) {
+            $row = self::attachClearMetaFromClearId($row, intval($row['clearId']));
+        }
+        return $row;
+    }
+
+    /** 供货商帮充 / 线上充 / 售后返充 */
+    protected static function isRechargeCapitalType($capitalType)
+    {
+        $capitalType = intval($capitalType);
+        $ids = [
+            dict::getDict('capitalType', 'ghsHelpCustomRecharge', 'id'),
+            dict::getDict('capitalType', 'ghsHelpCustomRechargeReturn', 'id'),
+            dict::getDict('capitalType', 'customRechargeToGhs', 'id'),
+        ];
+        return in_array($capitalType, $ids, true);
+    }
+
+    /** 结账类入账(relateId=结账单 id) */
+    protected static function isClearIncomeCapitalType($capitalType)
+    {
+        $capitalType = intval($capitalType);
+        $ids = [
+            dict::getDict('capitalType', 'ghsXsClear', 'id'),
+            dict::getDict('capitalType', 'ghsHelpCustomUseBalanceClear', 'id'),
+            dict::getDict('capitalType', 'customAskGhsUseBalanceClear', 'id'),
+        ];
+        return in_array($capitalType, $ids, true);
+    }
+
+    /**
+     * 充值销账后回写流水上的 clearId(GhsRechargeSettleService 调用)
+     */
+    public static function patchClearAuditByRechargeId($customId, $rechargeId, $clearId, $clearSn, $clearAmount, $finalBalance = null)
+    {
+        $customId = intval($customId);
+        $rechargeId = intval($rechargeId);
+        $clearId = intval($clearId);
+        if ($customId <= 0 || $rechargeId <= 0 || $clearId <= 0) {
+            return;
+        }
+        $row = self::getByCondition([
+            'customId' => $customId,
+            'relateId' => $rechargeId,
+            'io' => 1,
+        ], true, null, 'id DESC');
+        if (empty($row) || !method_exists($row, 'hasAttribute') || !$row->hasAttribute('clearId')) {
+            return;
+        }
+        $row->clearId = $clearId;
+        $row->clearSn = (string)$clearSn;
+        $row->clearAmount = bcadd((string)$clearAmount, '0', 2);
+        if ($finalBalance !== null && $row->hasAttribute('balance')) {
+            $row->balance = $finalBalance;
+        }
+        if ($row->hasAttribute('giveAmount')) {
+            $row->giveAmount = '0.00';
+        }
+        $row->save(false);
+    }
+
 
     public static function exportData($respond, $mainId)
     {

+ 6 - 0
biz-ghs/custom/classes/CustomClass.php

@@ -363,6 +363,9 @@ class CustomClass extends BaseClass
             'payTime' => $payTime,
             'rechargeType' => $rechargeType,
         ];
+        if (!empty($params['clearAudit']) && is_array($params['clearAudit'])) {
+            $cData = CustomBalanceChangeClass::mergeClearAuditIntoRechargeData($cData, $params['clearAudit']);
+        }
         $cRecharge = CustomRechargeClass::add($cData, true);
         $cRechargeId = $cRecharge->id ?? 0;
 
@@ -393,6 +396,9 @@ class CustomClass extends BaseClass
             'sjId' => $sjId,
             'remark' => $remark,
         ];
+        if (!empty($params['clearAudit']) && is_array($params['clearAudit'])) {
+            $cbData = CustomBalanceChangeClass::mergeClearAuditIntoRowData($cbData, $params['clearAudit']);
+        }
         CustomBalanceChangeClass::add($cbData, true);
 
         $ghsInfo->balance = bcadd($ghsInfo->balance, $amount, 2);

+ 21 - 4
biz-ghs/custom/services/GhsRechargeSettleService.php

@@ -85,10 +85,19 @@ class GhsRechargeSettleService
             util::fail('结账单金额有误');
         }
 
+        $clearId = intval($clear->id ?? 0);
+        $clearSn = $clear->orderSn ?? '';
+        $clearAudit = [
+            'clearId' => $clearId,
+            'clearSn' => $clearSn,
+            'clearAmount' => $pool,
+        ];
+
         $ghsRecharge = null;
         if (empty($customRecharge)) {
             $respond = CustomClass::rechargeBalance($custom, $pool, $shop, $staff, $payWay, [
                 'remark' => $clear->remark ?? '',
+                'clearAudit' => $clearAudit,
             ]);
             $custom = $respond['custom'];
             $ghs = $respond['ghs'];
@@ -98,18 +107,19 @@ class GhsRechargeSettleService
 
         OrderClearClass::applyNetBalanceClear($clear, $payWay, ['skipCashMoney' => true]);
 
-        $settled = self::money(OrderClearClass::sumClearAmountByClearId($clear->id ?? 0));
+        $settled = self::money(OrderClearClass::sumClearAmountByClearId($clearId));
         if (bccomp($settled, $pool, 2) > 0) {
             $settled = $pool;
         }
+        $clearAudit['clearAmount'] = $settled;
 
         self::refreshDebtFlags($custom, $ghs);
 
         $allocate = [
             'clear' => $clear,
             'realClearAmount' => $settled,
-            'clearId' => $clear->id ?? 0,
-            'clearSn' => $clear->orderSn ?? '',
+            'clearId' => $clearId,
+            'clearSn' => $clearSn,
             'clearAmount' => $settled,
         ];
 
@@ -342,7 +352,14 @@ class GhsRechargeSettleService
         }
 
         $relateId = $customRecharge->id ?? 0;
-        self::patchBalanceChangeRow(CustomBalanceChangeClass::class, $relateId, $clearId, $clearSn, $clearAmount, [], $finalCustomBalance);
+        $customId = is_object($custom) ? intval($custom->id ?? 0) : 0;
+        if ($customId <= 0 && is_object($customRecharge)) {
+            $customId = intval($customRecharge->customId ?? 0);
+        }
+        CustomBalanceChangeClass::patchClearAuditByRechargeId($customId, $relateId, $clearId, $clearSn, $clearAmount, $finalCustomBalance);
+        self::patchBalanceChangeRow(CustomBalanceChangeClass::class, $relateId, $clearId, $clearSn, $clearAmount, [
+            'customId' => $customId,
+        ], $finalCustomBalance);
 
         if (!empty($ghsRecharge)) {
             $gRelateId = $ghsRecharge->id ?? 0;