Documentation of all data models in the Payments app

Payments App Data Models Documentation

Brand values alignment: All features and data models should align with Courtex values: Community, Transparency, Accessibility, Integrity, Humility. Payment data must be handled with integrity and transparency. See docs/markdown/brand/copilot-instructions.md for full guidance.

Overview

The Payments app integrates Courtex with Stripe for subscription billing and payment processing. It stores Stripe product/price references and provides an audit log of all received webhook events.

Core Models

1. StripeProduct

The StripeProduct model stores a reference to a Stripe product and its associated price, used to link Courtex subscription plans to Stripe billing.

Key Fields: - name: Human-friendly product name - product_id: Stripe Product ID (e.g., prod_xxx) - price_id: Stripe Price ID (e.g., price_xxx); must be unique - amount: Price amount as a decimal (stored for local reference) - currency: Currency code (default AUD)

Business Logic: - Maps Stripe products to Courtex subscription plans (users.Plan) - price_id uniqueness ensures no duplicate Stripe price entries - Does not inherit from TimeStampedModel


2. StripeWebhookEvent

The StripeWebhookEvent model is an audit log of all Stripe webhook events received by Courtex. It enables idempotent processing and error tracking.

Key Fields: - event_id: Stripe event ID (e.g., evt_xxx); must be unique - type: Stripe event type string (e.g., payment_intent.succeeded, customer.subscription.updated) - user: Foreign key to users.User (nullable; SET_NULL on delete) — the user associated with this event - payload: Full event JSON payload (JSONField) - processed: Whether the event has been successfully processed (default False) - processing_error: Optional text field to store any errors encountered during processing - stripe_created: Datetime of the event as reported by Stripe - livemode: Boolean indicating whether the event is from live mode (True) or test mode (False)

Inherited from TimeStampedModel: - created_at, updated_at, deleted_at

Meta (Database Indexes): - Index on type — for filtering events by type - Index on processed — for querying unprocessed events - Index on created_at — for time-based queries

Business Logic: - Webhook events should be written to this table immediately on receipt, before any processing - Use event_id uniqueness to prevent duplicate event processing (idempotency) - Set processed = True after successful handling - Store any exceptions in processing_error for debugging failed events - A separate webhook model should be created for each external service (not only Stripe)


Related Apps

  • users: StripeWebhookEvent references users.User; users.Plan and users.Subscription hold the Stripe subscription ID and link to plan/tier
  • finance: Account balance credits triggered by webhook events are applied via finance.AccountBalance