'CluPilot Cloud e.U.', 'address' => 'Dreherstraße 66/1/8', 'postcode' => '1110', 'city' => 'Wien', 'vat_id' => 'ATU00000000', ]); }); it('skips a fully granted subscription: no invoice, no number consumed', function () { Queue::fake(); $customer = Customer::factory()->create(); $owner = Operator::factory()->create(); app(GrantSubscription::class)( customer: $customer, grantedBy: $owner, plan: 'team', term: Subscription::TERM_MONTHLY, datacenter: 'fsn', priceCents: 0, ); $order = Order::query()->where('customer_id', $customer->id)->sole(); expect(fn () => app(IssueInvoice::class)->forOrders($customer, collect([$order]))) ->toThrow(RuntimeException::class); expect(Invoice::query()->count())->toBe(0) ->and(InvoiceSeries::query()->where('kind', 'invoice')->value('next_number'))->toBe(1); }); it('invoices a discounted grant normally, at what the customer actually pays', function () { Queue::fake(); $customer = Customer::factory()->create(); $owner = Operator::factory()->create(); app(GrantSubscription::class)( customer: $customer, grantedBy: $owner, plan: 'team', term: Subscription::TERM_MONTHLY, datacenter: 'fsn', priceCents: 5000, ); $order = Order::query()->where('customer_id', $customer->id)->sole(); $invoice = app(IssueInvoice::class)->forOrders($customer, collect([$order])); expect($invoice->net_cents)->toBe(5000) ->and($invoice->number)->toStartWith('RE-'); }); it('skips a granted, free module the same way', function () { $order = Order::factory()->create(['plan' => 'team', 'datacenter' => 'fsn', 'status' => 'paid']); $subscription = app(OpenSubscription::class)($order); $owner = Operator::factory()->create(); $customer = $subscription->customer; app(GrantAddon::class)($subscription, $owner, 'priority_support', 0); $addonOrder = Order::query()->where('type', 'addon')->sole(); expect(fn () => app(IssueInvoice::class)->forOrders($customer, collect([$addonOrder]))) ->toThrow(RuntimeException::class); expect(Invoice::query()->count())->toBe(0); }); it('does not mistake an ordinary fully-discounted Stripe checkout for a grant', function () { // The exact case OpenSubscription's own docblock warns about: a real // Stripe checkout can also land at amount_cents = 0 (a 100% coupon). That // subscription was never granted (granted_at stays null) and is still an // owed invoice — isFreeGrant() must key off provenance, not off the // amount alone. $order = Order::factory()->create([ 'plan' => 'team', 'datacenter' => 'fsn', 'amount_cents' => 0, 'currency' => 'EUR', 'status' => 'paid', 'stripe_event_id' => 'evt_full_coupon', ]); $subscription = app(OpenSubscription::class)($order, Subscription::TERM_MONTHLY, ['price_cents' => 0]); expect($subscription->isGranted())->toBeFalse(); $invoice = app(IssueInvoice::class)->forOrders($order->customer, collect([$order])); expect($invoice->net_cents)->toBe(0) ->and($invoice->number)->toStartWith('RE-'); });