Skip to content

Book 7 — Platform & Admin (Index & Review Instrument)

What this book is. Books 1–6 documented the business modules — where money, stock, people and vehicles move. Book 7 documents the control plane underneath all of them: who is allowed to do what (permissions & roles), which behaviours are switched on per client (feature flags & settings), how every document gets its number, how the org is sliced (dimensions), how staff and customers raise issues (help desk, CRM), and how the system talks to the outside world (SMS, WhatsApp, email). Nothing in Book 7 sells, ships, or posts to the ledger by itself — instead, every chapter here is referenced by the other six books.

Chapters: 27 System Administration · 28 CRM · 29 Help Desk · 30 Communication Centre. Source nav (authoritative module boundaries): system_administration.blade.php (736 lines), crm.blade.php, help_desk.blade.php, communication_centre.blade.php.


The one-sentence version

Book 7 is the ERP's operating system: System Administration (Ch27) defines who can act, what is switched on, and how things are numbered; CRM (Ch28) and Help Desk (Ch29) are two separate issue-tracking systems (customer-facing vs internal); and the Communication Centre (Ch30) owns the SMS/WhatsApp/email channel that the whole ERP uses to reach people.


The control-plane map

flowchart TB
    subgraph SA["Ch27 System Administration — the control plane"]
        PERM["Permissions & Roles<br/>user_permissions (module___action)<br/>role_id==1 = superuser bypass"]
        FLAGS["Feature flags / settings<br/>settings + administration_settings"]
        NUM["Number Series<br/>wa_numer_series_codes"]
        DIM["Dimensions<br/>branches / departments / projects / gl_tags"]
        APPR["Approver Limits<br/>approver_limits (level → limit)"]
    end

    subgraph ISSUES["Issue tracking — TWO separate systems"]
        CRM["Ch28 CRM<br/>case_tickets (customer-facing)<br/>SLA + escalation matrix"]
        HD["Ch29 Help Desk<br/>tickets (internal IT/dev)<br/>status = event rows"]
    end

    COMMS["Ch30 Communication Centre<br/>SmsService (DI) + ScenarioNotificationDispatcher<br/>SMS · WhatsApp Cloud API · Email"]

    PERM -.gates.-> B16["Books 1–6<br/>(every module)"]
    FLAGS -.switches behaviour.-> B16
    NUM -.doc numbers.-> B16
    DIM -.scopes/tags data.-> B16
    APPR -.approval thresholds.-> B16

    CRM -->|assign / escalate / status SMS| COMMS
    HD -->|notify creator / support team| COMMS
    B16 -->|OTP, POS, delivery, approval, invoice alerts| COMMS

The four chapters at a glance

Ch Module The engine The one thing to remember
27 System Administration user_permissions + settings/administration_settings + NumberSeriesService The control plane every other book depends on. Permissions are enforced in controller methods, not route middleware.
28 CRM case_tickets / CaseTicket + escalation matrix Customer-facing complaint/case system with an SLA clock and 3-level escalation. Supplier Tickets are the same table (channel='supplier_portal').
29 Help Desk tickets / Ticket + ticket_statuses Internal staff→IT/dev queue. Status is the latest row in ticket_statuses, not a column; the "Development" status = engineering backlog.
30 Communication Centre SmsService (DI) + ScenarioNotificationDispatcher + 103 SmsScenarios The app-wide messaging backbone — consumed from ~146 files. Kenyan SMS aggregators (Airtouch default), Meta WhatsApp Cloud API, Laravel mail.

Seams resolved in Book 7 (long-standing open questions, now answered)

  1. "Are *___view / *___approve permission strings enforced, or only nav-hidden?" — the guide's single most-repeated open question, carried since Book 1. Verdict (code-proven, Ch27): they ARE enforced, but at the controller-method level, NOT via route middleware. The System-Admin route group carries only ['AdminLoggedIn','ip-blocker','single.session'] — none of which check a permission. Real gating is manual inside actions (e.g. RoleController:38, SettingsController:33, ApprovalLimitsController:23), each redirecting "Invalid Request" on failure. Caveat: because it is per-method and hand-written, coverage depends on developers remembering to add it — only 3 of ~60 controllers were audited, so completeness of enforcement is itself an open audit item (see §Open questions).

  2. "Where does 'which behaviour is live per client' actually resolve?" — carried since Book 2. Answer (Ch27): TWO flag tables — legacy settings (typed, read via the setting($slug) helper) and the newer administration_settings (read via AdministrationSetting::where('slug', …)). Every "feature-flag / tenant-difference" note in Books 1–6 (use-extensive-gl-posting, INVENTORY_SETUP='UOM BASED', activate-subbins, ACTIVATE_MANUFACTURING_MODULE, ENFORCE_DELIVERY_OFFLOADING…, etc.) reads one of these two tables. FEATURE-FLAG-typed settings are hidden from non-developer users.

  3. "Where do document numbers (PM-#####, FAC-, DSP-, PAYROLL series…) come from?" — referenced across Books 3–6. Answer (Ch27): NumberSeriesService::generate($code) over wa_numer_series_codes auto-provisions the code, increments last_number_used, and returns CODE-000123. There is a branch-scoped variant and a lost_number_series_codes gap tracker.

  4. "What is the shared notification channel used by approval queues everywhere?" — carried since Book 1's approval queues. Answer (Ch30): a single App\Interfaces\SmsService contract, container-bound once and consumed via app(SmsService::class) from ~146 files (OTPs, POS, approvals, requisitions, deliveries, invoices, CRM cases, queued jobs). Governance runs through 103 SmsScenarios + an allowed_sms_notifications on/off table + a ScenarioNotificationDispatcher that fans one business event to both SMS and WhatsApp.


Things that look connected but aren't

  • FOUR parallel issue-tracking systems, not one. (a) CRM case_tickets (customer complaints, Ch28); (b) Supplier Tickets = the same case_tickets table with channel='supplier_portal' (the bridge to the Supplier Portal, Book 3 Ch14); (c) Help Desk tickets (internal, Ch29); (d) a separate Weighbridge ticketing noted in passing. The word "ticket" is nominal noise — CRM's model is literally CaseTicket and its overdue job operates on case_tickets. CRM and Help Desk share zero data.
  • "Support Teams / Ticket Category" (in the System-Admin nav) belongs to Help Desk, NOT CRM. CRM's equivalent is its own per-category 3-level escalation matrix.
  • Admin "Employees" ≠ HR "employees". Admin "Employees" is the users login table (UserController, carries role_id); HR "employees" is the separate payroll master from Book 6 (EmployeeController). Same word, different tables.
  • Two feature-flag tables, not one — legacy settings vs newer administration_settings; readers use different access patterns (setting($slug) vs Eloquent). A dev looking for a flag must check both.
  • Bulk-SMS screens do NOT use the messaging backbone. Transactional SMS goes through the SmsService DI binding; the Bulk SMS blast screens route by a sender-ID switch and new the provider directly. A legacy helpers.php sendMessage() also hard-pins InfoSky. So the "backbone" is real for transactional traffic but partially fragmented for bulk/legacy paths.
  • The bulk-sms-* reference in the Help Desk nav is dead copy-paste — the $active_class variable is computed and never used; no help-desk route touches bulk SMS.

Consolidated open questions (for user/dev validation)

Enforcement & security - Permission-enforcement coverage audit. Enforcement is per-controller-method and hand-written; only 3 of ~60 admin controllers were verified. Which actions (if any) lack the check and are therefore reachable by URL regardless of $my_permissions? (High-value: this is a real authorization-gap risk, not just documentation.) - Hard-coded SMS default access token shipped in config/sms_gateway.php:14 — confirm it is overridden per environment and not a live credential in source. - EmailController has no permission guards (Ch30 §7) — anyone past AdminLoggedIn may reach the outbound-email screens.

Multi-tenancy & data model - Multi-tenancy boundary of the two flag tables — are settings / administration_settings per-tenant, global, or mixed? (Determines whether a flag flip affects one client or all.) - Help Desk status has no server-side transition guard — status() writes any value the client sends; the Open→Development→Completed→Closed flow is enforced only in the blade dropdown. - CRM scheduled --timeout-hours value, the case_category_actions UI, and the supplier-notification send path remain un-traced (Ch28 §7).

Operational - No SMS credits/cost ledger, no opt-out table, and no async SMS delivery-report (only WhatsApp has a DLR webhook) — how is cost and consent tracked?


Recurring patterns confirmed (across the whole guide)

  • Approval queues everywhere — and now the control surface behind them is documented: approver_limits (level → limit) + the permission model. This is the richest "approvers not curators" AI target in the ERP, with the audit trail (user_permissions, activity logs) to support it.
  • Tenant behaviour is flag-driven — and the flags now have a home (two tables in Ch27). A dedicated feature-flag inventory pass would let the AI phase reason about "which client runs which path."
  • Legacy/dead code intermixed — Book 7 adds fresh examples (dead bulk-sms nav in help desk; legacy settings vs administration_settings; legacy sendMessage() helper). The recommended standalone legacy-inventory pass still stands.

AI-leverage surfaces flagged for the later phase

  • Approver Limits + permission model (Ch27) — the concrete control plane for "make users approvers, not curators": thresholds, roles, and an audit trail already exist to drive intelligent routing/auto-approval.
  • CRM SLA + 3-level escalation matrix (Ch28) — a natural target for predictive escalation, auto-triage/categorisation, and overdue-risk scoring (the case_resolution_time_minutes clock is already there).
  • 103 SmsScenarios governance (Ch30) — a ready-made surface for explainable, preference-aware smart notifications (right message, right person, right channel), and for consolidating the fragmented bulk/legacy send paths.

Where this leaves the guide

Book 7 closes the chapter fan-out: all 30 chapters across Books 1–7 are written and on disk. Remaining to complete the guide:

  1. Placeholders — Manufacturing & Production (manufacturing_and_production, flag ACTIVATE_MANUFACTURING_MODULE) and Laboratory (laboratory, flag ACTIVATE_LABORATORY_MODULE): listed, feature-flagged, up-and-coming — short stubs, no deep dive.
  2. Cross-module handoff map — the end-to-end stitch across all seven books (order → dispatch → delivery → banking; procure → GRN → AP → GL; fleet money-out → GL; payroll → GL; issues → comms). Carry into it the one still-open cross-book loop: driver-INCENTIVE earnings (Book 5 tyre/fuel incentives) were never found reaching payroll_month_detail_earnings — the penalty half is resolved (via polymorphic EmployeePenalty), the earnings half stays OPEN.

With the control plane now documented, the guide has the vocabulary it was missing — permissions, flags, dimensions, number series, and the notification backbone — to describe how the business modules are wired together.