assertTrue(collect(Artisan::all())->has('demo:seed')); } public function test_free_plan_respects_branch_cap_and_skips_paid_modules(): void { $user = User::create([ 'public_id' => 'demo-free-public-id', 'name' => 'Ladill Demo (Free)', 'email' => 'demo-free@ladill.com', ]); $this->artisan('demo:seed', [ 'identity' => 'demo-free@ladill.com', '--plan' => 'free', ])->assertSuccessful(); $org = Organization::query()->where('owner_ref', $user->public_id)->first(); $this->assertNotNull($org); $this->assertSame('free', data_get($org->settings, 'plan')); $this->assertTrue((bool) data_get($org->settings, 'onboarded')); $this->assertSame(1, (int) data_get($org->settings, 'billed_branches')); $this->assertNotEmpty(data_get($org->settings, 'plan_expires_at')); $this->assertTrue(\Carbon\Carbon::parse(data_get($org->settings, 'plan_expires_at'))->isFuture()); $this->assertSame(1, Branch::query()->where('owner_ref', $user->public_id)->where('is_active', true)->count()); $this->assertSame(1, app(PlanService::class)->maxBranches($org)); $this->assertGreaterThanOrEqual(12, Patient::query()->where('owner_ref', $user->public_id)->count()); $this->assertGreaterThanOrEqual(20, Appointment::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame(0, InvestigationType::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame(0, InvestigationRequest::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame(0, Drug::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame(0, Prescription::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame(0, Bill::query()->where('owner_ref', $user->public_id)->count()); } public function test_pro_plan_seeds_multi_branch_and_paid_modules(): void { $user = User::create([ 'public_id' => 'demo-pro-public-id', 'name' => 'Ladill Demo (Pro)', 'email' => 'demo-pro@ladill.com', ]); $this->artisan('demo:seed', [ 'identity' => 'demo-pro@ladill.com', '--plan' => 'pro', ])->assertSuccessful(); $org = Organization::query()->where('owner_ref', $user->public_id)->firstOrFail(); $this->assertSame('pro', app(PlanService::class)->planKey($org)); $this->assertSame(3, Branch::query()->where('owner_ref', $user->public_id)->count()); $this->assertTrue(app(PlanService::class)->canUseProModules($org)); $this->assertGreaterThan(0, InvestigationType::query()->where('owner_ref', $user->public_id)->count()); $this->assertGreaterThan(0, InvestigationRequest::query()->where('owner_ref', $user->public_id)->count()); $this->assertGreaterThan(0, Drug::query()->where('owner_ref', $user->public_id)->count()); $this->assertGreaterThan(0, Prescription::query()->where('owner_ref', $user->public_id)->count()); $this->assertGreaterThan(0, Bill::query()->where('owner_ref', $user->public_id)->count()); } public function test_enterprise_seeds_assessments_and_more_branches(): void { $user = User::create([ 'public_id' => 'demo-enterprise-public-id', 'name' => 'Accra Healthcare Group', 'email' => 'demo-enterprise@ladill.com', ]); $this->artisan('demo:seed', [ 'identity' => $user->public_id, '--plan' => 'enterprise', ])->assertSuccessful(); $org = Organization::query()->where('owner_ref', $user->public_id)->firstOrFail(); $this->assertSame('enterprise', app(PlanService::class)->planKey($org)); $this->assertSame(6, Branch::query()->where('owner_ref', $user->public_id)->count()); $this->assertGreaterThan(0, Assessment::query()->where('owner_ref', $user->public_id)->count()); $this->assertGreaterThan(0, Bill::query()->where('owner_ref', $user->public_id)->count()); } public function test_idempotent_reseed_without_reset_does_not_duplicate(): void { $user = User::create([ 'public_id' => 'demo-idempotent-id', 'name' => 'Idempotent Demo', 'email' => 'demo-idempotent@ladill.com', ]); $this->artisan('demo:seed', [ 'identity' => 'demo-idempotent@ladill.com', '--plan' => 'free', ])->assertSuccessful(); $patients = Patient::query()->where('owner_ref', $user->public_id)->count(); $appointments = Appointment::query()->where('owner_ref', $user->public_id)->count(); $orgs = Organization::query()->where('owner_ref', $user->public_id)->count(); $this->artisan('demo:seed', [ 'identity' => 'demo-idempotent@ladill.com', '--plan' => 'free', ])->assertSuccessful(); $this->assertSame($patients, Patient::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame($appointments, Appointment::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame($orgs, Organization::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame(1, Branch::query()->where('owner_ref', $user->public_id)->count()); } public function test_reset_wipes_only_tenant_scoped_data_then_reseeds(): void { $keep = User::create([ 'public_id' => 'other-owner', 'name' => 'Other', 'email' => 'other@ladill.com', ]); Organization::create([ 'owner_ref' => $keep->public_id, 'name' => 'Keep Me', 'slug' => 'keep-me', 'settings' => ['onboarded' => true, 'plan' => 'free'], ]); Branch::create([ 'owner_ref' => $keep->public_id, 'organization_id' => Organization::query()->where('owner_ref', $keep->public_id)->value('id'), 'name' => 'Keep Branch', 'is_active' => true, ]); $user = User::create([ 'public_id' => 'demo-reset-id', 'name' => 'Reset Demo', 'email' => 'demo-reset@ladill.com', ]); $this->artisan('demo:seed', [ 'identity' => 'demo-reset@ladill.com', '--plan' => 'pro', ])->assertSuccessful(); $patientCount = Patient::query()->where('owner_ref', $user->public_id)->count(); $this->assertGreaterThan(0, $patientCount); $this->assertGreaterThan(0, Bill::query()->where('owner_ref', $user->public_id)->count()); $this->artisan('demo:seed', [ 'identity' => 'demo-reset@ladill.com', '--plan' => 'free', '--reset' => true, ])->assertSuccessful(); $this->assertSame(1, Branch::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame(0, Bill::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame(0, Drug::query()->where('owner_ref', $user->public_id)->count()); $this->assertSame('free', data_get( Organization::query()->where('owner_ref', $user->public_id)->value('settings'), 'plan' )); // Other tenant untouched. $this->assertSame(1, Organization::query()->where('owner_ref', $keep->public_id)->count()); $this->assertSame(1, Branch::query()->where('owner_ref', $keep->public_id)->count()); } public function test_creates_local_mirror_when_public_id_and_email_provided(): void { $this->assertDatabaseMissing('users', ['email' => 'new-demo@ladill.com']); $this->artisan('demo:seed', [ '--public-id' => 'brand-new-public-id', '--email' => 'new-demo@ladill.com', '--name' => 'New Demo', '--plan' => 'free', ])->assertSuccessful(); $user = User::query()->where('email', 'new-demo@ladill.com')->first(); $this->assertNotNull($user); $this->assertSame('brand-new-public-id', $user->public_id); $this->assertSame(1, Organization::query()->where('owner_ref', $user->public_id)->count()); } public function test_fails_when_mirror_missing_and_insufficient_identity(): void { $this->artisan('demo:seed', [ 'identity' => 'missing@ladill.com', '--plan' => 'free', ])->assertFailed(); } public function test_volumes_helper_marks_free_without_paid_modules(): void { $volumes = app(DemoTenantSeeder::class)->volumes('free'); $this->assertFalse($volumes['paid_modules']); $this->assertSame(1, $volumes['branches']); $this->assertSame(0, $volumes['assessments']); $pro = app(DemoTenantSeeder::class)->volumes('pro'); $this->assertTrue($pro['paid_modules']); $this->assertSame(3, $pro['branches']); } }