Commission Ledger Setup

Configure salesperson commission plans, project splits, cash-basis posting, adjustments, and historical backfills.

The commission ledger records salesperson commission when customer payments are completed. It replaces report-only commission calculations with permanent, auditable entries.

The system supports:

  • A commission configuration for each salesperson.
  • Percentage-based commission splits between multiple salespeople on a project.
  • Cash-basis commission posting as each payment is received.
  • Positive and negative adjustments with a required reason.
  • An idempotent backfill for completed historical payments.

How Commission Is Calculated

Commission posts when a project payment reaches Completed.

For each payment, Tempr:

  1. Calculates the commissionable portion of the payment.
  2. Divides that amount using the project's salesperson splits.
  3. Resolves each salesperson's commission configuration.
  4. Creates one protected earned ledger entry per salesperson.

The commissionable payment amount is proportional to the project's discounted subtotal:

payment share = payment amount / project grand total
commissionable payment = discounted subtotal * payment share
salesperson base = commissionable payment * project split percentage
commission earned = salesperson base * salesperson commission rate

This keeps commission on a cash basis while excluding the non-commissionable portion of the project total, such as sales tax.

The ledger entry's effective date uses the first available value in this order:

  1. Payment settlement date.
  2. Payment completion timestamp.
  3. Payment creation timestamp.

The split percentage and commission rate are stored on the ledger entry when it posts. Changing a user configuration later affects future payments only; it does not recalculate existing entries.

Available User Configurations

Each user has a commission_configuration value.

ConfigurationStored valueCalculation
Non-commissionednon_commissionedPays no commission.
Flat 3%flat_three_percentAlways pays 3% of the user's commissionable share.
Flat 5.5%flat_five_and_half_percentAlways pays 5.5% of the user's commissionable share.

New users default to non_commissioned. Assign a flat commission configuration only when the user should earn commission.

Initial Deployment

1. Run The Migrations

php artisan migrate

The migrations add:

  • users.commission_configuration
  • project_commission_splits
  • commission_ledger_entries

No additional environment variables are required.

2. Confirm Queue Processing

Automatic commission posting is handled by the queued PostCommissionForCompletedPayment listener. Confirm that the environment's queue worker or Horizon process is running and processing the configured default queue.

php artisan horizon:status

If the application does not use Horizon in that environment, confirm its normal Laravel queue worker is running instead.

A completed payment can dispatch the listener successfully while commission remains unposted if no queue worker processes the job. Monitor failed jobs and queue health after deployment.

3. Assign User Configurations

In the Config panel:

  1. Open /config.
  2. Select Users.
  3. Create or edit the salesperson.
  4. Select a Commission Configuration.
  5. Save the user.

The selected configuration also appears in the Users table under Commission.

The same assignment can be made in application code:

use App\Enums\Commissions\CommissionConfiguration;

$user->assignCommissionConfiguration(
    CommissionConfiguration::FlatFiveAndHalfPercent,
);

4. Configure Project Splits

In the main project profile:

  1. Open the project and select Products.
  2. Open the Actions menu.
  3. Select Commission splits.
  4. Add each salesperson and their project share.
  5. Confirm the percentages total exactly 100%.
  6. Save the splits.

If a project has no explicit splits, commission defaults to 100% for the project's consultant. If the project does not have a consultant, Tempr falls back to the customer's consultant.

Project splits lock after the first payment-backed commission entry posts. Configure historical splits before running the backfill. Corrections after posting must be entered as adjustments.

Backfilling Existing Payments

The backfill posts ledger entries for completed payments that do not already have commission entries.

Before running it:

  1. Assign the correct commission configuration to every salesperson.
  2. Add historical project splits where commission should not go 100% to the project consultant.
  3. Confirm every included project has either valid splits or an assigned project/customer consultant.
  4. Confirm the queue is paused or operational procedures prevent concurrent manual changes to the same commission setup.

Backfill all eligible completed payments:

php artisan commissions:backfill

Limit the backfill by settlement date:

php artisan commissions:backfill --from=2026-01-01 --to=2026-12-31

Both date options are inclusive. Either option can be used by itself.

The command is idempotent: payments with existing commission ledger entries are skipped, and posting the same payment again returns its existing entries. If a backfill stops because one project is not configured, correct that project and rerun the same command.

Do not use a configuration change to correct earned commission that has already posted. Earned entries cannot be edited, so post an adjustment instead.

Reviewing The Ledger

In the Reports panel:

  1. Open /reportal.
  2. Under Sales, select Commission Ledger.
  3. Filter by salesperson or entry type as needed.

Earned entries show the payment, project, commissionable amount, split percentage, snapshotted rate, and commission amount. Adjustment entries show their signed amount and reason.

The commission report also reads from these ledger entries and groups them by salesperson and effective date.

Posting Adjustments

Use an adjustment for salesperson errors, chargebacks, bonuses, or any correction to commission that has already posted.

In the Manage panel:

  1. Open /manage.
  2. Under Sales, select Commission Ledger.
  3. Select Add adjustment.

Enter:

  • The salesperson.
  • A signed dollar amount.
  • The effective date.
  • An optional related project.
  • A required reason.

Use a negative amount to reduce commission and a positive amount to increase it.

Examples:

ScenarioAdjustment
$125.50 chargeback for a measurement error-125.50
$200 discretionary bonus200.00

Manual adjustments can be edited from the same Manage-panel ledger if their salesperson, amount, effective date, project, or reason needs correction. Payment-earned entries cannot be edited, and no ledger entries can be deleted.

Operational Rules

  • Only Completed payments generate earned commission.
  • Non-project payments do not generate commission entries.
  • Each payment can create at most one earned entry for each salesperson.
  • Project splits must contain unique users and total exactly 100%.
  • Deleted users remain visible on historical ledger entries.
  • Deleting a project or payment does not delete its historical commission amount; the related reference becomes null where allowed.
  • Commission adjustments affect commission totals but do not change a salesperson's configured percentage.

Adding A Future Configuration

Commission formulas are separated behind App\Contracts\Commissions\CommissionRateConfiguration.

To add another variation:

  1. Create a rate configuration class that implements rateForCommissionableAmount(int $commissionableAmount): float.
  2. Add a backed case to App\Enums\Commissions\CommissionConfiguration.
  3. Add its user-facing label in getLabel().
  4. Resolve the new strategy from rateConfiguration().
  5. Add tests for the rate boundaries and mixed project splits.

The enum automatically supplies options to the user administration selector, so a new case does not require a database schema change.

For example, a future configuration could support a flat rate with a threshold, a project-type-specific rate, or another formula while retaining the same ledger and user assignment workflow.

Troubleshooting

A Completed Payment Has No Ledger Entry

Check:

  • The queue worker or Horizon is running.
  • The listener job is not in the failed jobs table.
  • The payment belongs to a project.
  • The project has valid splits or an assigned consultant.
  • The payment state is actually Completed.

After correcting the setup, retry the failed job or run the date-scoped backfill.

The Commission Splits Action Is Disabled

The action requires project financial access and project update access. If it is visible but disabled, either the user cannot update the project or at least one payment-backed commission entry has already posted. Posted splits are intentionally locked; use a signed adjustment to correct the salesperson's balance.

A User's New Rate Did Not Change An Old Entry

This is expected. The ledger snapshots the rate at posting time, and earned entries cannot be edited. The new configuration applies to future completed payments only.

The Backfill Stops On A Project

The project likely has no usable salesperson or its explicit splits do not total 100%. Correct the project setup, then rerun the command. Already-posted payments will be skipped.