diff --git a/addons/shopro/library/split/SplitCalculator.php b/addons/shopro/library/split/SplitCalculator.php index 72e1285..ec71564 100644 --- a/addons/shopro/library/split/SplitCalculator.php +++ b/addons/shopro/library/split/SplitCalculator.php @@ -58,6 +58,92 @@ class SplitCalculator return $items; } + /** + * 诊断为何未走佣金分账(供后台展示) + * @return array{amount_source:string,final_source:string,issues:array,commission_total:float,rule_total:float} + */ + public function diagnose($orderId) + { + $order = Order::get($orderId); + $amountSource = $this->config->getAmountSource(); + $issues = []; + $commissionTotal = 0.0; + + if (!$order) { + return [ + 'amount_source' => $amountSource, + 'final_source' => 'none', + 'issues' => ['订单不存在'], + 'commission_total'=> 0, + 'rule_total' => 0, + ]; + } + + $payFee = floatval($order['pay_fee']); + $commissionRewards = CommissionReward::where('order_id', $orderId)->where('status', '>=', 0)->select(); + if ($commissionRewards->isEmpty()) { + $issues[] = '该订单无分销佣金记录(未产生推广关系或未参与分销)'; + } + + foreach ($commissionRewards as $reward) { + $userId = intval($reward['agent_id']); + $amount = floatval($reward['commission']); + if ($userId <= 0) { + $issues[] = '佣金记录 agent_id 无效'; + continue; + } + if ($amount <= 0) { + continue; + } + $receiver = $this->getReceiver('promoter', $userId); + if (!$receiver) { + $issues[] = sprintf( + '推广员#%d 佣金¥%s 无汇付接收方(分账接收方 role_id 须等于该 user_id)', + $userId, + number_format($amount, 2, '.', '') + ); + continue; + } + $commissionTotal += $amount; + } + + $regionalRewards = $this->getRegionalRewardsByOrderId($orderId); + foreach ($regionalRewards as $reward) { + $uid = intval($reward['agent_user_id']); + $amount = floatval($reward['commission']); + if ($uid <= 0 || $amount <= 0) { + continue; + } + if (!$this->getReceiver('regional_agent', $uid)) { + $issues[] = sprintf('区域代理#%d 佣金¥%s 无汇付接收方', $uid, number_format($amount, 2, '.', '')); + continue; + } + $commissionTotal += $amount; + } + + $commissionItems = $this->calculateFromCommission($orderId); + $ruleItems = $this->calculateFromRules($payFee); + $ruleTotal = array_sum(array_column($ruleItems, 'amount')); + + $finalSource = 'none'; + if (!empty($commissionItems) && in_array($amountSource, ['commission', 'mixed'])) { + $finalSource = 'commission'; + } elseif (!empty($ruleItems) && ($amountSource === 'rule' || ($amountSource === 'mixed' && empty($commissionItems)))) { + $finalSource = 'rule'; + if ($amountSource === 'mixed' && !empty($issues)) { + $issues[] = '已回退到分账规则(如推广员 5%),金额与佣金不一致'; + } + } + + return [ + 'amount_source' => $amountSource, + 'final_source' => $finalSource, + 'issues' => $issues, + 'commission_total' => round($commissionTotal, 2), + 'rule_total' => round($ruleTotal, 2), + ]; + } + protected function getRegionalRewardsByOrderId($orderId) { try { @@ -78,9 +164,9 @@ class SplitCalculator $commissionRewards = CommissionReward::where('order_id', $orderId)->where('status', '>=', 0)->select(); foreach ($commissionRewards as $reward) { - $agent = \addons\shopro\model\commission\Agent::get($reward['agent_id']); - $userId = $agent ? $agent['user_id'] : 0; - if (!$userId) { + // agent_id 即分销商 user_id(shopro_commission_agent 主键) + $userId = intval($reward['agent_id']); + if ($userId <= 0) { continue; } $receiver = $this->getReceiver('promoter', $userId); diff --git a/application/admin/controller/shopro/split/Order.php b/application/admin/controller/shopro/split/Order.php index cbb418a..33dafeb 100644 --- a/application/admin/controller/shopro/split/Order.php +++ b/application/admin/controller/shopro/split/Order.php @@ -148,6 +148,13 @@ class Order extends Base $data['receiver_summary'] = $summaryLines ? implode(';', $summaryLines) : '—'; $data['fail_reason'] = $this->formatFailReason($data['wx_result'] ?? '', $status); + $diag = (new SplitCalculator())->diagnose($orderId); + $data['split_source'] = $diag['final_source']; + $data['split_source_text'] = $this->formatSplitSourceText($diag); + $data['split_diagnose'] = $diag['issues']; + $data['commission_total'] = $diag['commission_total']; + $data['rule_total'] = $diag['rule_total']; + unset($data['order'], $data['receivers']); $rows[] = $data; } @@ -280,6 +287,22 @@ class Order extends Base return $mobile; } + protected function formatSplitSourceText(array $diag) + { + $map = [ + 'commission' => '按佣金分账', + 'rule' => '按规则分账(兜底)', + 'none' => '未算出明细', + ]; + $text = $map[$diag['final_source'] ?? ''] ?? '-'; + if (($diag['final_source'] ?? '') === 'commission' && ($diag['commission_total'] ?? 0) > 0) { + $text .= ' ¥' . number_format(floatval($diag['commission_total']), 2, '.', ''); + } elseif (($diag['final_source'] ?? '') === 'rule' && ($diag['rule_total'] ?? 0) > 0) { + $text .= ' ¥' . number_format(floatval($diag['rule_total']), 2, '.', ''); + } + return $text; + } + protected function formatFailReason($wxResult, $status) { if ($status !== 4 || $wxResult === '' || $wxResult === null) { diff --git a/application/admin/view/shopro/split/order/index.html b/application/admin/view/shopro/split/order/index.html index 59b7006..6f53ff2 100644 --- a/application/admin/view/shopro/split/order/index.html +++ b/application/admin/view/shopro/split/order/index.html @@ -164,6 +164,24 @@ line-height: 1.5; white-space: nowrap; } + .source-tag { + display: inline-block; + padding: 0 6px; + border-radius: 4px; + font-size: 11px; + line-height: 18px; + white-space: nowrap; + margin-top: 4px; + } + .source-tag.commission { background: #ecf5ff; color: #409eff; } + .source-tag.rule { background: #fdf6ec; color: #e6a23c; } + .diagnose-hint { + font-size: 11px; + color: #e6a23c; + line-height: 1.5; + margin-top: 4px; + white-space: normal; + } .op-hint { font-size: 12px; color: #909399; @@ -230,11 +248,14 @@ - + @@ -252,6 +273,9 @@ ¥{{ formatMoney(r.amount) }}
按当前规则预估(历史失败单未落库明细)
+
+ {{ s.row.split_diagnose.join(';') }} +
—