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.
How to get here
Section titled “How to get here”- Sidebar → Cash Collection (cash icon).
- Direct URL:
/collectors. - A collector signs in at the same login URL; the system detects their
user_type = collectorand 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.
Layout
Section titled “Layout”The page has three views, switchable via the top tabs:
| Tab | What it shows |
|---|---|
| Collectors | List of collector accounts with their commission rate, monthly stats, and active assignment counts. |
| Assignments | All open assignments — invoices given to a collector but not yet marked paid or failed. |
| Reports | Per-collector breakdown: assigned, collected, failed, total cash in, commission earned. |
Collector accounts
Section titled “Collector accounts”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.
Assigning invoices
Section titled “Assigning invoices”POST /api/collectors/:id/assignments builds the collector’s daily route. The handler accepts a list of invoice IDs and, for each one:
- Verifies the invoice is
pendingorpartial— paid invoices can’t be assigned. - Verifies it isn’t already on another collector’s open route (the same invoice cannot be in two routes simultaneously).
- Creates a
collection_assignmentsrow with statusassigned. - 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.
The collector’s day
Section titled “The collector’s day”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.
Mark Collected
Section titled “Mark Collected”MarkCollected is the workhorse:
- Validates the assignment is still
assigned(not already paid or failed). - Records the cash amount taken, payment method (
cashis the default), and an optional photo of the receipt. - Posts a payment row on the underlying invoice — if the amount equals the balance, the invoice flips to
paid; if less, topartial. - Creates a
transactionrow withtype='renewal'(or'new'for first-month payments) andcollector_idset, so commission reports can attribute it. - 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. - The collector’s commission ledger is credited with
amount × collector.commission_percent / 100. - If WhatsApp is configured, a receipt PDF is sent to the subscriber automatically (see WhatsApp receipts below).
- Assignment status moves to
collected.
Mark Failed
Section titled “Mark Failed”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.
WhatsApp receipts
Section titled “WhatsApp receipts”If WhatsApp is configured in Communication Rules, MarkCollected triggers an automatic receipt:
- The invoice PDF is regenerated (now showing the payment as posted).
- The Ultramsg gateway sends it to the subscriber’s stored phone number.
- The message text comes from the Collector Receipt template — typically a thank-you plus the new expiry date.
- Delivery status is appended to
invoice.notification_logso 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.
Commission reports
Section titled “Commission reports”CollectorReport produces a per-period breakdown. For a date range (default: month-to-date):
| Column | Source |
|---|---|
| Collector | users.full_name |
| Stops | count of collection_assignments with created_at in range |
| Collected | count where status='collected' |
| Failed | count where status='failed' |
| Success rate | collected / stops × 100 |
| Cash collected | sum of amount on collected assignments |
| Commission earned | cash_collected × commission_percent / 100 |
| Already paid out | sum of transactions.type='commission_payout' for this collector |
| Balance | earned − 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.
Common workflows
Section titled “Common workflows”Build today’s route for a collector
Section titled “Build today’s route for a collector”- Open the Invoices page, filter
status = pendingand area = the collector’s zone. - Select all relevant rows (typically 30–60 stops).
- Bulk action → Assign to Collector → pick the collector.
- Click into the collector → confirm the Assignments count reflects the additions.
- WhatsApp the collector their route URL.
Reconcile end-of-day cash
Section titled “Reconcile end-of-day cash”- Reports tab → choose today, pick the collector.
- The page shows total cash collected and how many stops failed. Compare against the cash the collector hands you.
- Discrepancy? Drill into individual assignments — the photo and timestamp on each payment is your evidence.
- 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””- Open the subscriber → Billing tab → look at the invoice in question.
- If a payment is posted with
collector_idset, the collector did mark it. Check the timestamp and the photo attached. - If no payment is recorded, search Assignments → Failed in the same window — the collector may have marked it failed.
- Audit log (under Audit) shows every action the collector took, with IP and user-agent, so you can prove what happened.
Permissions
Section titled “Permissions”| Permission | What it gates |
|---|---|
collectors.view | See the Collectors list, Assignments, and Reports. |
collectors.create | Add collector accounts and set commission rates. |
collectors.edit | Edit a collector’s profile and reset their password. |
collectors.assign | Assign and unassign invoices on routes. |
collectors.delete | Soft-delete a collector account. |
collectors.commission_pay | Mark 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.
Related pages
Section titled “Related pages”- 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.