Skip to content

Cash Collection

Cash Collection is ProxPanel’s answer to the reality of small-ISP economics: the customer often pays in cash, in person, at the end of the month. A collector is a special user who walks a route, knocks on doors, takes cash, marks invoices paid in a mobile-friendly dashboard, and earns commission. This page covers the admin/reseller side: creating collector accounts, building their daily route via assignments, monitoring outcomes, and paying commission.

The collector’s own login lands on a stripped-down dashboard with only the routes they have been given — they cannot see other subscribers, edit plans, or change prices.

  • SidebarCash Collection (cash icon).
  • Direct URL: /collectors.
  • A collector signs in at the same login URL; the system detects their user_type = collector and routes them to /my-collections.

Visible to admins and to resellers who hold collectors.view. The Cash Collection page in SaaS mode is per-tenant — each ISP manages its own collectors.

The page has three views, switchable via the top tabs:

TabWhat it shows
CollectorsList of collector accounts with their commission rate, monthly stats, and active assignment counts.
AssignmentsAll open assignments — invoices given to a collector but not yet marked paid or failed.
ReportsPer-collector breakdown: assigned, collected, failed, total cash in, commission earned.

A collector is a row in users with user_type = 'collector'. They have:

  • A login (username + password).
  • A display name and phone (printed on the receipt the subscriber gets).
  • A commission percentage — the cut they earn on every invoice they personally collect.
  • An optional reseller scope — when set, the collector can only be assigned invoices belonging to that reseller’s subscribers. Useful when a reseller has their own field staff.

Create one from the Collectors tab → + New Collector. Reset their password from the same row. Soft-deleting a collector ends their access but leaves their historical collections and commission ledger intact.

POST /api/collectors/:id/assignments builds the collector’s daily route. The handler accepts a list of invoice IDs and, for each one:

  1. Verifies the invoice is pending or partial — paid invoices can’t be assigned.
  2. Verifies it isn’t already on another collector’s open route (the same invoice cannot be in two routes simultaneously).
  3. Creates a collection_assignments row with status assigned.
  4. Records who assigned it, when, and any notes (door code, preferred time, language).

You can assign in bulk from the Invoices page: filter unpaid invoices by area or reseller, multi-select, then Bulk → Assign to Collector.

DeleteAssignment removes an unsuccessful assignment so a different collector can pick it up — this does not change the invoice itself.

A collector signs in on their phone or tablet. Their dashboard (MyDashboard handler) shows:

  • Today’s total to collect (sum of assigned invoice balances).
  • Today’s already-collected amount and commission accrued.
  • A list of stops — each card has the subscriber’s name, phone (one-tap to call), address, amount due, and an open map link to their stored coordinates.

MyAssignments returns the full route ordered by reseller area then street so collectors don’t zig-zag.

MarkCollected is the workhorse:

  1. Validates the assignment is still assigned (not already paid or failed).
  2. Records the cash amount taken, payment method (cash is the default), and an optional photo of the receipt.
  3. Posts a payment row on the underlying invoice — if the amount equals the balance, the invoice flips to paid; if less, to partial.
  4. Creates a transaction row with type='renewal' (or 'new' for first-month payments) and collector_id set, so commission reports can attribute it.
  5. Auto-renew: if the invoice was for a renewal and the customer is now paid in full, autoRenewSubscriber() extends the subscriber’s expiry date and resets daily FUP counters. The customer is back online before the collector reaches the next door.
  6. The collector’s commission ledger is credited with amount × collector.commission_percent / 100.
  7. If WhatsApp is configured, a receipt PDF is sent to the subscriber automatically (see WhatsApp receipts below).
  8. Assignment status moves to collected.

Doors don’t always open. MarkFailed lets the collector record what went wrong:

  • not_home — no one answered.
  • refused — customer declined to pay.
  • wrong_address.
  • disconnected — phone says number is dead.
  • other — free-text required.

The assignment moves to failed status. By default the system reschedules it for 2 days out — it reappears on tomorrow-but-one’s route. This window is configurable per panel in Settings → Billing. If the customer is repeatedly failed, the admin sees a flag on the invoice and can switch to bulk Disconnect to apply pressure.

If WhatsApp is configured in Communication Rules, MarkCollected triggers an automatic receipt:

  1. The invoice PDF is regenerated (now showing the payment as posted).
  2. The Ultramsg gateway sends it to the subscriber’s stored phone number.
  3. The message text comes from the Collector Receipt template — typically a thank-you plus the new expiry date.
  4. Delivery status is appended to invoice.notification_log so you can see if it landed.

If the gateway is down, the payment still posts — the receipt is best-effort. The audit log records the failure.

CollectorReport produces a per-period breakdown. For a date range (default: month-to-date):

ColumnSource
Collectorusers.full_name
Stopscount of collection_assignments with created_at in range
Collectedcount where status='collected'
Failedcount where status='failed'
Success ratecollected / stops × 100
Cash collectedsum of amount on collected assignments
Commission earnedcash_collected × commission_percent / 100
Already paid outsum of transactions.type='commission_payout' for this collector
Balanceearned − paid_out

Click Mark Paid on a row to post the commission payout — the collector’s ledger zeroes out and the transaction is in the audit trail under your username.

  1. Open the Invoices page, filter status = pending and area = the collector’s zone.
  2. Select all relevant rows (typically 30–60 stops).
  3. Bulk action → Assign to Collector → pick the collector.
  4. Click into the collector → confirm the Assignments count reflects the additions.
  5. WhatsApp the collector their route URL.
  1. Reports tab → choose today, pick the collector.
  2. The page shows total cash collected and how many stops failed. Compare against the cash the collector hands you.
  3. Discrepancy? Drill into individual assignments — the photo and timestamp on each payment is your evidence.
  4. Once reconciled, click Mark Commission Paid to clear the commission balance and post the payout transaction.

Investigate why a customer says “I paid your guy”

Section titled “Investigate why a customer says “I paid your guy””
  1. Open the subscriber → Billing tab → look at the invoice in question.
  2. If a payment is posted with collector_id set, the collector did mark it. Check the timestamp and the photo attached.
  3. If no payment is recorded, search Assignments → Failed in the same window — the collector may have marked it failed.
  4. Audit log (under Audit) shows every action the collector took, with IP and user-agent, so you can prove what happened.
PermissionWhat it gates
collectors.viewSee the Collectors list, Assignments, and Reports.
collectors.createAdd collector accounts and set commission rates.
collectors.editEdit a collector’s profile and reset their password.
collectors.assignAssign and unassign invoices on routes.
collectors.deleteSoft-delete a collector account.
collectors.commission_payMark commission balances as paid out.

Collectors themselves do not need explicit permissions — their user_type automatically restricts them to /my-collections and the related endpoints.

  • Billing & Invoices — invoices that feed into routes.
  • Subscribers — addresses, phone numbers, and stored coordinates collectors rely on.
  • Communication Rules — WhatsApp template for collector receipts.
  • Reports — system-wide revenue rolls up cash collected through collectors.
  • Audit Logs — every collector action is recorded with IP and timestamp.