Ein Block bringt seinen eigenen Kopfraum mit
Ein Block gibt 20 GB und belegt 22. Ohne das haette ein Start mit drei Bloecken 90 GB auf 100 GB Platte gehabt — zehn Gigabyte Kopfraum, wo die Regel bei dieser Plattengroesse zwoelf verlangt, und der gestapelte Tarif waere genau der Fall geworden, den die Regel verhindern soll. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>feat/neue-pakete
parent
af05ed6694
commit
3ed80a05e0
|
|
@ -111,8 +111,19 @@ class ResizeVirtualMachine extends CustomerStep
|
|||
|
||||
$allowance = StorageAllowance::for($instance);
|
||||
|
||||
// Kontingent + Blöcke + Kopfraum des Pakets + Kopfraum der Blöcke.
|
||||
//
|
||||
// Der letzte Summand ist der neue: ein Block gibt dem Kunden 20 GB und
|
||||
// belegt 22, damit die Regel max(10 GB, 12 %) auch für ein gestapeltes
|
||||
// Paket gilt. Ohne ihn hätte ein Start mit drei Blöcken 90 GB auf 100 GB
|
||||
// Platte — zehn Gigabyte Kopfraum, wo die Regel zwölf verlangt.
|
||||
//
|
||||
// Beide Kopfräume werden gelesen, nicht abgeleitet: der des Pakets aus
|
||||
// dem eingefrorenen Vertrag, der der Blöcke aus den Buchungen.
|
||||
$target = $allowance->totalGb() > 0
|
||||
? $allowance->totalGb() + max(0, $planDisk - $planQuota)
|
||||
? $allowance->totalGb()
|
||||
+ max(0, $planDisk - $planQuota)
|
||||
+ max(0, $allowance->packDiskGb() - $allowance->packGb())
|
||||
: $planDisk;
|
||||
$actual = (int) $instance->disk_gb;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Order;
|
||||
use App\Models\SubscriptionAddon;
|
||||
use App\Services\Billing\AddonCatalogue;
|
||||
use App\Services\Billing\StorageAllowance;
|
||||
use App\Provisioning\Steps\Customer\ResizeVirtualMachine;
|
||||
|
||||
/**
|
||||
* Was ein Block auf der Platte bedeutet.
|
||||
*
|
||||
* Der Kopfraum wächst mit der Instanz (max(10 GB, 12 %)), sonst gilt die Regel
|
||||
* nur für frisch gekaufte Pakete und nicht für gestapelte. Eine volle Platte
|
||||
* legt nicht den Upload still, sondern die Instanz.
|
||||
*/
|
||||
it('rechnet Kopfraum des Pakets und der Blöcke zusammen', function () {
|
||||
// Start: 30 GB Kontingent auf 40 GB Platte. Drei Blöcke zu 20 GB nutzbar
|
||||
// und 22 GB belegt.
|
||||
$allowance = new StorageAllowance(planGb: 30, packs: 3, bookedGb: 60, bookedDiskGb: 66, packSizeGb: 20);
|
||||
|
||||
$planDisk = 40;
|
||||
$planQuota = 30;
|
||||
|
||||
$target = $allowance->totalGb()
|
||||
+ max(0, $planDisk - $planQuota)
|
||||
+ ($allowance->packDiskGb() - $allowance->packGb());
|
||||
|
||||
expect($target)->toBe(106);
|
||||
});
|
||||
|
||||
// Den Schritt selbst fahren: reservedRun() (aus CustomerStepsTest.php) baut ein
|
||||
// 'start'-Paket (100 GB Kontingent, 120 GB Platte — 20 GB Kopfraum des Pakets).
|
||||
// Drei Blöcke zu 20 GB nutzbar / 22 GB belegt kommen direkt als
|
||||
// SubscriptionAddon-Zeile dazu, statt über BookAddon zu buchen — das würde
|
||||
// einen Lieferlauf anstoßen und Stripe befragen, was hier nichts zur Sache tut;
|
||||
// gefragt ist nur, was ResizeVirtualMachine aus einer bereits gebuchten Zeile
|
||||
// macht.
|
||||
//
|
||||
// Ziel: 100 (Kontingent) + 60 (drei Blöcke à 20) + 20 (Kopfraum des Pakets,
|
||||
// 120-100) + 6 (Kopfraum der Blöcke, 66-60 belegt) = 186 GB.
|
||||
it('vergrößert die Platte um Paket- und Block-Kopfraum, und nur einmal', function () {
|
||||
$s = fakeServices();
|
||||
['run' => $run, 'instance' => $instance, 'order' => $order] = reservedRun();
|
||||
|
||||
SubscriptionAddon::create([
|
||||
'subscription_id' => $order->subscription->id,
|
||||
'addon_key' => AddonCatalogue::STORAGE,
|
||||
'price_cents' => 1000,
|
||||
'currency' => 'EUR',
|
||||
'quantity' => 3,
|
||||
'booked_at' => now(),
|
||||
'pack_gb' => 20,
|
||||
'pack_disk_gb' => 22,
|
||||
]);
|
||||
|
||||
expect(app(ResizeVirtualMachine::class)->execute($run)->type)->toBe('advance')
|
||||
->and($s['pve']->resizeCalls)->toContain('101:scsi0:186G')
|
||||
->and($instance->fresh()->disk_gb)->toBe(186);
|
||||
|
||||
// Wiederholungslauf: das Ziel ist absolut, nicht '+…', also darf ein
|
||||
// zweiter Durchlauf nicht noch einmal vergrößern.
|
||||
$s['pve']->resizeCalls = [];
|
||||
expect(app(ResizeVirtualMachine::class)->execute($run->fresh())->type)->toBe('advance')
|
||||
->and($s['pve']->resizeCalls)->toBe([])
|
||||
->and($instance->fresh()->disk_gb)->toBe(186);
|
||||
});
|
||||
Loading…
Reference in New Issue