Merge pull request #5262 from coollabsio/next

v4.0.0-beta.398
This commit is contained in:
Andras Bacsai 2025-03-01 12:49:14 +01:00 committed by GitHub
commit c9b364e03a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 86 additions and 13 deletions

View file

@ -50,7 +50,7 @@ public function handle()
} else { } else {
$subscription = $stripe->subscriptions->retrieve(data_get($team, 'subscription.stripe_subscription_id'), []); $subscription = $stripe->subscriptions->retrieve(data_get($team, 'subscription.stripe_subscription_id'), []);
$status = data_get($subscription, 'status'); $status = data_get($subscription, 'status');
if ($status === 'active' || $status === 'past_due') { if ($status === 'active') {
$team->subscription->update([ $team->subscription->update([
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
'stripe_trial_already_ended' => false, 'stripe_trial_already_ended' => false,

View file

@ -73,19 +73,21 @@ public function handle(): void
} }
$subscription = Subscription::where('team_id', $teamId)->first(); $subscription = Subscription::where('team_id', $teamId)->first();
if ($subscription) { if ($subscription) {
send_internal_notification('Old subscription activated for team: '.$teamId); // send_internal_notification('Old subscription activated for team: '.$teamId);
$subscription->update([ $subscription->update([
'stripe_subscription_id' => $subscriptionId, 'stripe_subscription_id' => $subscriptionId,
'stripe_customer_id' => $customerId, 'stripe_customer_id' => $customerId,
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
'stripe_past_due' => false,
]); ]);
} else { } else {
send_internal_notification('New subscription for team: '.$teamId); // send_internal_notification('New subscription for team: '.$teamId);
Subscription::create([ Subscription::create([
'team_id' => $teamId, 'team_id' => $teamId,
'stripe_subscription_id' => $subscriptionId, 'stripe_subscription_id' => $subscriptionId,
'stripe_customer_id' => $customerId, 'stripe_customer_id' => $customerId,
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
'stripe_past_due' => false,
]); ]);
} }
break; break;
@ -100,6 +102,7 @@ public function handle(): void
if ($subscription) { if ($subscription) {
$subscription->update([ $subscription->update([
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
'stripe_past_due' => false,
]); ]);
} else { } else {
throw new \RuntimeException("No subscription found for customer: {$customerId}"); throw new \RuntimeException("No subscription found for customer: {$customerId}");
@ -119,9 +122,7 @@ public function handle(): void
} }
if (! $subscription->stripe_invoice_paid) { if (! $subscription->stripe_invoice_paid) {
SubscriptionInvoiceFailedJob::dispatch($team); SubscriptionInvoiceFailedJob::dispatch($team);
send_internal_notification('Invoice payment failed: '.$customerId); // send_internal_notification('Invoice payment failed: '.$customerId);
} else {
send_internal_notification('Invoice payment failed but already paid: '.$customerId);
} }
break; break;
case 'payment_intent.payment_failed': case 'payment_intent.payment_failed':
@ -136,7 +137,7 @@ public function handle(): void
return; return;
} }
send_internal_notification('Subscription payment failed for customer: '.$customerId); // send_internal_notification('Subscription payment failed for customer: '.$customerId);
break; break;
case 'customer.subscription.created': case 'customer.subscription.created':
$customerId = data_get($data, 'customer'); $customerId = data_get($data, 'customer');
@ -158,7 +159,7 @@ public function handle(): void
} }
$subscription = Subscription::where('team_id', $teamId)->first(); $subscription = Subscription::where('team_id', $teamId)->first();
if ($subscription) { if ($subscription) {
send_internal_notification("Subscription already exists for team: {$teamId}"); // send_internal_notification("Subscription already exists for team: {$teamId}");
throw new \RuntimeException("Subscription already exists for team: {$teamId}"); throw new \RuntimeException("Subscription already exists for team: {$teamId}");
} else { } else {
Subscription::create([ Subscription::create([
@ -182,7 +183,7 @@ public function handle(): void
$subscription = Subscription::where('stripe_customer_id', $customerId)->first(); $subscription = Subscription::where('stripe_customer_id', $customerId)->first();
if (! $subscription) { if (! $subscription) {
if ($status === 'incomplete_expired') { if ($status === 'incomplete_expired') {
send_internal_notification('Subscription incomplete expired'); // send_internal_notification('Subscription incomplete expired');
throw new \RuntimeException('Subscription incomplete expired'); throw new \RuntimeException('Subscription incomplete expired');
} }
if ($teamId) { if ($teamId) {
@ -217,16 +218,40 @@ public function handle(): void
'stripe_plan_id' => $planId, 'stripe_plan_id' => $planId,
'stripe_cancel_at_period_end' => $cancelAtPeriodEnd, 'stripe_cancel_at_period_end' => $cancelAtPeriodEnd,
]); ]);
if ($status === 'paused' || $status === 'incomplete_expired' || $status === 'past_due') { if ($status === 'paused' || $status === 'incomplete_expired') {
if ($subscription->stripe_subscription_id === $subscriptionId) { if ($subscription->stripe_subscription_id === $subscriptionId) {
$subscription->update([ $subscription->update([
'stripe_invoice_paid' => false, 'stripe_invoice_paid' => false,
]); ]);
} }
} }
if ($status === 'past_due') {
if ($subscription->stripe_subscription_id === $subscriptionId) {
$subscription->update([
'stripe_past_due' => true,
]);
send_internal_notification('Past Due: '.$customerId.'Subscription ID: '.$subscriptionId);
}
}
if ($status === 'unpaid') {
if ($subscription->stripe_subscription_id === $subscriptionId) {
$subscription->update([
'stripe_invoice_paid' => false,
]);
send_internal_notification('Unpaid: '.$customerId.'Subscription ID: '.$subscriptionId);
}
$team = data_get($subscription, 'team');
if ($team) {
$team->subscriptionEnded();
} else {
send_internal_notification('Subscription unpaid but no team found in Coolify for customer: '.$customerId);
throw new \RuntimeException("No team found in Coolify for customer: {$customerId}");
}
}
if ($status === 'active') { if ($status === 'active') {
if ($subscription->stripe_subscription_id === $subscriptionId) { if ($subscription->stripe_subscription_id === $subscriptionId) {
$subscription->update([ $subscription->update([
'stripe_past_due' => false,
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
]); ]);
} }

View file

@ -93,6 +93,15 @@ public static function serverLimitReached()
return $servers >= $serverLimit; return $servers >= $serverLimit;
} }
public function subscriptionPastOverDue()
{
if (isCloud()) {
return $this->subscription?->stripe_past_due;
}
return false;
}
public function serverOverflow() public function serverOverflow()
{ {
if ($this->serverLimit() < $this->servers->count()) { if ($this->serverLimit() < $this->servers->count()) {
@ -185,6 +194,7 @@ public function subscriptionEnded()
'stripe_cancel_at_period_end' => false, 'stripe_cancel_at_period_end' => false,
'stripe_invoice_paid' => false, 'stripe_invoice_paid' => false,
'stripe_trial_already_ended' => false, 'stripe_trial_already_ended' => false,
'stripe_past_due' => false,
]); ]);
foreach ($this->servers as $server) { foreach ($this->servers as $server) {
$server->settings()->update([ $server->settings()->update([

View file

@ -2,7 +2,7 @@
return [ return [
'coolify' => [ 'coolify' => [
'version' => '4.0.0-beta.397', 'version' => '4.0.0-beta.398',
'helper_version' => '1.0.7', 'helper_version' => '1.0.7',
'realtime_version' => '1.0.6', 'realtime_version' => '1.0.6',
'self_hosted' => env('SELF_HOSTED', true), 'self_hosted' => env('SELF_HOSTED', true),

View file

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('subscriptions', function (Blueprint $table) {
$table->boolean('stripe_past_due')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('subscriptions', function (Blueprint $table) {
$table->dropColumn('stripe_past_due');
});
}
};

View file

@ -79,6 +79,16 @@ class="text-xs underline dark:text-white">OpenCollective</a>.<br><br></span>
</x-slot:button-text> </x-slot:button-text>
</x-popup> </x-popup>
</span> </span>
@if (currentTeam()->subscriptionPastOverDue())
<x-banner :closable=false>
<div><span class="font-bold text-red-500">WARNING:</span> Your subscription is in over-due. If your latest
payment is not paid within a week, all automations <span class="font-bold text-red-500">will
be deactivated</span>. Visit <a href="{{ route('subscription.show') }}"
class="underline dark:text-white">/subscription</a> to check your subscription status or pay your
invoice (or check your email for the invoice).
</div>
</x-banner>
@endif
@if (currentTeam()->serverOverflow()) @if (currentTeam()->serverOverflow())
<x-banner :closable=false> <x-banner :closable=false>
<div><span class="font-bold text-red-500">WARNING:</span> The number of active servers exceeds the limit <div><span class="font-bold text-red-500">WARNING:</span> The number of active servers exceeds the limit

View file

@ -1,10 +1,10 @@
{ {
"coolify": { "coolify": {
"v4": { "v4": {
"version": "4.0.0-beta.397" "version": "4.0.0-beta.398"
}, },
"nightly": { "nightly": {
"version": "4.0.0-beta.398" "version": "4.0.0-beta.399"
}, },
"helper": { "helper": {
"version": "1.0.7" "version": "1.0.7"