modules

Clients module

Track recurring-retainer customers for service and professional-services businesses. MRR, ARR, churn — all in one place.

Updated 2026-04-19

Who this is for

The Clients module only shows up for service-mode orgs (consultancies, agencies, professional services). Retail and wholesale orgs don't see it — they use Sales + Contacts instead.

A Client in Opterflow is a commercial relationship, not a person. The person is a Contact; the Client is the agreement — "Acme Corp pays us GHS 5,000/month for social media management."

When to use Clients vs. Contacts

Situation Use
Retainer / recurring agreement Client
One-time buyer / walk-in Contact with a Sale
Lead you're still pitching Contact in a Pipeline deal
Client whose retainer ended Client with status=churned

Every Client is backed by a Contact (its "primary contact" — the person you talk to most).

What's on /clients

  • Three stat cards up top:
    • Active Clients count
    • MRR — monthly recurring revenue (pesewas-accurate, quarterly/annual retainers normalised)
    • ARR — MRR × 12
  • Client table sorted by MRR descending. Columns: name, status, start date, monthly retainer, total billed, last touch, owner, actions.
  • Filter bar: status chips (active / paused / churned), owner dropdown, search.

Adding a client

Click Add Client. The modal asks for:

  • Client name — usually the company name
  • Primary contact — searchable dropdown of existing Contacts. Or "Create new contact" inline.
  • Start date — when the retainer begins
  • Retainer amount — in your org's currency
  • Frequency — monthly / quarterly / annual
  • Owner — which staff member is the account lead (optional)
  • Industry (optional)
  • Notes (optional)

Submit creates the Client row + first RetainerAgreement + primary ClientContact join row, all in one transaction.

How MRR is calculated

Source of truth: RetainerAgreement, not invoices.

  • Only active clients contribute (paused and churned = 0)
  • Only the currently-effective agreement counts (effectiveFrom ≤ today < effectiveTo)
  • Frequency normalisation:
    • monthly → amount
    • quarterly → amount / 3
    • annual → amount / 12

Stored denormalised on Client.currentMrr so sorting by MRR stays fast. Recomputed every time a retainer changes.

No pro-ration in v1. A client added mid-month contributes full MRR from day 1. Simpler, disappears next month anyway.

One-off project work isn't counted — that flows through Invoices with no retainer link. Financials module (v1.2) will surface "Project Revenue" vs "Recurring Revenue" as separate lines.

Editing a client

Click any row → opens the edit modal. You can change:

  • Name, status, start date, owner, industry, notes
  • Retainer amount or frequency — v1 replaces the current agreement in place. Rate change history is v1.1. Until then, editing a retainer is destructive — the UI warns.

Churning a client

Two ways:

  1. "Mark churned" (default) — status → churned, churnedAt = now, captures a reason (lost / budget / scope_ended / other). MRR drops to 0. Client stays visible (filter is "All" or "Churned").
  2. "Delete permanently" — admin only, requires type-to-confirm. Removes the row entirely. Usually you want "Mark churned" instead — you lose less data.

Reactivating a churned client

Click a churned row → Reactivate. Status flips to active, churnedAt + churnReason cleared, MRR recomputed from the existing RetainerAgreement.

Integration points

  • Campaigns: client's primary contact shows up in campaign audience filters (client.status = 'churned' AND churnedAt ≥ now - 90d is a good reactivation audience — coming in v1.1).
  • Pipeline: v1.1 adds a "Promote to Client" action on won deals.
  • Financials: future MRR chart reads directly from RetainerAgreement history.

Permissions

Role Access
Super admin Not applicable — super admin is platform-level
Admin Full CRUD
Manager Full CRUD
Staff View only

MRR/ARR stat cards respect financial visibility — staff without revenue permission see "Active Clients" count but the MRR/ARR cards show locked.

Common mistakes

  • Using Clients for one-time buyers. If they're not on a retainer, they're a Contact with a Sale.
  • Not setting frequency correctly. A client paying "GHS 30,000 annually" with frequency=monthly shows MRR=30,000 (wrong!). Set frequency=annual so MRR normalises to 2,500.
  • Editing retainer without warning. v1 overwrites history. Write down the previous rate somewhere before changing, or wait for v1.1's proper rate-change flow.

Was this article helpful?