payemnt billing and credits refactoring
This commit is contained in:
754
docs/10-MODULES/BILLING-PAYMENTS-COMPLETE.md
Normal file
754
docs/10-MODULES/BILLING-PAYMENTS-COMPLETE.md
Normal file
@@ -0,0 +1,754 @@
|
||||
# IGNY8 Billing & Payments - Complete Reference
|
||||
|
||||
> **Last Updated:** January 20, 2026
|
||||
> **Version:** 2.0 (Two-Pool Credit System)
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [System Overview](#1-system-overview)
|
||||
2. [Credit System](#2-credit-system)
|
||||
3. [Payment Methods](#3-payment-methods)
|
||||
4. [Subscription Lifecycle](#4-subscription-lifecycle)
|
||||
5. [Credit Packages](#5-credit-packages)
|
||||
6. [Invoice System](#6-invoice-system)
|
||||
7. [Renewal Workflow](#7-renewal-workflow)
|
||||
8. [Admin Operations](#8-admin-operations)
|
||||
9. [API Reference](#9-api-reference)
|
||||
10. [Database Schema](#10-database-schema)
|
||||
|
||||
---
|
||||
|
||||
## 1. System Overview
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ IGNY8 BILLING SYSTEM │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ STRIPE │ │ PAYPAL │ │ BANK TRANSFER│ │
|
||||
│ │ (Card/Intl) │ │ (Intl) │ │ (PK Only) │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ PAYMENT GATEWAY LAYER │ │
|
||||
│ │ • Webhook Processing • Payment Verification • Logging │ │
|
||||
│ └─────────────────────────────┬───────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ INVOICE SERVICE │ │
|
||||
│ │ • Create Invoice • Update Status • PDF Generation │ │
|
||||
│ └─────────────────────────────┬───────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ CREDIT SERVICE │ │
|
||||
│ │ • Plan Credits • Bonus Credits • Deduction • Reset │ │
|
||||
│ └─────────────────────────────┬───────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ ACCOUNT │ │
|
||||
│ │ credits (plan) │ bonus_credits (purchased) │ status │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key Files
|
||||
|
||||
| Component | File Path |
|
||||
|-----------|-----------|
|
||||
| Credit Service | `business/billing/services/credit_service.py` |
|
||||
| Invoice Service | `business/billing/services/invoice_service.py` |
|
||||
| Payment Service | `business/billing/services/payment_service.py` |
|
||||
| Email Service | `business/billing/services/email_service.py` |
|
||||
| Stripe Webhooks | `business/billing/views/stripe_views.py` |
|
||||
| PayPal Webhooks | `business/billing/views/paypal_views.py` |
|
||||
| Subscription Renewal | `business/billing/tasks/subscription_renewal.py` |
|
||||
| Invoice Lifecycle | `business/billing/tasks/invoice_lifecycle.py` |
|
||||
| Billing Admin | `modules/billing/admin.py` |
|
||||
| Billing Models | `business/billing/models.py` |
|
||||
|
||||
---
|
||||
|
||||
## 2. Credit System
|
||||
|
||||
### Two-Pool Credit Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ACCOUNT CREDITS │
|
||||
├────────────────────────────┬────────────────────────────────┤
|
||||
│ PLAN CREDITS │ BONUS CREDITS │
|
||||
│ (account.credits) │ (account.bonus_credits) │
|
||||
├────────────────────────────┼────────────────────────────────┤
|
||||
│ • From subscription plan │ • From credit packages │
|
||||
│ • Resets on renewal │ • NEVER expire │
|
||||
│ • Used FIRST │ • Used SECOND (after plan=0) │
|
||||
│ • Max = plan.included_ │ • No maximum limit │
|
||||
│ credits │ │
|
||||
└────────────────────────────┴────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Credit Deduction Flow
|
||||
|
||||
```
|
||||
┌──────────────────┐
|
||||
│ CREDIT REQUEST │
|
||||
│ (e.g., 50) │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Check Total │
|
||||
│ credits + bonus │
|
||||
│ >= requested? │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
┌──────────────┴──────────────┐
|
||||
│ NO │ YES
|
||||
▼ ▼
|
||||
┌────────────────┐ ┌────────────────────┐
|
||||
│ INSUFFICIENT │ │ Plan Credits >= 50?│
|
||||
│ Return False │ └─────────┬──────────┘
|
||||
└────────────────┘ │
|
||||
┌──────────┴──────────┐
|
||||
│ YES │ NO
|
||||
▼ ▼
|
||||
┌───────────────┐ ┌────────────────────┐
|
||||
│ Deduct from │ │ Deduct plan credits│
|
||||
│ plan credits │ │ to 0, remainder │
|
||||
│ only │ │ from bonus_credits │
|
||||
└───────────────┘ └────────────────────┘
|
||||
```
|
||||
|
||||
### Credit Operations
|
||||
|
||||
| Operation | Method | Affects | Description |
|
||||
|-----------|--------|---------|-------------|
|
||||
| Add Plan Credits | `add_credits()` | `credits` | Initial subscription, manual adjustment |
|
||||
| Add Bonus Credits | `add_bonus_credits()` | `bonus_credits` | Credit package purchases |
|
||||
| Deduct Credits | `deduct_credits()` | Both pools | AI operations, uses plan first |
|
||||
| Reset on Renewal | `reset_credits_for_renewal()` | `credits` only | Sets plan credits to new amount |
|
||||
| Check Balance | `check_credits()` | Read-only | Returns total available |
|
||||
|
||||
### Credit Transaction Types
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `subscription` | Plan credits from subscription |
|
||||
| `purchase` | Bonus credits from credit package |
|
||||
| `usage` | Credit consumption for AI operations |
|
||||
| `refund` | Credits returned due to failed operation |
|
||||
| `manual` | Admin adjustment |
|
||||
| `renewal` | Reset during subscription renewal |
|
||||
| `bonus` | Promotional bonus credits |
|
||||
|
||||
---
|
||||
|
||||
## 3. Payment Methods
|
||||
|
||||
### Payment Method by Country
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PAYMENT METHOD MATRIX │
|
||||
├─────────────────┬───────────────────────────────────────────┤
|
||||
│ COUNTRY │ AVAILABLE METHODS │
|
||||
├─────────────────┼───────────────────────────────────────────┤
|
||||
│ Pakistan (PK) │ ✅ Bank Transfer ✅ Stripe (Card) │
|
||||
│ │ ❌ PayPal (not available) │
|
||||
├─────────────────┼───────────────────────────────────────────┤
|
||||
│ Other (Intl) │ ✅ Stripe (Card) ✅ PayPal │
|
||||
│ │ ❌ Bank Transfer (not available) │
|
||||
└─────────────────┴───────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Payment Flow by Method
|
||||
|
||||
#### Stripe (Card) Flow
|
||||
|
||||
```
|
||||
┌─────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐
|
||||
│ User │────▶│ Frontend │────▶│ Create │────▶│ Stripe │
|
||||
│ Clicks │ │ Checkout │ │ Checkout │ │ Hosted │
|
||||
│ Pay │ │ │ │ Session │ │ Page │
|
||||
└─────────┘ └──────────┘ └─────────────┘ └────┬─────┘
|
||||
│
|
||||
▼
|
||||
┌─────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐
|
||||
│ Account │◀────│ Credit │◀────│ Invoice │◀────│ Webhook │
|
||||
│ Active │ │ Added │ │ Paid │ │ Received │
|
||||
└─────────┘ └──────────┘ └─────────────┘ └──────────┘
|
||||
```
|
||||
|
||||
#### PayPal Flow
|
||||
|
||||
```
|
||||
┌─────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐
|
||||
│ User │────▶│ Frontend │────▶│ Create │────▶│ PayPal │
|
||||
│ Clicks │ │ Checkout │ │ Order/Sub │ │ Hosted │
|
||||
│ Pay │ │ │ │ │ │ Page │
|
||||
└─────────┘ └──────────┘ └─────────────┘ └────┬─────┘
|
||||
│
|
||||
▼
|
||||
┌─────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐
|
||||
│ Account │◀────│ Credit │◀────│ Invoice │◀────│ Webhook │
|
||||
│ Active │ │ Added │ │ Paid │ │ CAPTURE │
|
||||
└─────────┘ └──────────┘ └─────────────┘ └──────────┘
|
||||
```
|
||||
|
||||
#### Bank Transfer Flow (PK Only)
|
||||
|
||||
```
|
||||
┌─────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐
|
||||
│ User │────▶│ View │────▶│ Manual │────▶│ Upload │
|
||||
│ Selects │ │ Bank │ │ Transfer │ │ Proof │
|
||||
│ Bank │ │ Details │ │ to Bank │ │ │
|
||||
└─────────┘ └──────────┘ └─────────────┘ └────┬─────┘
|
||||
│
|
||||
▼
|
||||
┌─────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐
|
||||
│ Account │◀────│ Credit │◀────│ Admin │◀────│ Payment │
|
||||
│ Active │ │ Added │ │ Approves │ │ Created │
|
||||
└─────────┘ └──────────┘ └─────────────┘ └──────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Subscription Lifecycle
|
||||
|
||||
### Subscription States
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ SUBSCRIPTION STATE MACHINE │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────┐
|
||||
│ NEW │
|
||||
│ SIGNUP │
|
||||
└────┬────┘
|
||||
│ Create subscription + invoice
|
||||
▼
|
||||
┌─────────────┐ Payment Failed ┌─────────────┐
|
||||
│ PENDING │─────────────────────────▶│ FAILED │
|
||||
│ (awaiting │ │ │
|
||||
│ payment) │ └─────────────┘
|
||||
└──────┬──────┘
|
||||
│ Payment Success
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ ACTIVE │◀─────────────────────────────────────┐
|
||||
│ │ Renewal Payment Success │
|
||||
└──────┬──────┘ │
|
||||
│ Renewal Date │
|
||||
▼ │
|
||||
┌─────────────┐ Payment Within ┌───────────┴─┐
|
||||
│ PENDING │ Grace Period │ │
|
||||
│ RENEWAL │────────────────────────▶│ ACTIVE │
|
||||
│ │ │ (renewed) │
|
||||
└──────┬──────┘ └─────────────┘
|
||||
│ Grace Period Expired (7 days)
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ EXPIRED │ Manual Reactivation
|
||||
│ │────────────────────────▶ Back to PENDING
|
||||
└─────────────┘
|
||||
|
||||
┌─────────────┐
|
||||
│ CANCELLED │ User-initiated cancellation
|
||||
│ │ (end of current period)
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
### Subscription Status Reference
|
||||
|
||||
| Status | Credits Access | Can Use Features | Next Action |
|
||||
|--------|----------------|------------------|-------------|
|
||||
| `pending` | ❌ No | ❌ No | Complete payment |
|
||||
| `active` | ✅ Yes | ✅ Yes | None (auto-renews) |
|
||||
| `pending_renewal` | ✅ Yes (24h) | ✅ Yes | Pay invoice |
|
||||
| `expired` | ❌ No | ❌ Limited | Resubscribe |
|
||||
| `cancelled` | ✅ Until end | ✅ Until end | None |
|
||||
| `failed` | ❌ No | ❌ No | Retry payment |
|
||||
|
||||
---
|
||||
|
||||
## 5. Credit Packages
|
||||
|
||||
### Available Packages
|
||||
|
||||
| Package | Credits | USD Price | PKR Price | Per Credit |
|
||||
|---------|---------|-----------|-----------|------------|
|
||||
| Starter | 500 | $50.00 | ≈ PKR 14,000 | $0.10 |
|
||||
| Growth | 2,000 | $200.00 | ≈ PKR 56,000 | $0.10 |
|
||||
| Scale | 5,000 | $300.00 | ≈ PKR 83,000 | $0.06 |
|
||||
| Enterprise | 20,000 | $1,200.00 | ≈ PKR 334,000 | $0.06 |
|
||||
|
||||
### Credit Package Purchase Flow
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────────────────────┐
|
||||
│ CREDIT PACKAGE PURCHASE FLOW │
|
||||
└───────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
User selects package
|
||||
│
|
||||
▼
|
||||
┌───────────────────┐
|
||||
│ Create Invoice │
|
||||
│ type='credit_ │
|
||||
│ package' │
|
||||
└─────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
|
||||
│ Stripe/PayPal? │────▶│ Auto-process via │────▶│ Webhook confirms │
|
||||
│ │ │ payment gateway │ │ payment success │
|
||||
└─────────┬─────────┘ └───────────────────┘ └─────────┬─────────┘
|
||||
│ │
|
||||
│ Bank Transfer? │
|
||||
▼ │
|
||||
┌───────────────────┐ ┌───────────────────┐ │
|
||||
│ Payment created │────▶│ Admin reviews & │ │
|
||||
│ status='pending_ │ │ approves payment │ │
|
||||
│ approval' │ └─────────┬─────────┘ │
|
||||
└───────────────────┘ │ │
|
||||
▼ ▼
|
||||
┌───────────────────────────────────────┐
|
||||
│ PAYMENT APPROVED │
|
||||
└─────────────────┬─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────┐
|
||||
│ CreditService.add_bonus_credits() │
|
||||
│ • Adds to account.bonus_credits │
|
||||
│ • Creates CreditTransaction │
|
||||
│ • NEVER expires │
|
||||
└───────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Credit Package Invoice Lifecycle
|
||||
|
||||
```
|
||||
Invoice Created ──▶ 48 hours ──▶ Reminder Sent ──▶ 48 hours ──▶ Invoice Voided
|
||||
│ │ │
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
status='pending' status='pending' status='void'
|
||||
(reminder sent) (auto-cancelled)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Invoice System
|
||||
|
||||
### Invoice Types
|
||||
|
||||
| Type | Description | Auto-Pay | Manual Pay |
|
||||
|------|-------------|----------|------------|
|
||||
| `subscription` | Monthly plan payment | Stripe/PayPal | Bank Transfer |
|
||||
| `credit_package` | One-time credit purchase | Stripe/PayPal | Bank Transfer |
|
||||
| `addon` | Additional features | Stripe/PayPal | Bank Transfer |
|
||||
| `custom` | Manual/admin-created | ❌ | ✅ |
|
||||
|
||||
### Invoice Status Flow
|
||||
|
||||
```
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ DRAFT │────▶│ SENT │────▶│ PENDING │────▶│ PAID │
|
||||
└─────────┘ └─────────┘ └────┬────┘ └─────────┘
|
||||
│
|
||||
┌────────┴────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────┐ ┌──────────┐
|
||||
│ OVERDUE │ │ FAILED │
|
||||
└────┬─────┘ └──────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────┐ ┌──────────┐
|
||||
│ VOID │ │CANCELLED │
|
||||
└──────────┘ └──────────┘
|
||||
```
|
||||
|
||||
### Invoice Status Reference
|
||||
|
||||
| Status | Description | User Action |
|
||||
|--------|-------------|-------------|
|
||||
| `draft` | Being created | - |
|
||||
| `sent` | Delivered to user | Pay Now |
|
||||
| `pending` | Awaiting payment | Pay Now |
|
||||
| `overdue` | Past due date | Pay Now (urgent) |
|
||||
| `paid` | Payment received | Download PDF |
|
||||
| `failed` | Payment failed | Retry/Pay Now |
|
||||
| `void` | Cancelled by system | - |
|
||||
| `cancelled` | Cancelled by admin | - |
|
||||
|
||||
---
|
||||
|
||||
## 7. Renewal Workflow
|
||||
|
||||
### Renewal Timeline by Payment Method
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ RENEWAL TIMELINE - STRIPE/PAYPAL (AUTO-PAY) │
|
||||
│ Industry Standard: No Advance Notice │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Day 0 (Renewal) Day +1 Day +7 │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌──────────┐ ┌────────────┐ ┌──────────┐ │
|
||||
│ │Auto-Pay │ │ If Failed: │ │ Expired │ │
|
||||
│ │ Attempt │ │ Retry + │ │ (after │ │
|
||||
│ └────┬─────┘ │ Email Sent │ │ retries) │ │
|
||||
│ │ └────────────┘ └──────────┘ │
|
||||
│ ┌────┴────┐ │
|
||||
│ │ SUCCESS │──▶ Receipt email + Credits reset to plan amount │
|
||||
│ └────┬────┘ │
|
||||
│ │ │
|
||||
│ ┌────┴────┐ │
|
||||
│ │ FAILURE │──▶ Payment failed email, Stripe retries 4x over 7 days │
|
||||
│ └─────────┘ │
|
||||
│ │
|
||||
│ EMAIL SCHEDULE (Industry Standard - Netflix, Spotify, Adobe): │
|
||||
│ • Payment Success: Receipt immediately │
|
||||
│ • Payment Failed: Notification after each retry attempt │
|
||||
│ • Final Warning: 1 day before account suspension │
|
||||
│ • Account Suspended: When grace period ends │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ RENEWAL TIMELINE - BANK TRANSFER │
|
||||
│ Simplified 3-Email Flow │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Day -3 Day 0 Day +1 Day +7 │
|
||||
│ │ │ │ │ │
|
||||
│ ▼ ▼ ▼ ▼ │
|
||||
│ ┌────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │Invoice │ │Reminder │ │ Urgent │ │ Expired │ │
|
||||
│ │Created │ │ Email │ │Reminder │ │ │ │
|
||||
│ │+Email │ │(if not │ │+Credits │ │ │ │
|
||||
│ │ │ │ paid) │ │ Reset │ │ │ │
|
||||
│ └────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
||||
│ │
|
||||
│ Timeline: │
|
||||
│ • Day -3: Invoice created + Email sent with payment instructions │
|
||||
│ • Day 0: Reminder email (renewal day, if still unpaid) │
|
||||
│ • Day +1: Urgent reminder + credits reset to 0 (if unpaid) │
|
||||
│ • Day +7: Subscription expired │
|
||||
│ │
|
||||
│ EMAILS: │
|
||||
│ 1. Invoice Email (Day -3): Invoice attached, bank details, Pay Now link │
|
||||
│ 2. Renewal Reminder (Day 0): "Your subscription renews today" │
|
||||
│ 3. Urgent Reminder (Day +1): "Payment overdue - action required" │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Renewal Credit Behavior
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ CREDIT RESET ON RENEWAL │
|
||||
├───────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ SCENARIO 1: Payment Before Renewal │
|
||||
│ ───────────────────────────────────── │
|
||||
│ • Credits NOT reset early │
|
||||
│ • On payment confirmation: │
|
||||
│ - plan credits → reset to plan.included_credits │
|
||||
│ - bonus_credits → UNCHANGED (never affected) │
|
||||
│ │
|
||||
│ SCENARIO 2: Payment After Renewal (within 24h) │
|
||||
│ ────────────────────────────────────────────── │
|
||||
│ • Credits stay unchanged for 24 hours │
|
||||
│ • On payment confirmation: │
|
||||
│ - plan credits → reset to plan.included_credits │
|
||||
│ - bonus_credits → UNCHANGED │
|
||||
│ │
|
||||
│ SCENARIO 3: No Payment After 24 Hours │
|
||||
│ ───────────────────────────────────── │
|
||||
│ • plan credits → reset to 0 (task: reset_unpaid_renewal_credits) │
|
||||
│ • bonus_credits → UNCHANGED (user can still use these) │
|
||||
│ • Warning email sent │
|
||||
│ │
|
||||
│ SCENARIO 4: Payment After Credit Reset │
|
||||
│ ────────────────────────────────────── │
|
||||
│ • On payment confirmation: │
|
||||
│ - plan credits → reset to plan.included_credits (restored) │
|
||||
│ - bonus_credits → UNCHANGED │
|
||||
│ │
|
||||
└───────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Celery Tasks Schedule
|
||||
|
||||
| Task | Schedule | Purpose |
|
||||
|------|----------|---------|
|
||||
| `create_bank_transfer_invoices` | Daily 09:00 | Create invoices 3 days before renewal (bank transfer only) |
|
||||
| `process_subscription_renewals` | Daily 00:05 | Process auto-pay renewals (Stripe/PayPal) |
|
||||
| `send_renewal_day_reminders` | Daily 10:00 | Send Day 0 reminder for bank transfer (if unpaid) |
|
||||
| `send_day_after_reminders` | Daily 09:15 | Send Day +1 urgent reminders + reset credits |
|
||||
| `check_expired_renewals` | Daily 00:15 | Mark subscriptions expired after 7-day grace period |
|
||||
| `send_credit_invoice_expiry_reminders` | Daily 09:30 | Remind about expiring credit package invoices |
|
||||
| `void_expired_credit_invoices` | Daily 00:45 | Auto-void credit invoices after 48h |
|
||||
|
||||
### Email Schedule Summary
|
||||
|
||||
**Stripe/PayPal (Auto-Pay) - Industry Standard:**
|
||||
| Event | Email |
|
||||
|-------|-------|
|
||||
| Payment Success | ✅ Receipt/Confirmation |
|
||||
| Payment Failed | ⚠️ Retry notification (per attempt) |
|
||||
| Final Warning | 🚨 1 day before suspension |
|
||||
| Account Suspended | ❌ Subscription expired |
|
||||
|
||||
**Bank Transfer (Manual Pay):**
|
||||
| Day | Email |
|
||||
|-----|-------|
|
||||
| Day -3 | 📧 Invoice created + payment instructions |
|
||||
| Day 0 | ⏰ Renewal day reminder (if unpaid) |
|
||||
| Day +1 | 🚨 Urgent reminder + credits reset warning |
|
||||
|
||||
---
|
||||
|
||||
## 8. Admin Operations
|
||||
|
||||
### Webhook Events (Payment Logs)
|
||||
|
||||
**Location:** Admin → Billing → Webhook Events
|
||||
|
||||
| Column | Description |
|
||||
|--------|-------------|
|
||||
| Event ID | Unique ID from Stripe/PayPal |
|
||||
| Provider | STRIPE or PAYPAL badge |
|
||||
| Event Type | e.g., `checkout.session.completed`, `PAYMENT.CAPTURE.COMPLETED` |
|
||||
| Status | Processed ✓, Failed ✗, Pending ⏳ |
|
||||
| Process Time | Actual processing duration |
|
||||
| Created | When webhook received |
|
||||
|
||||
**Actions:**
|
||||
- Mark as processed
|
||||
- Retry processing
|
||||
- View full payload (JSON)
|
||||
|
||||
### Payment Approval (Bank Transfer)
|
||||
|
||||
**Location:** Admin → Billing → Payments
|
||||
|
||||
**Approval Flow:**
|
||||
1. Filter by `status = pending_approval`
|
||||
2. Review `manual_reference` and `manual_notes`
|
||||
3. Check proof of payment upload
|
||||
4. Change status to `succeeded`
|
||||
5. System automatically:
|
||||
- Updates invoice to `paid`
|
||||
- Activates account (if subscription)
|
||||
- Adds credits (plan or bonus based on invoice type)
|
||||
|
||||
### Manual Credit Adjustment
|
||||
|
||||
**Location:** Admin → Billing → Credit Transactions
|
||||
|
||||
**To add credits manually:**
|
||||
1. Go to Account admin
|
||||
2. Edit the account
|
||||
3. Modify `credits` (plan) or `bonus_credits` (purchased)
|
||||
4. Save with note in admin_notes
|
||||
|
||||
**OR use shell:**
|
||||
```python
|
||||
from igny8_core.business.billing.services.credit_service import CreditService
|
||||
|
||||
# Add plan credits
|
||||
CreditService.add_credits(
|
||||
account=account,
|
||||
amount=500,
|
||||
transaction_type='manual',
|
||||
description='Manual adjustment - support ticket #123'
|
||||
)
|
||||
|
||||
# Add bonus credits
|
||||
CreditService.add_bonus_credits(
|
||||
account=account,
|
||||
amount=500,
|
||||
description='Promotional bonus - January 2026'
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. API Reference
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/v1/billing/credits/` | GET | Get credit balance |
|
||||
| `/api/v1/billing/credits/usage/` | GET | Get usage statistics |
|
||||
| `/api/v1/billing/invoices/` | GET | List invoices |
|
||||
| `/api/v1/billing/invoices/{id}/` | GET | Invoice detail |
|
||||
| `/api/v1/billing/invoices/{id}/pdf/` | GET | Download invoice PDF |
|
||||
| `/api/v1/billing/payments/` | GET | List payments |
|
||||
| `/api/v1/billing/plans/` | GET | List available plans |
|
||||
| `/api/v1/billing/subscriptions/` | GET | List subscriptions |
|
||||
| `/api/v1/billing/credit-packages/` | GET | List credit packages |
|
||||
| `/api/v1/billing/purchase/credits/` | POST | Purchase credit package |
|
||||
| `/api/v1/billing/subscribe/` | POST | Subscribe to plan |
|
||||
| `/api/v1/webhooks/stripe/` | POST | Stripe webhook endpoint |
|
||||
| `/api/v1/webhooks/paypal/` | POST | PayPal webhook endpoint |
|
||||
|
||||
### Credit Balance Response
|
||||
|
||||
```json
|
||||
{
|
||||
"credits": 3500,
|
||||
"bonus_credits": 2000,
|
||||
"total_credits": 5500,
|
||||
"credits_used_this_month": 1500,
|
||||
"plan_credits_per_month": 5000,
|
||||
"subscription_plan": "Scale",
|
||||
"period_end": "2026-02-12T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Database Schema
|
||||
|
||||
### Core Tables
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ accounts │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ id │ PK │
|
||||
│ name │ Account name │
|
||||
│ status │ pending, active, expired, etc. │
|
||||
│ credits │ Plan credits (resets on renewal) │
|
||||
│ bonus_credits │ Purchased credits (never expire) │
|
||||
│ plan_id │ FK → plans │
|
||||
│ billing_email │ Email for invoices │
|
||||
│ billing_country │ Country code (PK, US, etc.) │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ subscriptions │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ id │ PK │
|
||||
│ account_id │ FK → accounts │
|
||||
│ plan_id │ FK → plans │
|
||||
│ status │ pending, active, pending_renewal, expired, etc. │
|
||||
│ current_period_start │ Start of current billing period │
|
||||
│ current_period_end │ End of current billing period (renewal date) │
|
||||
│ metadata │ JSON (stripe_subscription_id, paypal_sub_id) │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ invoices │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ id │ PK │
|
||||
│ invoice_number │ Unique invoice number (INV-2026-00001) │
|
||||
│ account_id │ FK → accounts │
|
||||
│ subscription_id │ FK → subscriptions (nullable) │
|
||||
│ invoice_type │ subscription, credit_package, addon, custom │
|
||||
│ status │ draft, sent, pending, paid, overdue, void, etc. │
|
||||
│ total_amount │ Total amount │
|
||||
│ currency │ USD, PKR │
|
||||
│ due_date │ Payment due date │
|
||||
│ paid_at │ When payment received │
|
||||
│ metadata │ JSON (credit_package_id, etc.) │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ payments │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ id │ PK │
|
||||
│ invoice_id │ FK → invoices │
|
||||
│ account_id │ FK → accounts │
|
||||
│ amount │ Payment amount │
|
||||
│ currency │ USD, PKR │
|
||||
│ payment_method │ stripe, paypal, bank_transfer │
|
||||
│ status │ pending_approval, processing, succeeded, failed│
|
||||
│ stripe_payment_intent_id│ Stripe reference │
|
||||
│ paypal_order_id │ PayPal reference │
|
||||
│ manual_reference │ Bank transfer reference │
|
||||
│ approved_by_id │ FK → users (admin who approved) │
|
||||
│ approved_at │ When approved │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ credit_transactions │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ id │ PK │
|
||||
│ account_id │ FK → accounts │
|
||||
│ transaction_type │ subscription, purchase, usage, refund, manual, etc. │
|
||||
│ amount │ Credits added (+) or deducted (-) │
|
||||
│ balance_after │ Balance after this transaction │
|
||||
│ description │ Human-readable description │
|
||||
│ metadata │ JSON (invoice_id, payment_id, etc.) │
|
||||
│ created_at │ Timestamp │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ webhook_events │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ id │ PK │
|
||||
│ event_id │ Unique event ID from provider │
|
||||
│ provider │ stripe, paypal │
|
||||
│ event_type │ checkout.session.completed, PAYMENT.CAPTURE.COMPLETED │
|
||||
│ payload │ JSON - full webhook payload │
|
||||
│ processed │ Boolean - successfully processed? │
|
||||
│ processed_at │ When processed │
|
||||
│ error_message│ Error if processing failed │
|
||||
│ retry_count │ Number of retry attempts │
|
||||
│ created_at │ When received │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Card
|
||||
|
||||
### Credit Consumption Priority
|
||||
1. **Plan credits** used first
|
||||
2. **Bonus credits** used only when plan credits = 0
|
||||
|
||||
### What Happens on Renewal
|
||||
|
||||
| Event | Plan Credits | Bonus Credits |
|
||||
|-------|--------------|---------------|
|
||||
| Payment success | Reset to plan amount | No change |
|
||||
| No payment (24h) | Reset to 0 | No change |
|
||||
| Late payment | Reset to plan amount | No change |
|
||||
|
||||
### Payment Method Availability
|
||||
|
||||
| Country | Stripe | PayPal | Bank Transfer |
|
||||
|---------|--------|--------|---------------|
|
||||
| Pakistan (PK) | ✅ | ❌ | ✅ |
|
||||
| Others | ✅ | ✅ | ❌ |
|
||||
|
||||
### Invoice Expiry
|
||||
|
||||
| Invoice Type | Expiry |
|
||||
|--------------|--------|
|
||||
| Subscription | 7 days (grace period) |
|
||||
| Credit Package | 48 hours |
|
||||
|
||||
---
|
||||
|
||||
*Document generated from current codebase implementation as of January 20, 2026*
|
||||
196
docs/90-REFERENCE/BILLING-SYSTEM-MASTER.md
Normal file
196
docs/90-REFERENCE/BILLING-SYSTEM-MASTER.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# IGNY8 Billing System Master Document
|
||||
|
||||
**Last Updated:** 2026-01-20
|
||||
|
||||
This document is the authoritative reference for the billing system implementation, including models, invoice lifecycle, payment flows, credit reset logic, and notification timing.
|
||||
|
||||
---
|
||||
|
||||
## 1) Core Principles
|
||||
|
||||
- **No hardcoded products**: Plans, credit packages, and future add-ons are data-driven.
|
||||
- **Explicit invoice type**: `subscription`, `credit_package`, `addon`, `custom`.
|
||||
- **Correct crediting**:
|
||||
- Subscription credits reset to **0** at cycle end.
|
||||
- Subscription credits reset to **full plan amount** on renewal/activation.
|
||||
- Credit package credits add to balance.
|
||||
- **Lifecycle governance**: Credit invoices expire automatically and can be cancelled by users.
|
||||
- **Auditability**: Every credit change is recorded in `CreditTransaction`.
|
||||
|
||||
---
|
||||
|
||||
## 2) Data Model Overview
|
||||
|
||||
### 2.1 Invoice
|
||||
| Field | Purpose |
|
||||
|---|---|
|
||||
| `invoice_type` | `subscription`, `credit_package`, `addon`, `custom` |
|
||||
| `status` | `draft`, `pending`, `paid`, `void`, `uncollectible` |
|
||||
| `expires_at` | Expiry for credit invoices |
|
||||
| `void_reason` | Cancellation/expiration reason |
|
||||
| `line_items` | Itemized charges (product‑driven) |
|
||||
| `metadata` | Compatibility + gateway context |
|
||||
|
||||
### 2.2 Payment
|
||||
| Field | Purpose |
|
||||
|---|---|
|
||||
| `status` | `pending_approval`, `succeeded`, `failed`, `refunded` |
|
||||
| `payment_method` | `stripe`, `paypal`, `bank_transfer`, `local_wallet`, `manual` |
|
||||
| `invoice` | FK to invoice |
|
||||
| `metadata` | Gateway and fulfillment details |
|
||||
|
||||
### 2.3 Credits
|
||||
| Field | Purpose |
|
||||
|---|---|
|
||||
| `Account.credits` | Current balance |
|
||||
| `CreditTransaction` | Immutable ledger of changes |
|
||||
|
||||
---
|
||||
|
||||
## 3) Invoice Types and Fulfillment Rules
|
||||
|
||||
| Invoice Type | Fulfillment | Account Status Change |
|
||||
|---|---|---|
|
||||
| `subscription` | Reset credits to plan amount | Activate account + subscription |
|
||||
| `credit_package` | Add package credits | No status change |
|
||||
| `addon` | Provision add-on entitlement | No status change |
|
||||
| `custom` | No credits unless specified | No status change |
|
||||
|
||||
---
|
||||
|
||||
## 4) Flowcharts
|
||||
|
||||
### 4.1 Subscription Purchase (Stripe / PayPal / Bank Transfer)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[User selects plan] --> B[Create subscription invoice]
|
||||
B --> C{Payment Method}
|
||||
C -->|Stripe/PayPal| D[Gateway checkout]
|
||||
D --> E[Webhook payment succeeded]
|
||||
E --> F[Invoice paid]
|
||||
F --> G[Reset credits to full plan amount]
|
||||
G --> H[Account + subscription active]
|
||||
|
||||
C -->|Bank Transfer| I[User submits confirmation]
|
||||
I --> J[Payment pending_approval]
|
||||
J --> K[Admin approves]
|
||||
K --> F
|
||||
```
|
||||
|
||||
### 4.2 Subscription Renewal (Automatic + Manual)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Billing cycle end] --> B[Reset credits to 0]
|
||||
B --> C[Create renewal invoice]
|
||||
C --> D{Auto method available?}
|
||||
D -->|Yes| E[Gateway charges]
|
||||
E --> F[Webhook payment succeeded]
|
||||
F --> G[Reset credits to full plan amount]
|
||||
G --> H[Subscription active]
|
||||
|
||||
D -->|No| I[Manual payment required]
|
||||
I --> J[Invoice emailed]
|
||||
J --> K[Admin approves]
|
||||
K --> G
|
||||
```
|
||||
|
||||
### 4.3 Credit Package Purchase (All Methods)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[User selects credit package] --> B[Create credit invoice + expires_at]
|
||||
B --> C{Payment Method}
|
||||
C -->|Stripe/PayPal| D[Gateway checkout]
|
||||
D --> E[Webhook payment succeeded]
|
||||
E --> F[Add package credits]
|
||||
|
||||
C -->|Bank Transfer| G[User submits confirmation]
|
||||
G --> H[Payment pending_approval]
|
||||
H --> I[Admin approves]
|
||||
I --> F
|
||||
```
|
||||
|
||||
### 4.4 Credit Invoice Expiry
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Scheduler checks pending credit invoices] --> B{expires_at <= now?}
|
||||
B -->|Yes| C[Void invoice + notify user]
|
||||
B -->|No| D[No action]
|
||||
```
|
||||
|
||||
### 4.5 Credit Invoice Cancellation (User)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[User clicks cancel] --> B{Pending credit invoice?}
|
||||
B -->|Yes| C[Set status=void, void_reason=user_cancelled]
|
||||
C --> D[Notify user]
|
||||
B -->|No| E[Reject request]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5) Notification Matrix (Required Emails)
|
||||
|
||||
| Event | Email | Timing |
|
||||
|---|---|---|
|
||||
| Manual payment submitted | Payment confirmation | Immediate |
|
||||
| Manual payment approved | Payment approved | Immediate |
|
||||
| Manual payment rejected | Payment rejected | Immediate |
|
||||
| Renewal notice | Subscription renewal notice | N days before end |
|
||||
| Renewal invoice | Invoice email | At renewal creation |
|
||||
| Renewal reminder | Invoice reminder | Every 3 days until paid |
|
||||
| Credit invoice expiring | Credit invoice expiring | 24h before expires_at |
|
||||
| Credit invoice expired | Credit invoice expired | At void |
|
||||
| Credit invoice cancelled | Credit invoice cancelled | Immediate |
|
||||
| Payment failed | Payment failed | Immediate |
|
||||
| Low credits | Low credits warning | Threshold crossing |
|
||||
| Subscription expired | Subscription expired | When grace period ends |
|
||||
|
||||
---
|
||||
|
||||
## 6) Scheduled Tasks
|
||||
|
||||
| Task | Purpose | Schedule |
|
||||
|---|---|---|
|
||||
| send_renewal_notices | Renewal reminders | Daily 09:00 |
|
||||
| process_subscription_renewals | Create renewal invoices | Daily 00:05 |
|
||||
| send_invoice_reminders | Remind pending renewals | Daily 10:00 |
|
||||
| check_expired_renewals | Expire grace period | Daily 00:15 |
|
||||
| send_credit_invoice_expiry_reminders | Credit invoice expiry reminder | Daily 09:30 |
|
||||
| void_expired_credit_invoices | Auto-void expired credit invoices | Daily 00:45 |
|
||||
| replenish_monthly_credits | Monthly credit reset (legacy) | 1st day monthly |
|
||||
|
||||
---
|
||||
|
||||
## 7) Key Implementation Rules
|
||||
|
||||
1. **Invoice type drives fulfillment** (no plan/package hardcoding).
|
||||
2. **Subscription credits**: reset to **0** at cycle end, then set to **full amount** on renewal.
|
||||
3. **Credit packages**: add package credits only.
|
||||
4. **Credit invoices**: expire automatically and are cancellable by users.
|
||||
5. **Account status** only changes on **subscription invoices**.
|
||||
|
||||
---
|
||||
|
||||
## 8) Operational Verification Checklist
|
||||
|
||||
- Stripe/PayPal subscription purchase activates account and resets credits.
|
||||
- Bank transfer subscription approval resets credits (not adds).
|
||||
- Credit package approval adds package credits (not plan credits).
|
||||
- Credit invoices do not block subscription state.
|
||||
- Credit invoice expiry and cancellation work with emails.
|
||||
- Renewal resets credits to 0 at cycle end and to full on payment.
|
||||
|
||||
---
|
||||
|
||||
## 9) Extensibility (Future Add‑ons)
|
||||
|
||||
- Add new `Product` types without code changes to invoice fulfillment.
|
||||
- Use `invoice_type='addon'` with line items to provision entitlements.
|
||||
- No plan/package hardcoding required.
|
||||
|
||||
---
|
||||
|
||||
## 10) References
|
||||
|
||||
- Audit: [docs/audits/BILLING-SYSTEM-AUDIT-20260120.md](docs/audits/BILLING-SYSTEM-AUDIT-20260120.md)
|
||||
- Refactor Plan: [docs/audits/BILLING-SYSTEM-AUDIT-AND-REFACTOR-PLAN-20260120.md](docs/audits/BILLING-SYSTEM-AUDIT-AND-REFACTOR-PLAN-20260120.md)
|
||||
Reference in New Issue
Block a user