Skip to content

Reseller Payouts — Production Guide

Licensing

  • Catalog slug: reseller-payouts
  • Category: sales (Sales), category_sort_order = 20, module sort_order = 80
  • Free Marketplace opt-in (is_default_included = false, is_billable = false, price 0)
  • Hard dependency: Resellers (which itself requires Payments)
  • Marketplace blocks install until Resellers is entitled

Bootstrap

  1. Ensure Resellers (and Payments) are entitled first
  2. Enable Reseller Payouts from Marketplace
  3. Permissions via 2026_08_06_100007_add_reseller_payouts_permissions

Without Reseller Payouts entitlement, invoice Paid transitions do not create commission rows (listeners no-op after entitlement check).

Schema migrations

MigrationPurpose
2026_08_06_100002_create_reseller_commission_entries_tableledger + unique (customer_invoice_id, party)
2026_08_06_100006_register_reseller_payouts_modulecatalog via DefaultModuleRegistrar
2026_08_06_100008_add_reseller_payouts_resellers_dependencyhard dep → resellers

Event wiring

AppServiceProvider:

  • CustomerInvoiceBecamePaidAccrueResellerCommission
  • CustomerInvoiceLeftPaidVoidResellerCommission

Transitions are dispatched from CustomerInvoicePaidTransitions after invoice status recalculation (Payments post/void paths included).

Monitoring

  • Spatie activity log name: reseller_commission_entries
  • Track accrue/approve/pay/void volume via application logs / Nightwatch as needed

Deploy checklist

  1. Migrate commission table + catalog + permissions + Resellers dependency
  2. Confirm module:reseller-payouts + reseller-payouts.* on admin/manager/staff/reseller maps
  3. Confirm listeners registered in deployed app container
  4. Smoke: Paid invoice with reseller_id → two accrued rows → approve → pay; void invoice payment → entries voided; re-post payment → entries revived to accrued
  5. Confirm Partial invoices do not accrue

Finance runbook — invoice leaves Paid

Leaving Paid (CustomerInvoiceLeftPaid, typically from voiding a posted payment) calls voidForInvoice, which bulk-voids every non-void commission row for that invoice — including entries already marked paid.

This is intentional Phase 1 behavior so the ledger cannot stay “settled” against an unpaid invoice:

SituationResult
Accrued / approved entry, invoice unpaysStatus → void
Manually marked paid entry, invoice unpaysStatus → void (finance must treat as cancelled settlement)
Invoice becomes Paid againVoid rows for that invoice are revived to accrued with refreshed amount snapshots

Ops guidance: If commissions were already disbursed outside the app before a payment void, reverse or reclaim that disbursement in your payroll/AP process — EloSync marks the ledger void but does not move money. Manual Void on a single entry still rejects rows that are already paid while the invoice remains Paid.

Deferred

No automated disbursement gateway in Phase 1 — pay is ledger status only. Cross-workspace identity for parties remains deferred.

Official documentation for the EloSync SaaS Platform.