From 613e980267f0325c3f4650e68868bfe5398a5962 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Jun 2024 12:48:37 +0200 Subject: [PATCH] fix: cleanup subs in cloud --- .../Commands/CloudCleanupSubscriptions.php | 92 +++++++++++++++++++ app/Http/Controllers/Webhook/Stripe.php | 2 +- .../2024_06_25_184323_update_db.php | 26 ++++++ 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 app/Console/Commands/CloudCleanupSubscriptions.php diff --git a/app/Console/Commands/CloudCleanupSubscriptions.php b/app/Console/Commands/CloudCleanupSubscriptions.php new file mode 100644 index 000000000..0ef775dda --- /dev/null +++ b/app/Console/Commands/CloudCleanupSubscriptions.php @@ -0,0 +1,92 @@ +clearAll(); + $this->info('Cleaning up subcriptions teams'); + $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); + + $teams = Team::all()->sortBy('id'); + foreach ($teams as $team) { + $this->info("Checking team {$team->id}"); + if (! data_get($team, 'subscription')) { + $this->disableServers($team); + + continue; + } + // If the team has no subscription id and the invoice is paid, we need to reset the invoice paid status + if (! (data_get($team, 'subscription.stripe_subscription_id'))) { + $this->info("Resetting invoice paid status for team {$team->id} {$team->name}"); + + $team->subscription->update([ + 'stripe_invoice_paid' => false, + 'stripe_trial_already_ended' => false, + 'stripe_subscription_id' => null, + ]); + $this->disableServers($team); + + continue; + } else { + $subscription = $stripe->subscriptions->retrieve(data_get($team, 'subscription.stripe_subscription_id'), []); + $status = data_get($subscription, 'status'); + if ($status === 'active' || $status === 'past_due') { + $team->subscription->update([ + 'stripe_invoice_paid' => true, + 'stripe_trial_already_ended' => false, + ]); + + continue; + } + $this->info('Subscription status: '.$status); + $this->info('Subscription id: '.data_get($team, 'subscription.stripe_subscription_id')); + $confirm = $this->confirm('Do you want to cancel the subscription?', true); + if (! $confirm) { + $this->info("Skipping team {$team->id} {$team->name}"); + } else { + $this->info("Cancelling subscription for team {$team->id} {$team->name}"); + $team->subscription->update([ + 'stripe_invoice_paid' => false, + 'stripe_trial_already_ended' => false, + 'stripe_subscription_id' => null, + ]); + $this->disableServers($team); + } + } + } + + } catch (\Exception $e) { + $this->error($e->getMessage()); + + return; + } + } + + private function disableServers(Team $team) + { + foreach ($team->servers as $server) { + if ($server->settings->is_usable === true || $server->settings->is_reachable === true || $server->ip !== '1.2.3.4') { + $this->info("Disabling server {$server->id} {$server->name}"); + $server->settings()->update([ + 'is_usable' => false, + 'is_reachable' => false, + ]); + $server->update([ + 'ip' => '1.2.3.4', + ]); + } + } + + } +} diff --git a/app/Http/Controllers/Webhook/Stripe.php b/app/Http/Controllers/Webhook/Stripe.php index 230525c0e..15484f7f3 100644 --- a/app/Http/Controllers/Webhook/Stripe.php +++ b/app/Http/Controllers/Webhook/Stripe.php @@ -231,7 +231,7 @@ public function events(Request $request) 'stripe_plan_id' => null, 'stripe_cancel_at_period_end' => false, 'stripe_invoice_paid' => false, - 'stripe_trial_already_ended' => true, + 'stripe_trial_already_ended' => false, ]); // send_internal_notification('customer.subscription.deleted for customer: '.$customerId); break; diff --git a/database/migrations/2024_06_25_184323_update_db.php b/database/migrations/2024_06_25_184323_update_db.php index c57c4d403..005e063cc 100644 --- a/database/migrations/2024_06_25_184323_update_db.php +++ b/database/migrations/2024_06_25_184323_update_db.php @@ -19,6 +19,19 @@ public function up(): void $table->dropColumn('docker_compose_pr'); $table->dropColumn('docker_compose_pr_raw'); }); + Schema::table('subscriptions', function (Blueprint $table) { + $table->dropColumn('lemon_subscription_id'); + $table->dropColumn('lemon_order_id'); + $table->dropColumn('lemon_product_id'); + $table->dropColumn('lemon_variant_id'); + $table->dropColumn('lemon_variant_name'); + $table->dropColumn('lemon_customer_id'); + $table->dropColumn('lemon_status'); + $table->dropColumn('lemon_renews_at'); + $table->dropColumn('lemon_update_payment_menthod_url'); + $table->dropColumn('lemon_trial_ends_at'); + $table->dropColumn('lemon_ends_at'); + }); Schema::table('environment_variables', function (Blueprint $table) { $table->string('uuid')->nullable()->after('id'); }); @@ -51,6 +64,19 @@ public function down(): void $table->longText('docker_compose_pr')->nullable()->after('docker_compose_location'); $table->longText('docker_compose_pr_raw')->nullable()->after('docker_compose'); }); + Schema::table('subscriptions', function (Blueprint $table) { + $table->string('lemon_subscription_id')->nullable()->after('stripe_subscription_id'); + $table->string('lemon_order_id')->nullable()->after('lemon_subscription_id'); + $table->string('lemon_product_id')->nullable()->after('lemon_order_id'); + $table->string('lemon_variant_id')->nullable()->after('lemon_product_id'); + $table->string('lemon_variant_name')->nullable()->after('lemon_variant_id'); + $table->string('lemon_customer_id')->nullable()->after('lemon_variant_name'); + $table->string('lemon_status')->nullable()->after('lemon_customer_id'); + $table->timestamp('lemon_renews_at')->nullable()->after('lemon_status'); + $table->string('lemon_update_payment_menthod_url')->nullable()->after('lemon_renews_at'); + $table->timestamp('lemon_trial_ends_at')->nullable()->after('lemon_update_payment_menthod_url'); + $table->timestamp('lemon_ends_at')->nullable()->after('lemon_trial_ends_at'); + }); Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('uuid'); });