SurfSense/surfsense_backend/app/schemas/stripe.py
DESKTOP-RTLN3BA\$punk 65e511f77b feat: enhance credit management and user experience
- Updated database queries to check for column existence with schema context.
- Modified credit purchase quantity limits to allow up to 10,000 credits.
- Improved user interface for credit purchases, enabling custom amounts and clamping input values.
- Adjusted FAQ content to clarify credit purchasing process.
2026-06-10 22:52:27 -07:00

144 lines
4 KiB
Python

"""Schemas for Stripe-backed credit purchases."""
import uuid
from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field
from app.db import PagePurchaseStatus
class CreateCreditCheckoutSessionRequest(BaseModel):
"""Request body for creating a credit-purchase checkout session."""
quantity: int = Field(ge=1, le=10_000)
search_space_id: int = Field(ge=1)
class CreateCreditCheckoutSessionResponse(BaseModel):
"""Response containing the Stripe-hosted checkout URL."""
checkout_url: str
class CreditPurchaseRead(BaseModel):
"""Serialized credit purchase record.
``credit_micros_granted`` is in micro-USD (1_000_000 = $1.00).
"""
id: uuid.UUID
stripe_checkout_session_id: str
stripe_payment_intent_id: str | None = None
quantity: int
credit_micros_granted: int
amount_total: int | None = None
currency: str | None = None
source: str = "checkout"
status: str
completed_at: datetime | None = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class CreditPurchaseHistoryResponse(BaseModel):
"""Response containing the user's credit purchases."""
purchases: list[CreditPurchaseRead]
class CreditStripeStatusResponse(BaseModel):
"""Response describing credit-buying availability and current balance.
``credit_micros_balance`` is in micro-USD; the FE divides by 1_000_000
to display USD.
"""
credit_buying_enabled: bool
credit_micros_balance: int = 0
class PagePurchaseRead(BaseModel):
"""Serialized legacy page-purchase record (read-only history)."""
id: uuid.UUID
stripe_checkout_session_id: str
stripe_payment_intent_id: str | None = None
quantity: int
pages_granted: int
amount_total: int | None = None
currency: str | None = None
status: PagePurchaseStatus
completed_at: datetime | None = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class PagePurchaseHistoryResponse(BaseModel):
"""Response containing the authenticated user's legacy page purchases."""
purchases: list[PagePurchaseRead]
class AutoReloadSettingsResponse(BaseModel):
"""Auto-reload configuration + saved-card state for the settings UI.
All ``*_micros`` fields are micro-USD (1_000_000 == $1.00). ``feature_enabled``
reflects the server-side ``AUTO_RELOAD_ENABLED`` flag; when it is false the
UI should hide / disable the auto-reload controls entirely.
"""
feature_enabled: bool
enabled: bool = False
threshold_micros: int | None = None
amount_micros: int | None = None
min_amount_micros: int
has_payment_method: bool = False
failed_at: datetime | None = None
class UpdateAutoReloadSettingsRequest(BaseModel):
"""Update auto-reload preferences.
Enabling requires a saved card (set up via /stripe/auto-reload/setup) plus a
positive threshold and an amount of at least ``AUTO_RELOAD_MIN_AMOUNT_MICROS``.
"""
enabled: bool
threshold_micros: int | None = Field(default=None, ge=0)
amount_micros: int | None = Field(default=None, ge=0)
class CreateAutoReloadSetupSessionRequest(BaseModel):
"""Request body for starting the save-a-card (SetupIntent) checkout."""
search_space_id: int = Field(ge=1)
class CreateAutoReloadSetupSessionResponse(BaseModel):
"""Response containing the Stripe-hosted setup (save-card) checkout URL."""
checkout_url: str
class StripeWebhookResponse(BaseModel):
"""Generic acknowledgement for Stripe webhook delivery."""
received: bool = True
class FinalizeCheckoutResponse(BaseModel):
"""Response from /stripe/finalize-checkout.
Returned by the success page so the UI can show the post-purchase
balance immediately, even when the Stripe webhook hasn't been
delivered yet. ``status`` mirrors the underlying purchase row
(``pending`` / ``completed`` / ``failed``); the FE polls this
endpoint until it sees ``completed`` or a final ``failed``.
"""
status: str
credit_micros_balance: int = 0
credit_micros_granted: int | None = None