insertGetId([ 'code' => $code, 'name' => $code, 'is_default' => false, 'created_at' => now(), 'updated_at' => now(), ]); $rootId = (int) DB::table('agent_nodes')->insertGetId([ 'admin_site_id' => $siteId, 'parent_id' => null, 'depth' => 0, 'path' => '/'.$code, 'code' => $code, 'name' => 'Root', 'status' => 1, 'created_at' => now(), 'updated_at' => now(), ]); AgentProfile::query()->create([ 'agent_node_id' => $rootId, 'total_share_rate' => 60, 'credit_limit' => $creditLimit, 'allocated_credit' => 0, 'used_credit' => 0, 'rebate_limit' => 0.01, 'default_player_rebate' => 0.005, 'settlement_cycle' => 'weekly', ]); return AgentNode::query()->findOrFail($rootId); } test('player credit account syncs agent allocated credit', function (): void { $root = createAgentLineForAllocation('line-alloc', 10000); $service = app(AgentProfileService::class); $playerId = (int) DB::table('players')->insertGetId([ 'site_code' => 'line-alloc', 'agent_node_id' => $root->id, 'site_player_id' => 'p-alloc-1', 'username' => 'alloc1', 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, 'created_at' => now(), 'updated_at' => now(), ]); DB::table('player_credit_accounts')->insert([ 'player_id' => $playerId, 'credit_limit' => 2000, 'used_credit' => 0, 'frozen_credit' => 0, 'created_at' => now(), 'updated_at' => now(), ]); $service->refreshAllocatedCredit($root); $profile = AgentProfile::query()->where('agent_node_id', $root->id)->first(); expect((int) $profile->allocated_credit)->toBe(2000); expect($service->present($profile)['available_credit'])->toBe(8000); }); test('player credit allocation exceeds available throws', function (): void { $root = createAgentLineForAllocation('line-over', 5000); $service = app(AgentProfileService::class); expect(fn () => $service->assertMayIncreasePlayerCredit($root, 6000)) ->toThrow(\Illuminate\Validation\ValidationException::class); }); test('win loss does not change agent allocated credit', function (): void { $root = createAgentLineForAllocation('line-hold', 10000); $playerId = (int) DB::table('players')->insertGetId([ 'site_code' => 'line-hold', 'agent_node_id' => $root->id, 'site_player_id' => 'p-hold-1', 'username' => 'hold1', 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, 'created_at' => now(), 'updated_at' => now(), ]); DB::table('player_credit_accounts')->insert([ 'player_id' => $playerId, 'credit_limit' => 2000, 'used_credit' => 200, 'frozen_credit' => 0, 'created_at' => now(), 'updated_at' => now(), ]); app(AgentProfileService::class)->refreshAllocatedCredit($root); $profile = AgentProfile::query()->where('agent_node_id', $root->id)->first(); expect((int) $profile->allocated_credit)->toBe(2000); }); test('raising player credit limit succeeds when agent allocated credit includes other subordinates', function (): void { $root = createAgentLineForAllocation('line-player-raise', 10000); $service = app(AgentProfileService::class); $playerId = (int) DB::table('players')->insertGetId([ 'site_code' => 'line-player-raise', 'agent_node_id' => $root->id, 'site_player_id' => 'p-other', 'username' => 'other', 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, 'created_at' => now(), 'updated_at' => now(), ]); DB::table('player_credit_accounts')->insert([ 'player_id' => $playerId, 'credit_limit' => 3000, 'used_credit' => 0, 'frozen_credit' => 0, 'created_at' => now(), 'updated_at' => now(), ]); $service->refreshAllocatedCredit($root); $newPlayerId = (int) DB::table('players')->insertGetId([ 'site_code' => 'line-player-raise', 'agent_node_id' => $root->id, 'site_player_id' => 'p-raise-1', 'username' => 'raise1', 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, 'created_at' => now(), 'updated_at' => now(), ]); DB::table('player_credit_accounts')->insert([ 'player_id' => $newPlayerId, 'credit_limit' => 0, 'used_credit' => 0, 'frozen_credit' => 0, 'created_at' => now(), 'updated_at' => now(), ]); $service->adjustPlayerCreditAllocation($root, 0, 2000); DB::table('player_credit_accounts')->where('player_id', $newPlayerId)->update(['credit_limit' => 2000]); $service->refreshAllocatedCredit($root); $profile = AgentProfile::query()->where('agent_node_id', $root->id)->first(); expect((int) $profile->allocated_credit)->toBe(5000); });