lotteryAdmin(); abort_if($admin === null, 401); try { $agentProfileService->assertActorMayCreatePlayer($admin); } catch (\Illuminate\Validation\ValidationException $e) { return ApiMessage::errorResponse( $request, 'admin.player_create_capability_forbidden', ErrorCode::AdminForbidden->value, $e->errors(), 403, ); } $siteCode = (string) $request->validated('site_code'); if (! AdminSiteScope::siteCodeAllowed($admin, $siteCode)) { return ApiMessage::errorResponse($request, 'admin.player_create_site_forbidden', ErrorCode::AdminForbidden->value, null, 403); } $isNative = $request->filled('password'); $sitePlayerId = (string) ($request->validated('site_player_id') ?? ''); if ($isNative) { $sitePlayerId = $sitePlayerId !== '' ? $sitePlayerId : 'native:'.Str::lower(Str::ulid()); } if ($sitePlayerId === '') { return ApiMessage::errorResponse($request, 'admin.player_site_player_id_required', ErrorCode::ValidationFailed->value, null, 422); } $exists = Player::query() ->where('site_code', $siteCode) ->where('site_player_id', $sitePlayerId) ->exists(); if ($exists) { return ApiMessage::errorResponse($request, 'admin.player_already_registered', ErrorCode::ValidationFailed->value, null, 422); } if ($isNative) { $username = trim((string) $request->validated('username', '')); if ($username === '') { return ApiMessage::errorResponse($request, 'admin.player_native_username_required', ErrorCode::ValidationFailed->value, null, 422); } $usernameTaken = Player::query() ->where('site_code', $siteCode) ->where('username', $username) ->where('auth_source', PlayerAuthSource::LOTTERY_NATIVE) ->exists(); if ($usernameTaken) { return ApiMessage::errorResponse($request, 'admin.player_username_taken', ErrorCode::ValidationFailed->value, null, 422); } } $agentNodeId = $admin->isSuperAdmin() ? $this->resolveAgentNodeIdForSuperAdmin($request->validated('agent_node_id'), $siteCode) : $admin->primaryAgentNodeId(); if ($agentNodeId === null) { return ApiMessage::errorResponse( $request, 'admin.player_create_agent_required', ErrorCode::ValidationFailed->value, null, 422, ); } if (! $admin->isSuperAdmin()) { $agent = AdminAgentScope::primaryAgentNode($admin); if ($agent === null || (int) $agentNodeId !== (int) $agent->id) { return ApiMessage::errorResponse($request, 'admin.player_create_agent_forbidden', ErrorCode::AdminForbidden->value, null, 403); } } $agent = AgentNode::query()->findOrFail($agentNodeId); if ($request->has('rebate_rate')) { $rebateLimitValidator->assertPlayerRebateWithinAgent( $agent, (float) $request->input('rebate_rate', 0), (float) $request->input('extra_rebate_rate', 0), ); } $creditLimit = $request->has('credit_limit') ? (int) $request->input('credit_limit', 0) : ($isNative ? 0 : 0); $player = \Illuminate\Support\Facades\DB::transaction(function () use ( $agent, $agentProfileService, $playerCreditService, $request, $isNative, $siteCode, $agentNodeId, $sitePlayerId, $creditLimit, ): Player { $agentProfileService->assertMayIncreasePlayerCredit($agent, $creditLimit); $player = Player::query()->create([ 'site_code' => $siteCode, 'agent_node_id' => $agentNodeId, 'site_player_id' => $sitePlayerId, 'auth_source' => $isNative ? PlayerAuthSource::LOTTERY_NATIVE : PlayerAuthSource::MAIN_SITE_SSO, 'funding_mode' => $isNative ? PlayerFundingMode::CREDIT : PlayerFundingMode::WALLET, 'username' => $isNative ? trim((string) $request->validated('username')) : $request->validated('username'), 'password_hash' => $isNative ? Hash::make((string) $request->validated('password')) : null, 'nickname' => $request->validated('nickname'), 'default_currency' => $request->validated('default_currency', 'NPR'), 'status' => $request->validated('status', 0), ]); if ($request->has('credit_limit') || $isNative) { $playerCreditService->upsertAccount($player, [ 'credit_limit' => $creditLimit, ]); } $agentProfileService->refreshAllocatedCredit($agent); if ($request->has('rebate_rate')) { \Illuminate\Support\Facades\DB::table('player_rebate_profiles')->insert([ 'player_id' => $player->id, 'game_type' => '*', 'inherit_from_agent' => false, 'rebate_rate' => (float) $request->input('rebate_rate', 0), 'extra_rebate_rate' => (float) $request->input('extra_rebate_rate', 0), 'created_at' => now(), 'updated_at' => now(), ]); } return $player; }); return ApiResponse::success(PlayerApiPresenter::listItem($player))->setStatusCode(201); } private function resolveAgentNodeIdForSuperAdmin(mixed $requested, string $siteCode): ?int { if ($requested !== null && (int) $requested > 0) { return (int) $requested; } $siteId = \App\Models\AdminSite::query()->where('code', $siteCode)->value('id'); if ($siteId === null) { return null; } $rootId = \App\Models\AgentNode::query() ->where('admin_site_id', (int) $siteId) ->where('depth', 0) ->value('id'); return $rootId !== null ? (int) $rootId : null; } }