feat(commission): 重构分销商详情运营统计看板紧扣恒联业务与方案B一体化大余额

这个提交包含在:
chen
2026-09-29 15:07:07 +08:00
父节点 40f36c8889
当前提交 dbb9951857
共有 3 个文件被更改,包括 815 次插入 和 185 次删除

查看文件

@@ -69,7 +69,7 @@ class Agent extends Common
$detail->next_push3_text = '第 ' . ($seq + 1) . ' 单将返 ' . $detail->next_push3_amount;
$detail->last_self_order_text = $last ? date('Y-m-d H:i:s', $last) : '从未下单';
// 业务核心规范:进阶角色(创客V1~V6、酒道馆、区县代理、合伙股东)需自购考核;基础会员及品酒师免自购考核
// 业务核心规范:进阶角色(创客V1~V6、酒道馆、区县代理、合伙人)需自购考核;基础会员及品酒师免自购考核
if (!$isAdvanced) {
$detail->active_status_text = '免自购考核 (基础会员/品酒师)';
} else {
@@ -101,18 +101,204 @@ class Agent extends Common
$detail->total_income = $alignedIncome;
$detail->partner_cash_income = $alignedIncome;
$detail->push3_cash_income = number_format((float) $push3Cash, 2, '.', '');
$detail->partner_exclusive_cash = number_format((float) $partnerExclusiveCash, 2, '.', '');
$detail->user_money = number_format(floatval($detail->user ? $detail->user->money : 0), 2, '.', '');
$detail->user_commission = number_format(floatval($detail->user ? $detail->user->commission : 0), 2, '.', '');
$userData = $detail->user ? $detail->user->getData() : [];
$userMoney = $userData['money'] ?? 0;
$userCommission = $userData['commission'] ?? 0;
$detail->user_money = number_format(floatval($userMoney), 2, '.', '');
$detail->user_commission = number_format(floatval($userCommission), 2, '.', '');
$detail->partner_mode = \addons\shopro\service\partner\PartnerConfig::isPartnerMode() ? 1 : 0;
$rate = (new \addons\shopro\service\partner\RateService())->currentRate();
$detail->madow_value = \addons\shopro\service\partner\IdentityService::formatMoney((float) ($detail->madow ?? 0) * (float) $rate);
$detail->custom_role_names = \addons\shopro\service\partner\PartnerConfig::roleNames();
$detail->role_names = $detail->custom_role_names;
$detail->operational_stats = $this->getOperationalStats($detail, $id);
$this->success('分销商详情', null, $detail);
}
/**
* 构建运营官全景统计数据看板
*/
private function getOperationalStats($detail, $id)
{
$allUsers = \think\Db::name('user')->column('parent_user_id', 'id');
$getDesc = function ($uid) use (&$getDesc, $allUsers) {
$res = [];
foreach ($allUsers as $cid => $pid) {
if ((int)$pid === (int)$uid) {
$res[] = $cid;
$res = array_merge($res, $getDesc($cid));
}
}
return $res;
};
$descIds = $getDesc($id);
$directIds = [];
foreach ($allUsers as $cid => $pid) {
if ((int)$pid === (int)$id) {
$directIds[] = $cid;
}
}
// 1. 团队角色拓扑
$directCount = count($directIds);
$directPaidCount = empty($directIds) ? 0 : \think\Db::name('user')->whereIn('id', $directIds)->where('total_consume', '>', 0)->count();
$directMakerCount = empty($directIds) ? 0 : \think\Db::name('shopro_commission_agent')->whereIn('user_id', $directIds)->where('level', '>=', 2)->count();
$teamDescCount = count($descIds);
$teamPaidCount = empty($descIds) ? 0 : \think\Db::name('user')->whereIn('id', $descIds)->where('total_consume', '>', 0)->count();
$teamMakerAgents = empty($descIds) ? [] : \think\Db::name('shopro_commission_agent')->whereIn('user_id', $descIds)->where('level', '>=', 2)->column('level');
$teamMakerCount = count($teamMakerAgents);
$teamMakerDistribution = array_count_values($teamMakerAgents);
ksort($teamMakerDistribution);
$makerDistribution = [
'v1' => intval($teamMakerDistribution[2] ?? 0),
'v2' => intval($teamMakerDistribution[3] ?? 0),
'v3' => intval($teamMakerDistribution[4] ?? 0),
'v4' => intval($teamMakerDistribution[5] ?? 0),
'v5' => intval($teamMakerDistribution[6] ?? 0),
'v6' => intval($teamMakerDistribution[7] ?? 0),
];
$teamVenueCount = empty($descIds) ? 0 : \think\Db::name('shopro_commission_agent')->whereIn('user_id', $descIds)->where('is_venue', 1)->count();
$teamCountyCount = empty($descIds) ? 0 : \think\Db::name('shopro_commission_agent')->whereIn('user_id', $descIds)->where('is_county', 1)->count();
$conversionRate = $teamDescCount > 0 ? round(($teamPaidCount / $teamDescCount) * 100, 1) : 0.0;
// 2. 收益分成细项
$rewards = \think\Db::name('shopro_partner_reward')
->where('user_id', $id)
->where('status', 1)
->group('reward_type')
->column('sum(amount)', 'reward_type');
$push3Income = (float)($rewards['push3'] ?? 0);
$makerDiffIncome = (float)($rewards['maker_diff'] ?? 0);
$makerPeerIncome = (float)(($rewards['maker_peer'] ?? 0) + ($rewards['maker_overtaken'] ?? 0));
$teamSplitIncome = (float)(($rewards['team_venue'] ?? 0) + ($rewards['team_county'] ?? 0));
$sharePoolIncome = (float)(($rewards['venue_share'] ?? 0) + ($rewards['county_share'] ?? 0));
// 3. 业绩与订单分类
$selfOrderMoney = number_format((float)($detail->child_order_money_0 ?? 0), 2, '.', '');
$selfOrderCount = intval($detail->child_order_count_0 ?? 0);
$directOrderMoney = number_format((float)($detail->child_order_money_1 ?? 0), 2, '.', '');
$directOrderCount = intval($detail->child_order_count_1 ?? 0);
$teamOrderMoney = number_format((float)($detail->child_order_money_all ?? 0), 2, '.', '');
$teamOrderCount = intval($detail->child_order_count_all ?? 0);
$indirectOrderMoney = number_format(max(0, (float)$teamOrderMoney - (float)$directOrderMoney - (float)$selfOrderMoney), 2, '.', '');
$indirectOrderCount = max(0, $teamOrderCount - $directOrderCount - $selfOrderCount);
// 4. 晋升考核差距雷达
$currentLevel = intval($detail->level ?? 1);
$currentLevelRow = \think\Db::name('shopro_commission_level')->where('level', $currentLevel)->find();
$currentLevelName = $currentLevelRow ? $currentLevelRow['name'] : ($currentLevel >= 2 ? '创客V' . ($currentLevel - 1) : '品酒师');
$nextLevel = $currentLevel + 1;
$nextLevelRow = \think\Db::name('shopro_commission_level')->where('level', $nextLevel)->find();
if ($nextLevelRow) {
$nextRules = json_decode($nextLevelRow['upgrade_rules'] ?? '[]', true) ?: [];
$targetDirectUsers = intval($nextRules['child_user_count_1'] ?? 0);
$targetTeamOrders = intval($nextRules['child_order_count_all'] ?? 0);
$currentDirectUsers = intval($detail->child_user_count_1 ?? $directCount);
$currentTeamOrders = intval($detail->child_order_count_all ?? 0);
$currentSelfMoney = (float)($detail->child_order_money_0 ?? 0);
$directUserGap = max(0, $targetDirectUsers - $currentDirectUsers);
$teamOrderGap = max(0, $targetTeamOrders - $currentTeamOrders);
$isSelfPaid = ($selfOrderCount > 0 || $currentSelfMoney >= 1398);
$directUserPercent = $targetDirectUsers > 0 ? min(100, (int)round(($currentDirectUsers / $targetDirectUsers) * 100)) : 100;
$teamOrderPercent = $targetTeamOrders > 0 ? min(100, (int)round(($currentTeamOrders / $targetTeamOrders) * 100)) : 100;
$upgradeRadar = [
'current_level' => $currentLevel,
'current_level_name' => $currentLevelName,
'next_level' => $nextLevel,
'next_level_name' => $nextLevelRow['name'],
'target_direct_users' => $targetDirectUsers,
'current_direct_users' => $currentDirectUsers,
'direct_user_gap' => $directUserGap,
'direct_user_reached' => ($directUserGap === 0),
'direct_user_percent' => $directUserPercent,
'target_team_orders' => $targetTeamOrders,
'current_team_orders' => $currentTeamOrders,
'team_order_gap' => $teamOrderGap,
'team_order_reached' => ($teamOrderGap === 0),
'team_order_percent' => $teamOrderPercent,
'self_paid_reached' => $isSelfPaid,
'all_reached' => ($directUserGap === 0 && $teamOrderGap === 0 && $isSelfPaid),
'upgrade_lock' => intval($detail->upgrade_lock ?? 0)
];
} else {
$upgradeRadar = [
'current_level' => $currentLevel,
'current_level_name' => $currentLevelName,
'next_level' => 0,
'next_level_name' => '已达最高职级',
'target_direct_users' => 0,
'current_direct_users' => intval($detail->child_user_count_1 ?? $directCount),
'direct_user_gap' => 0,
'direct_user_reached' => true,
'direct_user_percent' => 100,
'target_team_orders' => 0,
'current_team_orders' => intval($detail->child_order_count_all ?? 0),
'team_order_gap' => 0,
'team_order_reached' => true,
'team_order_percent' => 100,
'self_paid_reached' => true,
'all_reached' => true,
'upgrade_lock' => intval($detail->upgrade_lock ?? 0)
];
}
return [
'roles' => [
'direct_total' => $directCount,
'direct_paid' => $directPaidCount,
'direct_unpaid' => max(0, $directCount - $directPaidCount),
'direct_maker' => $directMakerCount,
'team_total' => $teamDescCount,
'team_paid' => $teamPaidCount,
'team_unpaid' => max(0, $teamDescCount - $teamPaidCount),
'team_conversion_rate' => $conversionRate,
'team_maker' => $teamMakerCount,
'team_maker_distribution' => $makerDistribution,
'team_venue' => $teamVenueCount,
'team_county' => $teamCountyCount,
],
'orders' => [
'self_money' => $selfOrderMoney,
'self_count' => $selfOrderCount,
'direct_money' => $directOrderMoney,
'direct_count' => $directOrderCount,
'indirect_money' => $indirectOrderMoney,
'indirect_count' => $indirectOrderCount,
'team_money' => $teamOrderMoney,
'team_count' => $teamOrderCount,
],
'rewards' => [
'push3' => number_format($push3Income, 2, '.', ''),
'maker_diff' => number_format($makerDiffIncome, 2, '.', ''),
'maker_peer' => number_format($makerPeerIncome, 2, '.', ''),
'maker_total' => number_format($makerDiffIncome + $makerPeerIncome, 2, '.', ''),
'team_split' => number_format($teamSplitIncome, 2, '.', ''),
'share_pool' => number_format($sharePoolIncome, 2, '.', ''),
],
'assets' => [
'wallet_money' => $detail->user_money,
'total_income' => $detail->total_income,
'untransfer_commission' => $detail->user_commission,
'dmepa_madow' => number_format((float)($detail->madow ?? 0), 4, '.', ''),
'dmepa_value' => $detail->madow_value,
'voucher_total' => number_format((float)($detail->voucher_total ?? 0), 2, '.', ''),
'voucher_released' => number_format((float)($detail->voucher_released ?? 0), 2, '.', ''),
'voucher_available' => number_format(max(0, (float)($detail->voucher_released ?? 0) - (float)($detail->voucher_used ?? 0)), 2, '.', ''),
],
'upgrade_radar' => $upgradeRadar
];
}
/**
* 团队