Add account self-delete and subscription lifecycle sync (#34)
Soft-delete DELETE /api/user/ for authenticated users (hide conversations, blacklist tokens, block staff self-delete). Sync Stripe portal cancel/change via subscription.updated/deleted webhooks and expose cancel_at_period_end for Account UI (chat_web_app#75 companion).
This commit is contained in:
@@ -8,10 +8,13 @@ from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from chat_backend.tests.factories import make_company, make_user
|
||||
from finance.models import Invoice, Payment
|
||||
from finance.models import Invoice, Payment, UserSubscription
|
||||
from finance.services.plans import assign_plan_from_stripe, seed_subscription_plans
|
||||
from finance.services.webhooks import (
|
||||
dispatch_stripe_event,
|
||||
handle_checkout_session_completed,
|
||||
handle_customer_subscription_deleted,
|
||||
handle_customer_subscription_updated,
|
||||
handle_invoice_paid,
|
||||
handle_invoice_payment_failed,
|
||||
)
|
||||
@@ -107,6 +110,66 @@ class WebhookHandlerUnitTestCase(APITestCase):
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_checkout_assigns_plan_from_metadata(self):
|
||||
seed_subscription_plans(update_existing=False)
|
||||
session = {
|
||||
"id": "cs_test_plan_meta",
|
||||
"metadata": {"user_id": str(self.user.pk), "plan_slug": "founders"},
|
||||
"customer": "cus_meta",
|
||||
"subscription": "sub_meta",
|
||||
"payment_intent": "pi_meta",
|
||||
"payment_status": "paid",
|
||||
"amount_total": 1000,
|
||||
"currency": "usd",
|
||||
}
|
||||
handle_checkout_session_completed(session)
|
||||
sub = self.user.subscription
|
||||
self.assertEqual(sub.plan.slug, "founders")
|
||||
self.assertEqual(sub.source, UserSubscription.Source.STRIPE)
|
||||
self.assertEqual(sub.status, UserSubscription.Status.ACTIVE)
|
||||
|
||||
def test_subscription_updated_sets_cancel_at_period_end(self):
|
||||
seed_subscription_plans(update_existing=False)
|
||||
assign_plan_from_stripe(
|
||||
self.user,
|
||||
plan_slug="founders",
|
||||
stripe_subscription_id="sub_cancel",
|
||||
)
|
||||
result = handle_customer_subscription_updated(
|
||||
{
|
||||
"id": "sub_cancel",
|
||||
"status": "active",
|
||||
"cancel_at_period_end": True,
|
||||
"current_period_end": 1_700_259_200,
|
||||
"metadata": {"user_id": str(self.user.pk), "plan_slug": "founders"},
|
||||
}
|
||||
)
|
||||
self.assertIsNotNone(result)
|
||||
sub = UserSubscription.objects.get(user=self.user)
|
||||
self.assertTrue(sub.cancel_at_period_end)
|
||||
self.assertEqual(sub.status, UserSubscription.Status.ACTIVE)
|
||||
self.assertIsNotNone(sub.current_period_end)
|
||||
|
||||
def test_subscription_deleted_marks_canceled(self):
|
||||
seed_subscription_plans(update_existing=False)
|
||||
assign_plan_from_stripe(
|
||||
self.user,
|
||||
plan_slug="founders",
|
||||
stripe_subscription_id="sub_gone",
|
||||
)
|
||||
result = handle_customer_subscription_deleted(
|
||||
{
|
||||
"id": "sub_gone",
|
||||
"status": "canceled",
|
||||
"current_period_end": 1_700_259_200,
|
||||
"metadata": {"user_id": str(self.user.pk)},
|
||||
}
|
||||
)
|
||||
self.assertIsNotNone(result)
|
||||
sub = UserSubscription.objects.get(user=self.user)
|
||||
self.assertEqual(sub.status, UserSubscription.Status.CANCELED)
|
||||
self.assertFalse(sub.cancel_at_period_end)
|
||||
|
||||
|
||||
class StripeWebhookViewTestCase(APITestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user