Skip to content

PBX Admin

PBX Admin is the operator-side administration surface for Lubb's telephony backend — a FusionPBX-based switch ("the pbx box") that carries every tenant's calls. Instead of a separate admin site, it renders that box's own admin screens (gateways, SIP trunking, DID inventory, dialplans, conferences, extensions, call records) inside Lubb's own grid engine, so platform operators manage the switch without leaving the ERP. It is used by platform superadmins/operators managing shared telephony infrastructure — not by resellers or customers, and not to be confused with the customer-facing call-flow editor (documented separately), which is about a single tenant's own routing.

What you can do

  • Routing — manage SIP gateways (carrier trunks), view SIP profiles, access control lists, switch variables, hangup-cause definitions, and the platform dialplan (view-only)
  • Phone numbers — manage the platform-wide DID inventory: assign a number to a customer's domain and gateway, release it back to available, maintain the callee whitelist and numbering-plan blocks
  • Pricing — track currency exchange rates, review supplier cost aggregates and grouped destination rates, browse customer ratesheets by pricelist, and reconcile supplier CDR bills against internal costs
  • Business PBX — administer call forwarding, contacts, fax servers, call broadcasts, the conference stack (centres, rooms, profiles, controls, keys), PIN numbers, voicemail message archives, feature codes, time conditions, text-to-speech recordings, IVR menus, ring groups, music on hold, phrases, call blocking, and call-centre queues
  • PBX Extensions — manage per-domain extensions, unlimited-channel and airtime plan overrides, tenant-facing phone numbers, voicemail boxes, and review failed registrations and call recordings
  • Status — monitor live call records (CDR), active queues, the fax queue, SIP registration status, security events, and user activity logs
  • System — view default FusionPBX settings and database transaction logs
  • Supplier CDR reconciliation — upload a carrier's own CDR export and have it automatically matched line-by-line against Lubb's own call records and current rate deck, surfacing cost and duration variances

Common tasks

  1. Add a SIP gateway (carrier trunk). Open Gateways, add a new row with gateway name, profile, proxy, and credentials. Saving posts to the pbx box's GatewaysController, which validates the config and rescans the FreeSWITCH profile so the trunk registers immediately — the box, not this app, decides what's valid.
  2. Assign a DID number to a customer. Open Phone Number Inventory, find the number (status Available), and set its Account (domain) and Gateway. To release a number, clear the Account and set status back to Available — there's no delete button here, because "deleting" a number on the box only detaches it, it doesn't remove it from inventory.
  3. Reconcile a supplier's CDR invoice. On Supplier CDR Imports, use "Upload Supplier CDR" to submit the carrier's CSV export. The upload returns immediately with status pending; matching against a month of our own call records runs in the background and the batch's status updates to compared when done. Drill into "View Comparison" for the call-by-call result.
  4. Investigate a cost variance. In the comparison for a batch, filter by variance type — Not In Ours (amber, usually a matching issue such as a caller-ID rewrite or clock skew) versus a genuine cost variance (red). Each line shows what the supplier charged, what our own gateway cost was, and what today's rate deck would charge for the same call.
  5. Re-run a comparison. After adjusting match tolerances or once the PBX has back-filled call records for the period, use the "Re-compare" row action on a batch (or POST /pbx-supplier-cdr/{batch_id}/compare) to re-match the stored supplier lines against current data.
  6. Add a conference centre. Open Conference Centers and create a row with name, extension, and PIN length. The box's ConferenceCentersGridController builds the paired dialplan entry and reloads FreeSWITCH so the extension is dialable immediately — a plain database insert alone would leave the centre unreachable.

Data model

Most PBX Admin screens have no local Lubb table at all — they are a live proxy of the pbx box's own FusionPBX/FreeSWITCH database (gateways, SIP profiles, extensions, dialplans, conferences, and so on), read and written through the box's own session and controllers. The two exceptions are local to this app:

  • PbxSupplierCdrBatch — one row per uploaded carrier CDR file: totals, period, tolerances, and counts of matched/variant/unmatched lines.
  • PbxSupplierCdrLine — one row per call in that batch, holding both sides' duration and cost plus the match result (matched, not in ours, not in supplier) and today's re-rated deck cost for comparison.

Everything else — gateway configs, SIP trunks, DID inventory, dialplans, extensions, CDR — lives entirely on the pbx box; nothing is duplicated into Lubb's own database.

Configuration & integrations

  • The pbx box (FusionPBX/FreeSWITCH, pbx.cloudtools.co.za) — every module except supplier CDR reconciliation is a live read/write bridge to this box's own admin modules and /grid/{slug} endpoints, authenticated over an SSO session as the signed-in operator (the same bridge built for the call-flow editor's iframe deep-links).
  • FreeSWITCH — changes to gateways, extensions, ring groups, conferences, and dialplan-backed modules trigger the box's own reload/rescan hooks so the running switch picks up the change; nothing here writes silently to a table FreeSWITCH ignores.
  • FusionPBX credential provider — connection details for the pbx box are resolved through erp_credentials.resolve_provider(..., "fusionpbx").
  • Supplier CDR compare service — CSV parsing, matching against our own call_history, and re-rating against the current gateway rate deck run as a background task per uploaded batch.

API reference

PBX Admin has no bespoke CRUD endpoints of its own — every pbxa-* grid slug (gateways, phone number inventory, extensions, call records, and the rest) runs through the platform's generic grid engine, which transparently forwards writes to the pbx box's own endpoint (generic or bespoke controller, per module) instead of writing to a local table:

MethodPathPurpose
GET/grid/{slug}/dataList/search/paginate a module's rows (server-side paging against the pbx box)
GET/grid/{slug}/optionsColumn and field definitions for a module
GET/grid/{slug}/statsHeader stat tiles (e.g. cost variance totals)
POST/grid/{slug}Create a row (writable modules only)
PUT/grid/{slug}/{row_id}Update a row (writable modules only)
DELETE/grid/{slug}/{row_id}Delete a row (writable modules only)
POST/grid/{slug}/action/{key}Row/bulk button actions, e.g. Re-compare

Supplier CDR reconciliation has its own router (superuser-only), since uploading and comparing aren't plain grid operations:

MethodPathPurpose
POST/pbx-supplier-cdr/uploadUpload a carrier's CDR export (CSV/TXT, max 40MB) and schedule the comparison
POST/pbx-supplier-cdr/{batch_id}/compareRe-run the comparison for an existing batch

Which grid modules are writable, and whether a save reaches the pbx box's generic engine or one of its own bespoke controllers, is entirely the pbx box's decision — read-only modules (SIP Profiles, Call Forward, Registration Status, most Status/System tables) reflect the box's own permission model, not a limitation added here.

Lubb ERP Documentation