Commission rates & two-tier hierarchy
Commission rates & two-tier hierarchy
This guide explains how the rates work, when each rate triggers, and how the parent's "indirect" commission is calculated.
Rate types
Every reseller has 4 rate fields, stored in mod_reseller_admins:
| Field | When it applies | Whose orders |
|---|---|---|
new_order_rate | Customer's first paid invoice | The reseller's own customers |
renewal_rate | Any subsequent paid invoice (renewals) | The reseller's own customers |
indirect_new_order_rate | Customer's first paid invoice | The reseller's downline's customers |
indirect_renewal_rate | Renewal paid invoice | The reseller's downline's customers |
Rates are percentages of the invoice total amount (after tax, including the invoice's full balance). All percentages stored with 2 decimal places, range 0–100%.
Two-tier example
Setup: - Reseller A (top tier) — new_order_rate=5, renewal_rate=3, indirect_new_order_rate=2, indirect_renewal_rate=1 - Reseller B (downline of A) — new_order_rate=8, renewal_rate=5, indirect rates 0/0
Customer of A pays a $100 first-time invoice: - A earns: $100 × 5% = $5 (level=1, direct) - B earns: nothing (B is not A's parent)
Customer of B pays a $100 first-time invoice: - B earns: $100 × 8% = $8 (level=1, direct) - A earns: $100 × 2% = $2 (level=2, indirect, using A's indirect_new_order_rate)
Note: the indirect rate is taken from the parent's record, not the downline's. So A controls how much it earns on B's orders.
When commissions are recorded
The InvoicePaid WHMCS hook runs on every paid invoice. The hook: 1. Looks up the customer's assigned reseller. 2. If found, calculates direct commission (level=1, using new_order_rate or renewal_rate). 3. If the reseller has a parent, calculates indirect commission (level=2, using parent's indirect_*_rate). 4. Inserts records into mod_reseller_commissions with status pending and idempotency guarded by a UNIQUE key on (invoice_id, admin_id, level).
The UNIQUE key means re-firing InvoicePaid on the same invoice never creates duplicate commission rows.
Customer assignment determines direct commission
A commission is only created if the paid invoice's customer is assigned to a reseller (mod_reseller_customers.admin_id IS NOT NULL). If the customer is in the pool (no admin_id), no commission is created on that invoice — even if the order amount is non-zero.
To retroactively assign: have the reseller claim from Customer Pool, or assign via admin Customer Pool view.
Editing rates after the fact
Changing a rate only affects future commission calculations. Existing commission records in the table are not recalculated. If you need to backfill, the easiest path is to manually update the row in the Commissions tab.
Cycle protection
The parent dropdown enforces: - A reseller cannot pick themselves. - A reseller cannot pick someone who is already their downline (no cycles).
Attempting either via direct POST also fails server-side with an audit log entry.