## Summary - Companion to [chat_web_app#33](ai_ml_operations/chat_web_app#33) (Account billing + Customer Portal) - Follow-on from finance MVP [#21](#21): add authenticated `POST /api/finance/portal/` that creates a Stripe Billing Portal session and returns `portal_url` - Resolve Stripe customer from the user's latest `Invoice.stripe_customer_id`; return `400` when missing (user must complete Checkout first) - Document `STRIPE_PORTAL_RETURN_URL` (default `{FRONTEND_BASE_URL}/account/`) in settings + env examples ## Test plan - [ ] `manage.py test finance.tests.test_portal finance.tests.test_checkout` - [ ] Authenticated portal create with invoice that has `stripe_customer_id` → `201` + `portal_url` - [ ] No customer / unpaid user → `400` with clear detail - [ ] Missing `STRIPE_SECRET_KEY` → `503` - [ ] Unauthenticated → `401` - [ ] Custom `return_url` in body overrides default portal return URLReviewed-on: #35
38 lines
777 B
Python
38 lines
777 B
Python
from django.urls import path
|
|
|
|
from finance.views import (
|
|
CreateBillingPortalSessionView,
|
|
CreateCheckoutSessionView,
|
|
InvoiceListView,
|
|
PaymentListView,
|
|
StripeWebhookView,
|
|
)
|
|
|
|
urlpatterns = [
|
|
path(
|
|
"checkout/",
|
|
CreateCheckoutSessionView.as_view(),
|
|
name="finance_checkout",
|
|
),
|
|
path(
|
|
"portal/",
|
|
CreateBillingPortalSessionView.as_view(),
|
|
name="finance_portal",
|
|
),
|
|
path(
|
|
"invoices/",
|
|
InvoiceListView.as_view(),
|
|
name="finance_invoices",
|
|
),
|
|
path(
|
|
"payments/",
|
|
PaymentListView.as_view(),
|
|
name="finance_payments",
|
|
),
|
|
path(
|
|
"webhooks/stripe/",
|
|
StripeWebhookView.as_view(),
|
|
name="finance_stripe_webhook",
|
|
),
|
|
]
|