Files
chat_backend/llm_be/finance/serializers.py
T
westfarn 67f16565e9
Deploy Beta / unit-tests (push) Successful in 9s
Unit Tests / test (push) Successful in 10s
Deploy Beta / docker (push) Successful in 26s
Deploy Beta / deploy-beta (push) Successful in 6m49s
Add Stripe Customer Portal session API for account billing (#35)
## 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
2026-07-31 03:54:28 -07:00

56 lines
1.4 KiB
Python

from rest_framework import serializers
from finance.models import Invoice, Payment
class InvoiceSerializer(serializers.ModelSerializer):
class Meta:
model = Invoice
fields = [
"id",
"provider",
"status",
"currency",
"amount_due",
"amount_paid",
"period_start",
"period_end",
"stripe_invoice_id",
"stripe_checkout_session_id",
"stripe_subscription_id",
"hosted_invoice_url",
"description",
"created",
"last_modified",
]
read_only_fields = fields
class PaymentSerializer(serializers.ModelSerializer):
class Meta:
model = Payment
fields = [
"id",
"invoice",
"provider",
"status",
"currency",
"amount",
"stripe_payment_intent_id",
"stripe_charge_id",
"paid_at",
"failure_message",
"created",
"last_modified",
]
read_only_fields = fields
class CheckoutSessionSerializer(serializers.Serializer):
success_url = serializers.URLField(required=False, allow_blank=False)
cancel_url = serializers.URLField(required=False, allow_blank=False)
class PortalSessionSerializer(serializers.Serializer):
return_url = serializers.URLField(required=False, allow_blank=False)