artisan('lottery:agent-roles-sync')->assertExitCode(0); }); test('agent profile switches strip create player and child manage from effective permissions', function (): void { $siteId = (int) DB::table('admin_sites')->where('is_default', true)->value('id'); $rootId = (int) DB::table('agent_nodes')->where('admin_site_id', $siteId)->where('depth', 0)->value('id'); $child = AgentNode::query()->create([ 'admin_site_id' => $siteId, 'parent_id' => $rootId, 'path' => '/', 'depth' => 1, 'code' => 'cap-child', 'name' => 'Cap Child', 'status' => 1, ]); $child->path = "/{$rootId}/{$child->id}/"; $child->save(); AgentProfile::query()->create([ 'agent_node_id' => $child->id, 'total_share_rate' => 10, 'credit_limit' => 0, 'allocated_credit' => 0, 'used_credit' => 0, 'rebate_limit' => 0, 'default_player_rebate' => 0, 'can_grant_extra_rebate' => false, 'can_create_child_agent' => false, 'can_create_player' => false, ]); $admin = AdminUser::query()->create([ 'username' => 'cap_child_agent', 'name' => 'Cap Child Agent', 'email' => null, 'password' => Hash::make('secret-strong'), 'status' => 0, ]); DB::table('admin_user_agents')->insert([ 'admin_user_id' => $admin->id, 'agent_node_id' => $child->id, 'is_primary' => true, 'granted_at' => now(), ]); $admin->syncPrimaryPlatformAgentRole($child->id); $fresh = $admin->fresh(); $profile = AdminAuthProfile::fromAdmin($fresh); $perms = $profile['permissions']; expect($perms)->toContain('prd.agent.view') ->not->toContain('prd.agent.manage') ->not->toContain('prd.users.manage'); expect($fresh->hasPermissionCode('agent.node.manage'))->toBeFalse(); expect($fresh->hasPermissionCode('service.players.manage'))->toBeFalse(); expect($fresh->hasPermissionCode('settlement.agent.manage'))->toBeTrue(); expect($fresh->adminPermissionSlugs())->toContain('prd.settlement.agent.manage'); expect($profile['agent']['can_create_child_agent'])->toBeFalse(); expect($profile['agent']['can_create_player'])->toBeFalse(); }); test('agent profile switches on grant create capabilities even when platform agent role omits manage', function (): void { $siteId = (int) DB::table('admin_sites')->where('is_default', true)->value('id'); $rootId = (int) DB::table('agent_nodes')->where('admin_site_id', $siteId)->where('depth', 0)->value('id'); $child = AgentNode::query()->create([ 'admin_site_id' => $siteId, 'parent_id' => $rootId, 'path' => '/', 'depth' => 1, 'code' => 'cap-child-on', 'name' => 'Cap Child On', 'status' => 1, ]); $child->path = "/{$rootId}/{$child->id}/"; $child->save(); AgentProfile::query()->create([ 'agent_node_id' => $child->id, 'total_share_rate' => 10, 'credit_limit' => 0, 'allocated_credit' => 0, 'used_credit' => 0, 'rebate_limit' => 0, 'default_player_rebate' => 0, 'can_grant_extra_rebate' => false, 'can_create_child_agent' => true, 'can_create_player' => true, ]); $admin = AdminUser::query()->create([ 'username' => 'cap_child_on_agent', 'name' => 'Cap Child On Agent', 'email' => null, 'password' => Hash::make('secret-strong'), 'status' => 0, ]); DB::table('admin_user_agents')->insert([ 'admin_user_id' => $admin->id, 'agent_node_id' => $child->id, 'is_primary' => true, 'granted_at' => now(), ]); $admin->syncPrimaryPlatformAgentRole($child->id); $fresh = $admin->fresh(); expect($fresh->hasPermissionCode('agent.node.manage'))->toBeTrue(); expect($fresh->hasPermissionCode('service.players.manage'))->toBeTrue(); expect($fresh->adminPermissionSlugs())->toContain('prd.agent.manage') ->and($fresh->adminPermissionSlugs())->toContain('prd.users.manage') ->and($fresh->adminPermissionSlugs())->toContain('prd.settlement.agent.manage'); expect($fresh->hasPermissionCode('settlement.agent.manage'))->toBeTrue(); }); test('line root bound agent receives settlement manage at login', function (): void { $siteId = (int) DB::table('admin_sites')->where('is_default', true)->value('id'); $rootId = (int) DB::table('agent_nodes')->where('admin_site_id', $siteId)->where('depth', 0)->value('id'); $admin = AdminUser::query()->create([ 'username' => 'settle_root_agent', 'name' => 'Settle Root Agent', 'email' => null, 'password' => Hash::make('secret-strong'), 'status' => 0, ]); DB::table('admin_user_agents')->insert([ 'admin_user_id' => $admin->id, 'agent_node_id' => $rootId, 'is_primary' => true, 'granted_at' => now(), ]); $admin->syncPrimaryPlatformAgentRole($rootId); $fresh = $admin->fresh(); expect($fresh->hasPermissionCode('settlement.agent.manage'))->toBeTrue(); expect($fresh->adminPermissionSlugs())->toContain('prd.settlement.agent.manage'); }); test('agent with downline children receives settlement manage at login', function (): void { $siteId = (int) DB::table('admin_sites')->where('is_default', true)->value('id'); $rootId = (int) DB::table('agent_nodes')->where('admin_site_id', $siteId)->where('depth', 0)->value('id'); $parent = AgentNode::query()->create([ 'admin_site_id' => $siteId, 'parent_id' => $rootId, 'path' => '/', 'depth' => 1, 'code' => 'settle-parent', 'name' => 'Settle Parent', 'status' => 1, ]); $parent->path = "/{$rootId}/{$parent->id}/"; $parent->save(); $child = AgentNode::query()->create([ 'admin_site_id' => $siteId, 'parent_id' => $parent->id, 'path' => "/{$rootId}/{$parent->id}/", 'depth' => 2, 'code' => 'settle-child', 'name' => 'Settle Child', 'status' => 1, ]); $child->path = "/{$rootId}/{$parent->id}/{$child->id}/"; $child->save(); AgentProfile::query()->create([ 'agent_node_id' => $parent->id, 'total_share_rate' => 20, 'credit_limit' => 0, 'allocated_credit' => 0, 'used_credit' => 0, 'rebate_limit' => 0, 'default_player_rebate' => 0, 'can_grant_extra_rebate' => false, 'can_create_child_agent' => false, 'can_create_player' => false, ]); $admin = AdminUser::query()->create([ 'username' => 'settle_parent_agent', 'name' => 'Settle Parent Agent', 'email' => null, 'password' => Hash::make('secret-strong'), 'status' => 0, ]); DB::table('admin_user_agents')->insert([ 'admin_user_id' => $admin->id, 'agent_node_id' => $parent->id, 'is_primary' => true, 'granted_at' => now(), ]); $admin->syncPrimaryPlatformAgentRole($parent->id); $fresh = $admin->fresh(); expect($fresh->hasPermissionCode('settlement.agent.manage'))->toBeTrue(); expect($fresh->adminPermissionSlugs())->toContain('prd.settlement.agent.manage'); });