Customization Playbooks¶
This section answers the most practical question a buyer or developer will have:
“I understand the system. Now how do I safely change it?”
Instead of vague advice, this section provides clear playbooks :
- what to change
- where to change it
- what side effects to expect
- what not to touch
Each playbook is based on real extension scenarios .
Adding a New Payment Gateway (Stripe / Razorpay)¶
Goal¶
Add a new payment provider without breaking existing purchases .
Correct Approach¶
- Create a new app
- Follow the same contract as
payments_dodo: - Initiate checkout
- Receive webhook
- Update
Order - Create
PurchasedProduct
What You Reuse¶
payments.Orderpayments.PurchasedProduct- Download logic
- Access checks
What You Must NOT Do¶
- Do not grant access directly
- Do not duplicate Order models
Why This Works¶
payments defines what access means
Provider apps only define how payment happens
Making Support Free or Subscription-Based¶
Scenario A – Free Support¶
If you want free support:
- Remove
PurchasedProductdependency - OR auto-create a “support entitlement”
⚠️ Strong Warning
This breaks a core revenue guardrail.
Recommended instead:
- Create a free tier product
- Grant access via
PurchasedProductas usual
Scenario B – Subscription Support¶
- Extend
PurchasedProductwith: - expiry date
- plan type
- Update:
has_active_support_request- support eligibility checks
Do NOT:
- Move logic into
depsupport - Bypass ownership checks
Adding Product Versions or Changelogs¶
Goal¶
Show detailed update history instead of a 3-day badge.
Safe Approach¶
- Create
ProductVersionmodel - Link it to
Product - Show latest version info in UI
Keep:
- Update badge logic intact
updated_atmeaningful
Do NOT:
- Remove update badge logic
- Store versions inside PurchasedProduct
Allowing Multiple Files per Product¶
Correct Pattern¶
- Create
ProductAssetmodel - ForeignKey →
Product - Control visibility per asset
Reuse:
- Signed URL download logic
- Ownership checks via PurchasedProduct
Do NOT:
- Store multiple files in JSON
- Expose raw storage URLs
Adding Roles (Admin, Affiliate, Manager)¶
Correct Way¶
- Add flags to
Useris_affiliate = True - Add mixins similar to:
IsSellerMixinIsCustomerMixin
Do NOT:
- Create new user tables
- Hardcode role checks in views
Customizing Seller Dashboard Metrics¶
Safe Customizations¶
- Add new cards
- Add new charts
- Add cached analytics
Use:
- Aggregations on Orders
- PurchasedProduct counts
Avoid:
- Querying payment providers live
- Heavy queries without caching
Changing Storage Provider (AWS S3 / GCP)¶
Correct Approach¶
- Modify
STORAGESsettings only - Keep storage API intact
Why this works:
- File access is abstracted
- Download logic stays unchanged
Never:
- Hardcode storage logic in views
- Change file access permissions casually
Customizing Authentication Flow¶
Safe Changes¶
- UI changes
- Add OTP or magic links
- Add new OAuth providers
Dangerous Changes
- Removing email verification
- Changing login redirect logic
Remember:
Auth is system entry point .
Adding APIs (Mobile / Public)¶
Recommended Strategy¶
- Create a new
apiapp - Reuse:
- models
- access rules
- Expose only read operations first
Do NOT:
- Put APIs inside existing apps
- Expose PurchasedProduct write access
Customization Golden Rules¶
- Never bypass PurchasedProduct
- Never grant access in UI
- Never let providers decide access
- Never duplicate ownership
- Never break role symmetry
If a change violates any of the above, rethink it.