collab: Update billing migration endpoint to work for users without active subscriptions (#29792)

Marshall Bowers created

This PR updates the billing migration endpoint to work for users who do
not have an active subscription.

This will allow us to use the endpoint to migrate all users.

Release Notes:

- N/A

Change summary

crates/collab/src/api/billing.rs | 44 +++++++++++++++++-----------------
1 file changed, 22 insertions(+), 22 deletions(-)

Detailed changes

crates/collab/src/api/billing.rs 🔗

@@ -624,7 +624,7 @@ struct MigrateToNewBillingBody {
 #[derive(Debug, Serialize)]
 struct MigrateToNewBillingResponse {
     /// The ID of the subscription that was canceled.
-    canceled_subscription_id: String,
+    canceled_subscription_id: Option<String>,
 }
 
 async fn migrate_to_new_billing(
@@ -650,29 +650,28 @@ async fn migrate_to_new_billing(
         .get_active_billing_subscriptions(HashSet::from_iter([user.id]))
         .await?;
 
-    let Some((_billing_customer, billing_subscription)) =
+    let canceled_subscription_id = if let Some((_billing_customer, billing_subscription)) =
         old_billing_subscriptions_by_user.get(&user.id)
-    else {
-        return Err(Error::http(
-            StatusCode::NOT_FOUND,
-            "No active billing subscriptions to migrate".into(),
-        ));
-    };
+    {
+        let stripe_subscription_id = billing_subscription
+            .stripe_subscription_id
+            .parse::<stripe::SubscriptionId>()
+            .context("failed to parse Stripe subscription ID from database")?;
 
-    let stripe_subscription_id = billing_subscription
-        .stripe_subscription_id
-        .parse::<stripe::SubscriptionId>()
-        .context("failed to parse Stripe subscription ID from database")?;
+        Subscription::cancel(
+            &stripe_client,
+            &stripe_subscription_id,
+            stripe::CancelSubscription {
+                invoice_now: Some(true),
+                ..Default::default()
+            },
+        )
+        .await?;
 
-    Subscription::cancel(
-        &stripe_client,
-        &stripe_subscription_id,
-        stripe::CancelSubscription {
-            invoice_now: Some(true),
-            ..Default::default()
-        },
-    )
-    .await?;
+        Some(stripe_subscription_id)
+    } else {
+        None
+    };
 
     let feature_flags = app.db.list_feature_flags().await?;
 
@@ -691,7 +690,8 @@ async fn migrate_to_new_billing(
     }
 
     Ok(Json(MigrateToNewBillingResponse {
-        canceled_subscription_id: stripe_subscription_id.to_string(),
+        canceled_subscription_id: canceled_subscription_id
+            .map(|subscription_id| subscription_id.to_string()),
     }))
 }