Skip to main content

Plans, entitlements, and usage tracking for Django SaaS apps.

Project description

mroudai-django-subscriptions

Reusable Django app for plans, subscriptions, entitlements, and usage limits. It does not process payments.

Features

  • Plans with feature flags and numeric limits.
  • Subscriptions scoped to a tenant or user.
  • Deterministic entitlement resolution (resolve_entitlements).
  • Optional per-tenant/user overrides and metered usage tracking.
  • Grace periods and trials with sensible defaults.
  • Django admin for plans, subscriptions, overrides, and usage counters.

Installation

pip install mroudai-django-subscriptions

Add to INSTALLED_APPS:

INSTALLED_APPS = [
    # ...
    "subscriptions",
]

Run migrations:

python manage.py migrate subscriptions

Settings

SUBSCRIPTIONS_TENANT_MODEL = None        # e.g. "tenants.Tenant" or None
SUBSCRIPTIONS_USER_MODEL = None          # defaults to AUTH_USER_MODEL
SUBSCRIPTIONS_DEFAULT_PLAN_SLUG = "free"
SUBSCRIPTIONS_TRIAL_DAYS_DEFAULT = 14
SUBSCRIPTIONS_GRACE_DAYS_DEFAULT = 7
SUBSCRIPTIONS_ENABLE_OVERRIDES = True
SUBSCRIPTIONS_ENABLE_USAGE = True

Tenancy rules:

  • If SUBSCRIPTIONS_TENANT_MODEL is set, subscriptions are tenant-first; user is optional for attribution.
  • If it is not set, subscriptions are user-scoped.

Defining plans

Plans are static and hold flags + limits:

from subscriptions.models import Plan

Plan.objects.create(
    name="Free",
    slug="free",
    features={"booking_ui": True, "multi_staff": False},
    limits={"providers_max": 1, "bookings_per_month": 50},
)

Features must be booleans. Limits must be integers >= 0 or None for unlimited.

Assigning subscriptions

from subscriptions.services import assign_plan

# user-mode example
subscription = assign_plan(plan="pro", user=request.user)

This expires any current subscription for the same tenant/user and starts a new one. Trials default to SUBSCRIPTIONS_TRIAL_DAYS_DEFAULT.

Cancel with optional grace:

from subscriptions.services import cancel_subscription

cancel_subscription(subscription, at_period_end=False)

Resolving entitlements

from subscriptions.selectors import resolve_entitlements

entitlements = resolve_entitlements(user=request.user)

entitlements == {
    "features": {"booking_ui": True, ...},
    "limits": {"bookings_per_month": 50, ...},
    "status": "ACTIVE",  # TRIAL/GRACE/EXPIRED etc determined by dates
}

Overrides (optional)

If SUBSCRIPTIONS_ENABLE_OVERRIDES is True, use the admin or create EntitlementOverride rows to tweak features/limits per tenant or user. Overrides are applied on top of the plan.

Usage tracking (optional)

If SUBSCRIPTIONS_ENABLE_USAGE is True, increment and enforce limits for keys ending with _per_month:

from subscriptions.services import increment_usage, enforce_limit

enforce_limit(key="bookings_per_month", user=request.user)
increment_usage(key="bookings_per_month", user=request.user)

check_limit returns (allowed, remaining); enforce_limit raises ValidationError if exceeded.

Decorators

from subscriptions.services import require_feature, require_limit

@require_feature("booking_ui")
def create_booking(*, user, **kwargs):
    ...

@require_limit("bookings_per_month")
def make_booking(*, user, **kwargs):
    ...

Admin

The Django admin registers plans, subscriptions, overrides, and usage counters. JSON fields use a simple textarea for quick editing.

What this app deliberately does not do

  • No payment gateway integration (PayWise/Stripe/etc.).
  • No invoicing or receipts.
  • No domain-specific booking logic.

Development

Tests (using SQLite by default):

python test django-subscriptions

SQLite works for development; PostgreSQL is recommended for production.

Release to PyPI

Install build tooling:

python install_upload_dependencies.py

Build and upload (requires TWINE_USERNAME/TWINE_PASSWORD or TWINE_TOKEN):

python upload.py

Licence

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mroudai_django_subscriptions-0.1.0.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mroudai_django_subscriptions-0.1.0-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file mroudai_django_subscriptions-0.1.0.tar.gz.

File metadata

File hashes

Hashes for mroudai_django_subscriptions-0.1.0.tar.gz
Algorithm Hash digest
SHA256 08d0bf7da56450f8de6d263916ee1658d1482be0dc790c210192e96f5a98478b
MD5 02c59d0bf3e0bb7e263f1362cc3adbb8
BLAKE2b-256 74f119a15afe91414d92dd2580800603a276806763981a00b7d3f9ed5b58dd54

See more details on using hashes here.

File details

Details for the file mroudai_django_subscriptions-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mroudai_django_subscriptions-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 97cedff2f1ae06db7eb8d7e28d8c34e1c516f87b64359c89390e70ad5f24ba04
MD5 d4a5cdfbc99d6795ea92332625e1a199
BLAKE2b-256 27d375fae8c766fc1709425f1b006d349df2fe5f9ae3e0aaec20309557900596

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page