diff --git a/resources/views/livewire/billing.blade.php b/resources/views/livewire/billing.blade.php
index 129bc45..0d5e63e 100644
--- a/resources/views/livewire/billing.blade.php
+++ b/resources/views/livewire/billing.blade.php
@@ -72,7 +72,9 @@
@php
$net = $pending->sum('amount_cents');
$gross = $pending->sum(fn ($o) => $o->grossCents());
- $recurringNet = $pending->filter->isRecurring()->sum('amount_cents');
+ // Summed from the same per-order rounding the total uses: rounding
+ // after aggregating would let the two figures disagree by a cent.
+ $recurringGross = $pending->filter->isRecurring()->sum(fn ($o) => $o->grossCents());
@endphp
@@ -87,11 +89,11 @@
{{ __('billing.cart.total_gross') }}
{{ $eur($gross) }}
- @if ($recurringNet > 0)
+ @if ($recurringGross > 0)
{{-- The number that actually matters every month, kept apart
from a one-off traffic top-up in the same cart. --}}
- {{ __('billing.cart.recurring_note', ['amount' => $eur((int) round($recurringNet * (1 + \App\Models\Order::taxRate())))]) }}
+ {{ __('billing.cart.recurring_note', ['amount' => $eur($recurringGross)]) }}
@endif
diff --git a/tests/Feature/CartTest.php b/tests/Feature/CartTest.php
index c5471e6..9274a14 100644
--- a/tests/Feature/CartTest.php
+++ b/tests/Feature/CartTest.php
@@ -132,3 +132,20 @@ it('separates what recurs from a one-off top-up', function () {
Livewire\Livewire::actingAs($user)->test(Billing::class)->assertSee($expected);
});
+
+it('keeps the recurring figure consistent with the total to the cent', function () {
+ [$customer, $user] = cartCustomer();
+ config()->set('provisioning.tax.rate_percent', 20);
+
+ // Cent-level prices: rounding after aggregating instead of per order makes
+ // the two figures disagree, and a customer who spots that stops trusting
+ // every other number on the page.
+ Order::factory()->for($customer)->create(['type' => 'storage', 'amount_cents' => 3, 'status' => 'pending']);
+ Order::factory()->for($customer)->create(['type' => 'storage', 'amount_cents' => 3, 'status' => 'pending']);
+
+ $expected = Illuminate\Support\Number::currency(0.08, in: 'EUR', locale: 'de');
+
+ Livewire\Livewire::actingAs($user)->test(Billing::class)
+ ->assertSee($expected) // total gross
+ ->assertSee(__('billing.cart.recurring_note', ['amount' => $expected])); // and the note
+});