Skip to content

Commit e974a06

Browse files
simonhampclaude
andauthored
Remove automatic is_comped detection from invoice handler (#332)
* Remove automatic is_comped detection from invoice paid handler Stop auto-setting is_comped based on invoice total being zero. The comped status should only be set intentionally via admin tools. Renamed method to updateSubscriptionPricePaid to reflect its purpose. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix dashboard showing Active badge for canceled subscriptions Check subscription active() status instead of just existence, so canceled/ended subscriptions correctly show "No active subscription". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8b701ce commit e974a06

4 files changed

Lines changed: 79 additions & 9 deletions

File tree

app/Jobs/HandleInvoicePaidJob.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ private function handleSubscriptionUpdate(): void
6161
'invoice_id' => $this->invoice->id,
6262
]);
6363

64-
$this->updateSubscriptionCompedStatus();
64+
$this->updateSubscriptionPricePaid();
6565
}
6666

6767
private function handleSubscriptionCreated(): void
@@ -76,12 +76,12 @@ private function handleSubscriptionCreated(): void
7676

7777
if ($isRenewal && $licenseKey && $licenseId) {
7878
$this->handleLegacyLicenseRenewal($subscription, $licenseKey, $licenseId);
79-
$this->updateSubscriptionCompedStatus();
79+
$this->updateSubscriptionPricePaid();
8080

8181
return;
8282
}
8383

84-
$this->updateSubscriptionCompedStatus();
84+
$this->updateSubscriptionPricePaid();
8585
}
8686

8787
private function handleLegacyLicenseRenewal($subscription, string $licenseKey, string $licenseId): void
@@ -169,7 +169,7 @@ private function handleSubscriptionRenewal(): void
169169
'invoice_id' => $this->invoice->id,
170170
]);
171171

172-
$this->updateSubscriptionCompedStatus();
172+
$this->updateSubscriptionPricePaid();
173173
}
174174

175175
private function handleManualInvoice(): void
@@ -591,9 +591,9 @@ private function createBundlePluginLicense(User $user, Plugin $plugin, PluginBun
591591
}
592592

593593
/**
594-
* Mark the local Cashier subscription as comped if the invoice total is zero.
594+
* Update the price paid on the local Cashier subscription from the invoice total.
595595
*/
596-
private function updateSubscriptionCompedStatus(): void
596+
private function updateSubscriptionPricePaid(): void
597597
{
598598
if (! $this->invoice->subscription) {
599599
return;
@@ -605,7 +605,6 @@ private function updateSubscriptionCompedStatus(): void
605605
$invoiceTotal = $this->invoice->total ?? 0;
606606

607607
$subscription->update([
608-
'is_comped' => $invoiceTotal <= 0,
609608
'price_paid' => max(0, $invoiceTotal),
610609
]);
611610
}

resources/views/livewire/customer/dashboard.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
/>
8383

8484
{{-- Subscription Card --}}
85-
@if($this->activeSubscription)
85+
@if($this->activeSubscription?->active())
8686
<x-dashboard-card
8787
title="Subscription"
8888
:value="$this->subscriptionName"

tests/Feature/DashboardLayoutTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,26 @@ public function test_user_name_with_apostrophe_is_not_double_escaped_in_dashboar
5353
$response->assertSee("Timmy D'Hooghe");
5454
}
5555

56+
// ========================================
57+
// Subscription Card Tests
58+
// ========================================
59+
60+
public function test_dashboard_shows_no_active_subscription_when_subscription_is_canceled(): void
61+
{
62+
$user = User::factory()->create();
63+
Subscription::factory()->for($user)->create([
64+
'stripe_price' => self::MAX_PRICE_ID,
65+
'stripe_status' => 'canceled',
66+
'ends_at' => now()->subDay(),
67+
]);
68+
69+
Livewire::actingAs($user)
70+
->test(Dashboard::class)
71+
->assertOk()
72+
->assertSee('No active subscription')
73+
->assertDontSee('badge="Active"');
74+
}
75+
5676
// ========================================
5777
// Sidebar Team Item Tests
5878
// ========================================

tests/Feature/Jobs/HandleInvoicePaidJobTest.php

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,56 @@ public function it_does_not_create_license_for_any_subscription(string $planKey)
6666
Bus::assertNotDispatched(CreateAnystackLicenseJob::class);
6767
}
6868

69+
#[Test]
70+
public function it_does_not_auto_set_is_comped_when_invoice_total_is_zero(): void
71+
{
72+
Bus::fake();
73+
74+
$user = User::factory()->create([
75+
'stripe_id' => 'cus_test123',
76+
]);
77+
78+
$priceId = 'price_test_mini';
79+
config(['subscriptions.plans.mini.stripe_price_id' => $priceId]);
80+
81+
$subscription = \Laravel\Cashier\Subscription::factory()
82+
->for($user, 'user')
83+
->create([
84+
'stripe_id' => 'sub_test123',
85+
'stripe_status' => 'active',
86+
'stripe_price' => $priceId,
87+
'quantity' => 1,
88+
'is_comped' => false,
89+
]);
90+
91+
SubscriptionItem::factory()
92+
->for($subscription, 'subscription')
93+
->create([
94+
'stripe_id' => 'si_test123',
95+
'stripe_price' => $priceId,
96+
'quantity' => 1,
97+
]);
98+
99+
$this->mockStripeSubscriptionRetrieve('sub_test123');
100+
101+
$invoice = $this->createStripeInvoice(
102+
customerId: 'cus_test123',
103+
subscriptionId: 'sub_test123',
104+
billingReason: Invoice::BILLING_REASON_SUBSCRIPTION_CREATE,
105+
priceId: $priceId,
106+
subscriptionItemId: 'si_test123',
107+
total: 0,
108+
);
109+
110+
$job = new HandleInvoicePaidJob($invoice);
111+
$job->handle();
112+
113+
$subscription->refresh();
114+
115+
$this->assertFalse((bool) $subscription->is_comped);
116+
$this->assertEquals(0, $subscription->price_paid);
117+
}
118+
69119
public static function subscriptionPlanProvider(): array
70120
{
71121
return [
@@ -81,14 +131,15 @@ private function createStripeInvoice(
81131
string $billingReason,
82132
string $priceId,
83133
string $subscriptionItemId,
134+
int $total = 25000,
84135
): Invoice {
85136
return Invoice::constructFrom([
86137
'id' => 'in_test_'.uniqid(),
87138
'object' => 'invoice',
88139
'customer' => $customerId,
89140
'subscription' => $subscriptionId,
90141
'billing_reason' => $billingReason,
91-
'total' => 25000,
142+
'total' => $total,
92143
'currency' => 'usd',
93144
'payment_intent' => 'pi_test_'.uniqid(),
94145
'metadata' => [],

0 commit comments

Comments
 (0)