Files
igny8/docs/10-MODULES/BILLING-PAYMENTS-COMPLETE.md
IGNY8 VPS (Salman) 257b6817f1 Version 1.9.0
2026-01-20 07:58:48 +00:00

757 lines
49 KiB
Markdown

# 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 │
└───────────────┘ └────────────────────┘
```
> **Note:** The two-pool logic is internal to `CreditService.deduct_credits()`. All AI functions and other credit consumers are unaffected - they call the same credit check/deduct methods as before.
### 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: send_day_after_reminders) │
│ • 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*