tenseleyflow/shithub / 8356cd5

Browse files

web/orgs/billing: gate Manage CTA on subscription_id, not customer_id

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
8356cd5c4e173cc9edbe1ae3efcdcb0f955ee562
Parents
987485f
Tree
b7edd51

1 changed file

StatusFile+-
M internal/web/handlers/orgs/billing_settings.go 21 15
internal/web/handlers/orgs/billing_settings.gomodified
@@ -223,21 +223,27 @@ func (h *Handlers) renderSettingsBilling(w http.ResponseWriter, r *http.Request,
223223
 		debug = h.billingDebugView(r, state)
224224
 	}
225225
 	_ = h.d.Render.RenderPage(w, r, "orgs/settings_billing", map[string]any{
226
-		"Title":                 org.Slug + " - billing and plans",
227
-		"CSRFToken":             middleware.CSRFTokenForRequest(r),
228
-		"Org":                   org,
229
-		"AvatarURL":             "/avatars/" + url.PathEscape(org.Slug),
230
-		"ActiveOrgNav":          "settings",
231
-		"OrgSettingsActive":     "billing",
232
-		"BillingEnabled":        h.d.BillingEnabled,
233
-		"Error":                 errMsg,
234
-		"Notice":                notice,
235
-		"BillingAlert":          billingAlertForState(state, org.Slug),
236
-		"Summary":               billingSummary(state, memberCount),
237
-		"Seats":                 billingSeatBreakdown{ActiveMembers: memberCount, BillableSeats: int64(state.BillableSeats), PendingInvites: pendingInviteCount, SnapshotLabel: billingSeatDetail(state)},
238
-		"PrivateCollaboration":  privateCollab,
239
-		"CanStartCheckout":      h.billingConfigured(),
240
-		"CanManageSubscription": h.billingConfigured() && state.StripeCustomerID.Valid && strings.TrimSpace(state.StripeCustomerID.String) != "",
226
+		"Title":                org.Slug + " - billing and plans",
227
+		"CSRFToken":            middleware.CSRFTokenForRequest(r),
228
+		"Org":                  org,
229
+		"AvatarURL":            "/avatars/" + url.PathEscape(org.Slug),
230
+		"ActiveOrgNav":         "settings",
231
+		"OrgSettingsActive":    "billing",
232
+		"BillingEnabled":       h.d.BillingEnabled,
233
+		"Error":                errMsg,
234
+		"Notice":               notice,
235
+		"BillingAlert":         billingAlertForState(state, org.Slug),
236
+		"Summary":              billingSummary(state, memberCount),
237
+		"Seats":                billingSeatBreakdown{ActiveMembers: memberCount, BillableSeats: int64(state.BillableSeats), PendingInvites: pendingInviteCount, SnapshotLabel: billingSeatDetail(state)},
238
+		"PrivateCollaboration": privateCollab,
239
+		"CanStartCheckout":     h.billingConfigured(),
240
+		// Gate on StripeSubscriptionID, not StripeCustomerID. A
241
+		// customer record exists from the moment a Checkout Session
242
+		// is minted; the subscription id only lands after
243
+		// customer.subscription.created. Gating on the customer id
244
+		// surfaced "Manage or cancel" buttons for orgs that abandoned
245
+		// checkout without paying.
246
+		"CanManageSubscription": h.billingConfigured() && state.StripeSubscriptionID.Valid && strings.TrimSpace(state.StripeSubscriptionID.String) != "",
241247
 		"GracePeriodLabel":      formatGracePeriod(h.d.BillingGracePeriod),
242248
 		"Invoices":              billingInvoiceViews(invoices),
243249
 		"IsSiteAdmin":           viewer.IsSiteAdmin,