create(['role' => UserRole::CourseDesigner]); $current = Subscription::query()->create([ 'organization_id' => $designer->organization_id, 'plan_key' => 'enterprise', 'status' => 'active', 'starts_at' => now()->subDay(), 'seat_limit' => 250, 'storage_quota_bytes' => 1000, 'storage_used_bytes' => 400, 'ai_credit_quota' => 500, 'ai_credits_used' => 125, 'enabled_features' => ['taxonomy', 'exports'], ]); $otherDesigner = User::factory()->create(['role' => UserRole::CourseDesigner]); Subscription::query()->create([ 'organization_id' => $otherDesigner->organization_id, 'plan_key' => 'private-plan', 'status' => 'active', 'starts_at' => now()->subDay(), ]); Sanctum::actingAs($designer); $this->getJson('/api/v1/subscription?organization_id='.$otherDesigner->organization_id) ->assertOk() ->assertJsonPath('data.id', $current->getKey()) ->assertJsonPath('data.seatLimit', 250) ->assertJsonPath('data.seatUsed', 1) ->assertJsonPath('data.storageUsedBytes', 400) ->assertJsonPath('data.aiCreditsUsed', 125) ->assertJsonPath('data.enabledFeatures.0', 'taxonomy') ->assertJsonMissing(['planKey' => 'private-plan']); } public function test_manager_cannot_view_subscription_configuration(): void { $manager = User::factory()->create(['role' => UserRole::Manager]); Sanctum::actingAs($manager); $this->getJson('/api/v1/subscription')->assertForbidden(); } public function test_super_admin_can_list_create_and_update_platform_subscriptions_with_audit(): void { $organization = Organization::factory()->create(['name' => 'Acme Platform']); Sanctum::actingAs(User::factory()->create(['organization_id' => null, 'role' => UserRole::SuperAdmin])); $id = $this->postJson('/api/v1/platform/subscriptions', [ 'organizationId' => $organization->getKey(), 'planKey' => 'enterprise', 'status' => 'active', 'startsAt' => now()->subDay()->toISOString(), 'expiresAt' => now()->addMonth()->toISOString(), 'seatLimit' => 100, 'storageQuotaBytes' => 100000, 'aiCreditQuota' => 2000, 'enabledFeatures' => ['exports', 'taxonomy'], ])->assertCreated()->assertJsonPath('data.organization.name', 'Acme Platform')->json('data.id'); $this->getJson('/api/v1/platform/subscriptions?search=acme&status=active&plan=enterprise&perPage=10') ->assertOk()->assertJsonPath('meta.total', 1)->assertJsonPath('data.0.id', $id)->assertJsonPath('data.0.seatLimit', 100); $this->patchJson('/api/v1/platform/subscriptions/'.$id, ['planKey' => 'enterprise-plus', 'seatLimit' => 150, 'expiresAt' => null, 'status' => 'suspended']) ->assertOk()->assertJsonPath('data.planKey', 'enterprise-plus')->assertJsonPath('data.status', 'suspended')->assertJsonPath('data.seatLimit', 150); $this->assertDatabaseHas('subscriptions', ['id' => $id, 'expires_at' => null]); $this->assertDatabaseHas('audit_logs', ['organization_id' => $organization->getKey(), 'action' => 'subscription.created', 'entity_id' => $id]); $this->assertDatabaseHas('audit_logs', ['organization_id' => $organization->getKey(), 'action' => 'subscription.updated', 'entity_id' => $id]); } public function test_tenant_roles_and_unsupported_deployments_cannot_manage_platform_subscriptions(): void { Sanctum::actingAs(User::factory()->create(['role' => UserRole::CourseDesigner])); $this->getJson('/api/v1/platform/subscriptions')->assertForbidden(); config()->set('deployment.mode', 'on_premise'); $this->app->forgetInstance(DeploymentCapabilities::class); Sanctum::actingAs(User::factory()->create(['organization_id' => null, 'role' => UserRole::SuperAdmin])); $this->getJson('/api/v1/platform/subscriptions')->assertNotFound(); } }