CluPilotCloud/tests/Feature/Billing/NewPlanLadderTest.php

80 lines
3.6 KiB
PHP

<?php
use App\Models\PlanFamily;
use App\Models\Subscription;
use App\Services\Billing\PlanCatalogue;
/**
* Die Leiter, wie sie verkauft wird.
*
* Zugeschnitten auf die Maschine, die dasteht: 388 GB vergebbar, ~58 GB RAM für
* Gäste. Neun Startkunden à 40 GB Platte lasten Speicher und RAM gleichzeitig
* aus — die alte Leiter band bei drei Kunden und ließ sechs RAM-Plätze
* verfallen.
*/
it('verkauft drei Pakete', function () {
expect(array_keys(app(PlanCatalogue::class)->sellable()))->toBe(['start', 'team', 'business']);
});
it('verkauft sie zu den beschlossenen Zahlen', function () {
$sellable = app(PlanCatalogue::class)->sellable();
expect($sellable['start']['quota_gb'])->toBe(30)
->and($sellable['start']['disk_gb'])->toBe(40)
->and($sellable['start']['ram_mb'])->toBe(6144)
->and($sellable['start']['seats'])->toBe(10)
->and($sellable['start']['price_cents'])->toBe(3900)
->and($sellable['start']['yearly_price_cents'])->toBe(39000)
->and($sellable['team']['quota_gb'])->toBe(85)
->and($sellable['team']['disk_gb'])->toBe(100)
->and($sellable['team']['price_cents'])->toBe(7900)
->and($sellable['business']['quota_gb'])->toBe(175)
->and($sellable['business']['disk_gb'])->toBe(200)
->and($sellable['business']['price_cents'])->toBe(13900);
});
it('lässt neun Startkunden auf 388 GB', function () {
$start = app(PlanCatalogue::class)->sellable()['start'];
expect(intdiv(388, $start['disk_gb']))->toBe(9);
});
it('nimmt das interne Paket und Enterprise aus dem Laden', function () {
expect(PlanFamily::query()->where('key', 'test')->value('internal'))->toBeTruthy()
->and(PlanFamily::query()->where('key', 'test')->value('name'))->toBe('Intern')
->and(PlanFamily::query()->where('key', 'enterprise')->value('sales_enabled'))->toBeFalsy();
});
it('schaltet kein zweites Mal um, wenn sie noch einmal gefahren wird', function () {
// Ein zweiter Deploy, ein wiederholtes `migrate` auf einem Bestand, der die
// Umschaltung schon hinter sich hat: die Migration darf dann keine dritte
// Fassung nachschieben und die laufende nicht beenden. Erkannt wird das an
// dem, was die laufende Fassung TRÄGT, nicht an ihrer Nummer.
$before = App\Models\PlanVersion::query()->count();
(require database_path('migrations/2026_08_01_000004_switch_to_new_plan_ladder.php'))->up();
expect(App\Models\PlanVersion::query()->count())->toBe($before)
->and(app(PlanCatalogue::class)->sellable()['team']['quota_gb'])->toBe(85)
->and(app(PlanCatalogue::class)->currentVersion('team')->available_until)->toBeNull();
});
it('lässt einen laufenden Vertrag auf seinen eigenen Zahlen', function () {
// Ein Vertrag, wie ihn OpenSubscription vor der Umschaltung geschrieben
// hat, mit der Maschine dazu.
$subscription = Subscription::factory()->create([
'plan' => 'team', 'quota_gb' => 500, 'disk_gb' => 540, 'price_cents' => 17900,
]);
$instance = App\Models\Instance::factory()->create([
'customer_id' => $subscription->customer_id, 'status' => 'active',
'quota_gb' => 500, 'disk_gb' => 540,
]);
// Der Katalog sagt heute etwas anderes — und keine Leseseite schreibt es
// dem Vertrag um. Die mittlere Zusicherung ist die eigentliche: sie geht
// durch denselben Weg, über den eine Bereitstellung das Kontingent holt.
expect(app(PlanCatalogue::class)->sellable()['team']['quota_gb'])->toBe(85)
->and(App\Services\Billing\StorageAllowance::for($instance)->planGb)->toBe(500)
->and($subscription->fresh()->price_cents)->toBe(17900);
});