- 在多个控制器中更新权限检查逻辑,确保管理员能够更灵活地管理代理和玩家。 - 在 AdminPlayerStoreController 中引入对玩家创建能力的验证,确保只有具备相应权限的管理员能够创建玩家。 - 更新请求验证逻辑,新增 credit_limit、rebate_rate 和 extra_rebate_rate 字段,以支持更细粒度的玩家管理。 - 在 AgentNodeProfileController 中添加对父代理能力授予的验证,确保子代理的权限在父代理范围内。 - 引入 AgentProfileFieldRules 以简化代理资料更新请求的规则定义,提升代码复用性。
102 lines
4.0 KiB
PHP
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];
|
|
}
|
|
}
|