mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
feat(billing): cancel in-app with a one-question reason
Add a "Cancel subscription" button beside "Manage Subscription" in Settings. It opens a dialog with one optional question (five answers, no default, a note box under the two that want detail), then schedules the Stripe subscription to end at the close of the current period without a trip to the portal. The answer is stored in a new subscription_cancellations table and shown, with an all-time tally, on the admin dashboard; the category is also mirrored onto Stripe's cancellation feedback, the free text stays local. The cancel route claims the local cancel flag with a conditional update before calling Stripe, so two racing requests cannot both write a reason row, and hands the claim back when Stripe refuses. A subscription Stripe no longer knows answers 409 with a pointer to the portal instead of a 500. The route carries an account-keyed rate limit on top of the shared IP one. Two fixes found on the way: the pinned Stripe API version reports current_period_end on the subscription item rather than the subscription, so the sync stored null for every period end; a shared helper now reads the item first. And the RadioGroup styles targeted a data-checked attribute radix never writes, so the checked state was invisible in the light theme.
This commit is contained in:
+6
-1
@@ -127,7 +127,12 @@ vi.mock('@/lib/stripe', async (importOriginal) => {
|
||||
...actual,
|
||||
getStripe: vi.fn(() => ({
|
||||
customers: { create: vi.fn(async () => ({ id: 'cus_test_default' })) },
|
||||
subscriptions: { list: vi.fn(async () => ({ data: [] })) },
|
||||
subscriptions: {
|
||||
list: vi.fn(async () => ({ data: [] })),
|
||||
update: vi.fn(() => {
|
||||
throw new Error('stripe.subscriptions.update was not stubbed for this test');
|
||||
}),
|
||||
},
|
||||
checkout: {
|
||||
sessions: { create: vi.fn(async () => ({ url: 'https://stripe.test/checkout' })) },
|
||||
},
|
||||
|
||||
@@ -70,6 +70,7 @@ const REVIEWED_MIGRATIONS = [
|
||||
'20260818120000_add_upload_reservation_purpose',
|
||||
'20260820120000_add_comment_images',
|
||||
'20260822120000_add_video_subtitles',
|
||||
'20260908120000_add_subscription_cancellations',
|
||||
];
|
||||
|
||||
/** Objects POST_PUSH_SQL must have produced. Verified after it runs. */
|
||||
|
||||
Reference in New Issue
Block a user