"""Stripe Checkout and Billing Portal session helpers.""" from __future__ import annotations from typing import Any import stripe from django.conf import settings from finance.models import Invoice class StripeNotConfiguredError(RuntimeError): """Raised when Stripe secret key is missing.""" def configure_stripe() -> str: secret = settings.STRIPE_SECRET_KEY if not secret: raise StripeNotConfiguredError( "STRIPE_SECRET_KEY is not configured. Set it in the environment." ) stripe.api_key = secret return secret def subscription_line_items() -> list[dict[str, Any]]: """Build Checkout line_items from settings-backed subscription pricing.""" price_id = settings.STRIPE_PRICE_ID if price_id: return [{"price": price_id, "quantity": 1}] return [ { "price_data": { "currency": settings.SUBSCRIPTION_PRICE_CURRENCY, "unit_amount": settings.SUBSCRIPTION_PRICE_AMOUNT_CENTS, "recurring": {"interval": settings.SUBSCRIPTION_PRICE_INTERVAL}, "product_data": { "name": settings.SUBSCRIPTION_PRODUCT_NAME, }, }, "quantity": 1, } ] def create_checkout_session( *, user, success_url: str | None = None, cancel_url: str | None = None, ): """Create a Stripe Checkout Session for the subscription plan.""" configure_stripe() metadata = { "user_id": str(user.pk), "company_id": str(user.company_id) if user.company_id else "", } customer_email = getattr(user, "email", None) or None session = stripe.checkout.Session.create( mode="subscription", line_items=subscription_line_items(), success_url=success_url or settings.STRIPE_CHECKOUT_SUCCESS_URL, cancel_url=cancel_url or settings.STRIPE_CHECKOUT_CANCEL_URL, customer_email=customer_email, client_reference_id=str(user.pk), metadata=metadata, subscription_data={"metadata": metadata}, ) return session def resolve_stripe_customer_id(*, user) -> str | None: """Return the most recent Stripe customer id stored on the user's invoices.""" return ( Invoice.objects.filter(user=user) .exclude(stripe_customer_id="") .order_by("-created") .values_list("stripe_customer_id", flat=True) .first() ) def create_billing_portal_session( *, customer_id: str, return_url: str | None = None, ): """Create a Stripe Customer Portal session for plan/payment/cancel management.""" configure_stripe() return stripe.billing_portal.Session.create( customer=customer_id, return_url=return_url or settings.STRIPE_PORTAL_RETURN_URL, )