Files
lotteryLaravel/app/Support/PlayerApiPresenter.php
kang a44679665d feat: 增强代理和玩家管理功能
- 在多个控制器中更新权限检查逻辑,确保管理员能够更灵活地管理代理和玩家。
- 在 AdminPlayerStoreController 中引入对玩家创建能力的验证,确保只有具备相应权限的管理员能够创建玩家。
- 更新请求验证逻辑,新增 credit_limit、rebate_rate 和 extra_rebate_rate 字段,以支持更细粒度的玩家管理。
- 在 AgentNodeProfileController 中添加对父代理能力授予的验证,确保子代理的权限在父代理范围内。
- 引入 AgentProfileFieldRules 以简化代理资料更新请求的规则定义,提升代码复用性。
2026-06-04 18:00:50 +08:00

102 lines
4.0 KiB
PHP

<?php
namespace App\Support;
use App\Models\AgentProfile;
use App\Models\Player;
use App\Models\PlayerWallet;
use App\Support\PlayerFundingMode;
use Illuminate\Support\Facades\DB;
/** 玩家 API 统一 JSON 形状(列表行 / 详情)。 */
final class PlayerApiPresenter
{
/** @return array<string, mixed> */
public static function listItem(Player $player): array
{
$wallets = $player->relationLoaded('wallets')
? $player->wallets
: $player->wallets()->get();
$walletRows = $wallets->map(static fn (PlayerWallet $w): array => [
'wallet_type' => $w->wallet_type,
'currency_code' => $w->currency_code,
'balance' => (int) $w->balance,
'frozen_balance' => (int) $w->frozen_balance,
'available_balance' => max(0, (int) $w->balance - (int) $w->frozen_balance),
'status' => (int) $w->status,
])->values()->all();
$agent = $player->relationLoaded('agentNode')
? $player->agentNode
: ($player->agent_node_id ? $player->agentNode()->first() : null);
$usesCredit = PlayerFundingMode::usesCredit($player);
$credit = DB::table('player_credit_accounts')->where('player_id', $player->id)->first();
$creditLimit = $credit !== null ? (int) $credit->credit_limit : ($usesCredit ? 0 : null);
$usedCredit = $credit !== null ? (int) $credit->used_credit : ($usesCredit ? 0 : null);
$availableCredit = $credit !== null
? max(0, (int) $credit->credit_limit - (int) $credit->used_credit - (int) $credit->frozen_credit)
: ($usesCredit ? 0 : null);
[$rebateRate, $rebateInherited] = self::resolveListRebate($player, $agent);
return [
'id' => (int) $player->id,
...AgentNodeApiPresenter::embed($agent),
'site_code' => $player->site_code,
'site_player_id' => $player->site_player_id,
'auth_source' => $player->auth_source,
'funding_mode' => $player->funding_mode,
'username' => $player->username,
'nickname' => $player->nickname,
'default_currency' => $player->default_currency,
'status' => (int) $player->status,
'last_login_at' => $player->last_login_at?->toIso8601String(),
'created_at' => $player->created_at?->toIso8601String(),
'wallets' => $walletRows,
'uses_credit' => $usesCredit,
'credit_limit' => $creditLimit,
'used_credit' => $usedCredit,
'available_credit' => $availableCredit,
'rebate_rate' => $rebateRate,
'rebate_inherited' => $rebateInherited,
'risk_tags' => $player->risk_tags ?? [],
'rebate_profiles' => DB::table('player_rebate_profiles')
->where('player_id', $player->id)
->orderBy('game_type')
->get()
->map(static fn (object $row): array => [
'game_type' => (string) $row->game_type,
'rebate_rate' => (float) $row->rebate_rate,
'extra_rebate_rate' => (float) $row->extra_rebate_rate,
'inherit_from_agent' => (bool) $row->inherit_from_agent,
])
->all(),
];
}
/**
* @return array{0: ?float, 1: bool} rebate rate (ratio) and whether inherited from agent
*/
private static function resolveListRebate(Player $player, ?\App\Models\AgentNode $agent): array
{
$row = DB::table('player_rebate_profiles')
->where('player_id', $player->id)
->where('game_type', '*')
->first();
if ($row !== null && ! (bool) $row->inherit_from_agent) {
return [(float) $row->rebate_rate, false];
}
if ($agent !== null) {
$profile = AgentProfile::query()->where('agent_node_id', $agent->id)->first();
return [(float) ($profile?->default_player_rebate ?? 0), true];
}
return [null, false];
}
}