feat(split): 添加分账诊断功能用于后台展示

- 新增 SplitCalculator::diagnose() 方法,用于诊断订单分账问题
- 返回分账来源、佣金总额、规则总额及具体问题说明
- 在管理员分账订单控制器中集成诊断信息显示
- 优化前端表格显示分账来源标签和诊断提示信息
- 修复佣金奖励查询中 agent_id 使用错误的问题
```
这个提交包含在:
可乐加冰
2026-10-05 13:05:53 +08:00
父节点 9181c7144f
当前提交 34c005d271
共有 3 个文件被更改,包括 137 次插入 和 4 次删除

查看文件

@@ -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);