CRMconnect Azuvio · Docs

Workflow: Sales Agent Commission

Modules involved: Invoices · Payments · Commission (Policy · Applicable Staff · Hierarchy · Receipt) · Sales Agent · Goals · DataPulse
Who uses it: Sales Manager · Sales Agents · Finance Administrator
Typical duration: Instantaneous after invoice payment (automatic trigger) + monthly cycle for commission payout

Overview

The Commission module automatically calculates the commission owed to a sales agent the moment an invoice is paid. No manual action is required for the actual calculation — everything is triggered by the after_payment_added hook. The full workflow covers: commission policy configuration, assigning agents to policies, automatic calculation upon payment, viewing accumulated commissions, and actual payout through issuing a Commission Receipt.

Note: Commission is calculated only on standard CRM invoices (tblinvoices). Invoices from the Sales Agent module (sa_sale_invoices) do not trigger commission.


Flow diagram

[CONFIGURATION — once only]
  │
  ├── Commission Policy (type 1–5, date range, percentage/scale)
  ├── Applicable Staff → assign agent to policy
  ├── Hierarchy (optional) → coordinator receives % of agent's commission
  └── General options → calculate_after_days · payment_trigger_mode
  │
  ↓
[INVOICING]
  │
  ├── Invoice created → sale_agent set on invoice (or on client/group)
  └── Invoice status: Draft → Sent
  │
  ↓
[INVOICE PAYMENT — automatic trigger]
  │
  ├── Payment recorded → after_payment_added hook fires
  ├── System checks: invoice age ≥ calculate_after_days?
  ├── System checks: payment_trigger_mode?
  │     'partial_allowed' (default) → any payment > 0 generates commission
  │     'full_only' → commission only if sum of payments = invoice total
  ├── System checks: invoice eligible? (not voided, valid status)
  └── System resolves agent: sale_agent on invoice → customer_admin of client
        → commission_salesadmin_group (client group → agent)
  │
  ↓
[COMMISSION GENERATED]
  │
  ├── Row created in tblcommission: staffid, invoice_id, amount, paid=0
  ├── Types 1–4: calculated immediately per invoice
  └── Type 5 (monthly/margin): calculated by cron on commission_month_close_day
  │
  ↓
[APPROVAL / VIEWING]
  │
  ├── Manager → /admin/commission → sees commissions with paid=0
  ├── Agent → sees their own commissions (permission commission_manage → view)
  └── Reports: commission_chart · staff_monthly_dashboard
  │
  ↓
[COMMISSION PAYOUT]
  │
  ├── Manager creates Commission Receipt: selects unpaid commissions
  ├── Receipt can be converted to Expense (for accounting records)
  └── Selected commissions → paid=1 in tblcommission
  │
  ↓
[COMMISSION PAID ✓]

Step by step

1. Initial configuration (admin)

1a. Commission policy

Where: /admin/commission → Commission Policy → New Policy

There are 5 policy types (commission_policy_type):

Type Name How it works
1 Ladder — invoice total Different percentages on value tiers of the total invoice
2 Flat percentage Fixed percentage applied to invoice total (or profit, if amount_to_calculate=1)
3 Per-product with quantity tiers Different percentages per product based on quantity
4 Ladder per product Scale on individual product values
5 Monthly margin (staff monthly) Calculated at month end based on net margin; requires staff_margin_settings JSON

Essential fields when creating:

Field Required Notes
name Yes Descriptive name for the policy
policy_scope Yes vendor (for vendors/clients) or staff (for employees)
from_date / to_date Yes Policy validity range
commission_type Yes percentage or fixed amount
payment_trigger_mode Yes partial_allowed (default) or full_only
calculate_after_days No Days to wait after payment before calculating commission (0 = immediately)
amount_to_calculate No 0 = invoice total, 1 = profit (difference from product cost)
commission_tax_mode No without_tax (default) or with_tax

Important: If calculate_after_days is negative, the system automatically uses 14 days.

1b. Assigning an agent to a policy

Where: /admin/commission → Applicable Staff → Add

Links an employee (staffid) to a policy (commission_policy_id) through the tblcommission_applicable_staff table. An agent can be assigned to multiple policies with different dates.

For vendor/client type commissions: Applicable Client (set is_client=1 and commission_receiver_vendor_id on the client record).

1c. Commission hierarchy (optional)

Where: /admin/commission → Settings → Hierarchy

Allows a coordinator to receive a percentage of the commission of the agent under their supervision:

Field Description
salesman staffid of sales agent
coordinator staffid of coordinator/manager
percent % of agent's commission received by the coordinator

1d. General options

Where: /admin/commission → Settings → Commission General

Option Default value Description
commission_payment_trigger_mode partial_allowed Global (can be overridden per policy)
commission_calculate_after_days 0 Global waiting days
commission_cron_interval_minutes 1440 (24h) Backup cron for commissions missed by hook
commission_month_close_day 1 Day of month on which type-5 is calculated (for previous month)

2. Resolving the agent on an invoice

When an invoice is paid, the system determines the agent in this order:

  1. invoices.sale_agent — agent set directly on the invoice
  2. tblcustomer_admins.staff_id — the client's account admin (if sale_agent is empty)
  3. tblcommission_salesadmin_group — client group → agent mapping (if the first two are empty)

Gotcha: If none of the three is configured, no commission is generated and no alert appears. Always verify that invoices have sale_agent set or that clients have a customer admin.


3. Automatic calculation upon payment

When a payment is recorded (/admin/invoices/:id → Add Payment or via API), the after_payment_added hook calls Commission_model::add_commission($payment_id).

System checks performed (if any fail, commission is NOT generated):

Check Detail
Invoice age Invoice date + calculate_after_days ≤ today
Invoice status Status must NOT be in [5=cancelled, 6=draft, 7=credit note, 8=internal]
Voiding Invoice does not have an associated credit note
Trigger mode If full_only: sum of all payments = invoice total

Fallback cron: Every commission_cron_interval_minutes minutes, a job checks invoices with payments that missed the hook and generates missing commissions.

Manual regeneration (admin):

  • On invoice: Regenerate Commission button
  • Bulk: /admin/commission → Recalculate (requires commission → create permission)

4. Type 5 commissions — Monthly margin

Different from types 1–4: calculation is not done per payment, but monthly via cron.

On day commission_month_close_day of the month (default day 1), run_staff_monthly_commissions() calculates for the previous month:

  • Aggregates all paid invoices from that month per agent
  • Calculates net margin (sales_net, avg_margin, avg_discount)
  • Applies tiers from staff_margin_settings JSON
  • Writes to tblcommission_staff_monthly (status: draft)
  • Writes per-invoice details to tblcommission_staff_monthly_detail

5. Viewing and approving commissions

Where: /admin/commission

Section Who sees it What it shows
Commission List Admin + commission_manage → view All commissions with paid=0
Staff Monthly Dashboard Admin + commission_manage → view Monthly summary per agent, draft status
Commission Chart Admin + commission_manage → view Commission trend charts
Agent (own) Staff with commission_manage → view Their own commissions only

6. Commission payout

Where: /admin/commission → Commission Receipts → New Receipt

Steps:

  1. Select unpaid commissions (paid=0) to include in the payout
  2. Fill in: amount, paymentmode, date, note, transactionid
  3. Save → system marks all selected tblcommission entries with paid=1
  4. Optional: check Convert to Expense to automatically generate an expense in the Expenses module (for accounting records)

Required permissions: commission_receipt → create + commission_receipt → view


Required permissions

Role / Permission Access
Admin Full access to all functions
commission_manage → view View commissions, charts, monthly reports
commission → create Bulk recalculation
commission → view_setting Access to Settings
commission_receipt → view/create/edit/delete Manage payment receipts
commission_applicable_client → view/create/delete Manage applicable clients

Gotchas

Problem Cause Solution
Commission not generated after payment sale_agent missing on invoice, expired policy, or calculate_after_days not met Check sale_agent field on invoice + policy dates + after_days setting
full_only does not generate on partial payment Correct behavior — commission only appears on full payment Switch to partial_allowed if you want commission on each installment
Commission generated twice Both cron and hook ran System checks for an existing row in tblcommission per invoice_id+staffid before insert — duplicate is blocked
Agent does not appear in Applicable Staff dropdown User does not have active Staff role Verify that the user is an active Staff member in the system
Type-5 not calculated commission_month_close_day has not passed or cron has not run Check the day setting and verify CRM cron is active (/admin/misc/cron_jobs)

Module references