create(['plan' => 'team', 'datacenter' => 'fsn', 'status' => 'paid']); return app(OpenSubscription::class)($order); } it('books a module at zero cost, with provenance on the row', function () { $subscription = subscriptionForGrant(); $owner = Operator::factory()->create(); $addon = app(GrantAddon::class)( subscription: $subscription, grantedBy: $owner, addonKey: 'priority_support', priceCents: 0, note: 'Entschuldigung für die Störung', ); $catalogue = app(AddonCatalogue::class)->priceCents('priority_support'); expect($addon->price_cents)->toBe(0) ->and($addon->isGranted())->toBeTrue() ->and($addon->granted_by)->toBe($owner->id) ->and($addon->grant_note)->toBe('Entschuldigung für die Störung') ->and($addon->catalogue_price_cents)->toBe($catalogue) ->and($addon->order->stripe_event_id)->toBeNull() ->and($addon->order->amount_cents)->toBe(0); }); it('books a discounted module below the catalogue price', function () { $subscription = subscriptionForGrant(); $owner = Operator::factory()->create(); $catalogue = app(AddonCatalogue::class)->priceCents('collabora_pro'); $addon = app(GrantAddon::class)( subscription: $subscription, grantedBy: $owner, addonKey: 'collabora_pro', priceCents: $catalogue - 500, ); expect($addon->price_cents)->toBe($catalogue - 500) ->and($addon->isGranted())->toBeTrue(); }); it('refuses to charge more for a granted module than it actually costs', function () { $subscription = subscriptionForGrant(); $owner = Operator::factory()->create(); $catalogue = app(AddonCatalogue::class)->priceCents('extra_backups'); expect(fn () => app(GrantAddon::class)( subscription: $subscription, grantedBy: $owner, addonKey: 'extra_backups', priceCents: $catalogue + 1, ))->toThrow(RuntimeException::class); });