Skip to content

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:

FieldWhen it appliesWhose orders
new_order_rateCustomer's first paid invoiceThe reseller's own customers
renewal_rateAny subsequent paid invoice (renewals)The reseller's own customers
indirect_new_order_rateCustomer's first paid invoiceThe reseller's downline's customers
indirect_renewal_rateRenewal paid invoiceThe 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.