shish 4 часов назад
Родитель
Сommit
dddd88aebf
2 измененных файлов с 102 добавлено и 10 удалено
  1. 21 0
      biz-ghs/forward/classes/ForwardClass.php
  2. 81 10
      biz-ghs/stat/classes/StatKdClass.php

+ 21 - 0
biz-ghs/forward/classes/ForwardClass.php

@@ -41,6 +41,27 @@ class ForwardClass extends BaseClass
         return bcadd($row['total'] ?? '0', '0', 2);
     }
 
+    /**
+     * 拉取时段内成功冲销凭证及关联原单支付字段,供渠道收入按原入账渠道对冲。
+     * 为何联表:挂账单冲销应扣「挂账已结」,不能一律扣「系统收款」。
+     * @return array 每行含 amount/payWay/orderId/debtPrice/remainDebtPrice/onlinePay/orderPayWay
+     */
+    public static function listForChannelIncomeDeduct($mainId, $startTime, $endTime)
+    {
+        $sql = "SELECT f.amount, f.payWay, f.orderId, f.fundType,
+                o.debtPrice, o.remainDebtPrice, o.onlinePay, o.payWay AS orderPayWay
+            FROM xhGhsForward f
+            LEFT JOIN xhGhsOrder o ON o.id = f.orderId
+            WHERE f.mainId=:mainId AND f.status=:status AND f.addTime BETWEEN :start AND :end";
+        $rows = Yii::$app->db->createCommand($sql, [
+            ':mainId' => $mainId,
+            ':status' => self::STATUS_SUCCESS,
+            ':start' => $startTime,
+            ':end' => $endTime,
+        ])->queryAll();
+        return $rows ?: [];
+    }
+
     /**
      * 按客户汇总成功冲销金额(customId => amount)
      */

+ 81 - 10
biz-ghs/stat/classes/StatKdClass.php

@@ -411,19 +411,90 @@ class StatKdClass extends BaseClass
                 $staffAmountList[$staffId] = ['num' => 1, 'amount' => $currentAmount, 'staffName' => $staffName];
             }
         }
-        // 方案A:渠道收入总计扣减成功冲销金额(笔数不因冲销增减)
-        $fwdAmount = ForwardClass::sumAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime);
-        if (bccomp((string)$fwdAmount, '0', 2) > 0) {
-            $incomeList['system']['amount'] = bcsub((string)$incomeList['system']['amount'], (string)$fwdAmount, 2);
-            $incomeList['system']['category']['pf']['amount'] = bcsub(
-                (string)$incomeList['system']['category']['pf']['amount'],
-                (string)$fwdAmount,
-                2
-            );
-        }
+        // 方案A:按原单入账渠道扣减成功冲销金额(只减金额不减笔数;挂账已结扣 debtClear)
+        self::deductForwardFromChannelIncome($incomeList, $mainId, $currentStartTime, $currentEndTime);
 
         return ['incomeList' => $incomeList, 'staffAmountList' => $staffAmountList, 'payCodeIncome' => $payCodeIncome, 'lsAfterSale' => $lsAfterSale];
 
     }
 
+    /**
+     * 渠道收入对冲冲销:按原销售单当时计入的渠道扣金额。
+     * 挂账已结 → debtClear;挂账未结 → debt;在线付 → system;线下按 payWay。
+     * 自由冲销无原单时按凭证 payWay(多为余额)扣,避免误进系统收款。
+     */
+    protected static function deductForwardFromChannelIncome(&$incomeList, $mainId, $startTime, $endTime)
+    {
+        $rows = ForwardClass::listForChannelIncomeDeduct($mainId, $startTime, $endTime);
+        if (empty($rows)) {
+            return;
+        }
+        foreach ($rows as $row) {
+            $amount = bcadd((string)($row['amount'] ?? '0'), '0', 2);
+            if (bccomp($amount, '0', 2) <= 0) {
+                continue;
+            }
+            $channel = self::resolveForwardIncomeChannel($row);
+            if (empty($channel) || !isset($incomeList[$channel])) {
+                $channel = 'other';
+            }
+            $incomeList[$channel]['amount'] = bcsub((string)$incomeList[$channel]['amount'], $amount, 2);
+            // 批发冲销明细落在 pf;无 category 的渠道(如美团)只扣总额
+            if (isset($incomeList[$channel]['category']['pf'])) {
+                $incomeList[$channel]['category']['pf']['amount'] = bcsub(
+                    (string)$incomeList[$channel]['category']['pf']['amount'],
+                    $amount,
+                    2
+                );
+            }
+        }
+    }
+
+    /**
+     * 根据冲销凭证 + 关联原单字段,映射到 kdIncome 渠道 key(与批发开单入账分支一致)
+     */
+    protected static function resolveForwardIncomeChannel($row)
+    {
+        $debtPrice = bcadd((string)($row['debtPrice'] ?? '0'), '0', 2);
+        $remainDebt = bcadd((string)($row['remainDebtPrice'] ?? '0'), '0', 2);
+        $orderId = intval($row['orderId'] ?? 0);
+        $payWay = intval($row['orderPayWay'] ?? ($row['payWay'] ?? 0));
+        if ($orderId <= 0) {
+            $payWay = intval($row['payWay'] ?? 0);
+        }
+        $onlinePay = intval($row['onlinePay'] ?? dict::getDict('onlinePay', 'not'));
+
+        // 有挂账标记的原单:已结清进「挂账已结」,未结进「挂账未结」
+        if ($orderId > 0 && bccomp($debtPrice, '0', 2) > 0) {
+            if (bccomp($remainDebt, '0', 2) > 0) {
+                return 'debt';
+            }
+            return 'debtClear';
+        }
+
+        if ($onlinePay == dict::getDict('onlinePay', 'yes')) {
+            return 'system';
+        }
+
+        switch ($payWay) {
+            case dict::getDict('payWay', 'wxPay'):
+                return 'kfWx';
+            case dict::getDict('payWay', 'alipay'):
+                return 'aliPay';
+            case dict::getDict('payWay', 'cash'):
+                return 'cash';
+            case dict::getDict('payWay', 'balancePay'):
+                return 'balancePay';
+            case dict::getDict('payWay', 'bankCard'):
+                return 'bankCard';
+            case dict::getDict('payWay', 'debtPay'):
+                // 凭证记欠款但原单无 debtPrice 时,按已结挂账对冲(冲销前提多为已结清)
+                return 'debtClear';
+            case dict::getDict('payWay', 'unknown'):
+                return 'other';
+            default:
+                return 'other';
+        }
+    }
+
 }