create(); $owner = Operator::factory()->create(); $subscription = app(GrantSubscription::class)( customer: $customer, grantedBy: $owner, plan: 'team', term: Subscription::TERM_MONTHLY, datacenter: 'fsn', priceCents: 0, note: 'Freund des Hauses', ); $order = Order::query()->where('customer_id', $customer->id)->sole(); expect($order->amount_cents)->toBe(0) ->and($order->stripe_event_id)->toBeNull() ->and($subscription->price_cents)->toBe(0) ->and($subscription->plan)->toBe('team') // The customer is owed the real machine, so the snapshot is the // catalogue's — only the price and the provenance were overridden. ->and($subscription->ram_mb)->toBeGreaterThan(0) ->and($subscription->isGranted())->toBeTrue() ->and($subscription->isFreeGrant())->toBeTrue() ->and($subscription->granted_by)->toBe($owner->id) ->and($subscription->grant_note)->toBe('Freund des Hauses') ->and($subscription->granted_until)->toBeNull() ->and($subscription->catalogue_price_cents)->toBeGreaterThan(0); // Same downstream pipeline as a paid order: a run was opened and dispatched. $run = ProvisioningRun::query()->where('subject_id', $order->id)->sole(); expect($run->pipeline)->toBe('customer'); Queue::assertPushed(AdvanceRunJob::class, fn ($job) => $job->runUuid === $run->uuid); }); it('records a discount as what it is: a price below the catalogue, not a free plan', function () { $customer = Customer::factory()->create(); $owner = Operator::factory()->create(); $subscription = app(GrantSubscription::class)( customer: $customer, grantedBy: $owner, plan: 'team', term: Subscription::TERM_MONTHLY, datacenter: 'fsn', priceCents: 5000, ); expect($subscription->price_cents)->toBe(5000) ->and($subscription->catalogue_price_cents)->toBeGreaterThan(5000) ->and($subscription->isFreeGrant())->toBeFalse() ->and($subscription->isGranted())->toBeTrue(); }); it('grants a quota bonus beyond the plan, baked into the frozen snapshot', function () { $customer = Customer::factory()->create(); $owner = Operator::factory()->create(); $plainTeam = app(PlanCatalogue::class)->currentVersion('team'); $subscription = app(GrantSubscription::class)( customer: $customer, grantedBy: $owner, plan: 'team', term: Subscription::TERM_MONTHLY, datacenter: 'fsn', priceCents: 0, bonus: ['quota_gb' => $plainTeam->quota_gb + 250], ); expect($subscription->quota_gb)->toBe($plainTeam->quota_gb + 250); }); it('refuses to charge more for a grant than the plan actually costs', function () { $customer = Customer::factory()->create(); $owner = Operator::factory()->create(); $price = app(PlanCatalogue::class)->currentVersion('team')->priceFor('monthly')->amount_cents; expect(fn () => app(GrantSubscription::class)( customer: $customer, grantedBy: $owner, plan: 'team', term: Subscription::TERM_MONTHLY, datacenter: 'fsn', priceCents: $price + 1, ))->toThrow(RuntimeException::class); }); it('remembers until when a dated grant runs, and leaves it unlimited otherwise', function () { $customer = Customer::factory()->create(); $owner = Operator::factory()->create(); $until = now()->addMonths(6); $subscription = app(GrantSubscription::class)( customer: $customer, grantedBy: $owner, plan: 'team', term: Subscription::TERM_MONTHLY, datacenter: 'fsn', priceCents: 0, until: $until, ); expect($subscription->granted_until->toDateString())->toBe($until->toDateString()); });