Client Statuses at a Glance
Status (what stage the client is in)
SubStatus (what contract type or situation)
Which SubStatus goes with which Status?
| Status | Possible SubStatuses |
|---|---|
| Onboarding | — (empty) or Delayed |
| Reactivation Onboarding | — (empty) or Delayed |
| Active — Multichannel | MTC, Rolling, Fixed Term, Termination Notice, Termination (credits left) |
| Active — Platform Only | — (empty) or Termination Notice |
| Suspended | — (empty) |
| Inactive | — (empty) |
The Client Journey — End to End
Common Operations & What They Do
Create a New Client
Use the New Book Campaign form. This sets the client to Onboarding and creates the first campaign. A contract and package are also created if the client is billable.
Go Live
Once the campaign setup is complete and Finance has approved, Ops clicks Go Live. The client moves from Onboarding to Active — Multichannel with SubStatus MTC or Fixed Term.
Terminate a Client
From the client page, select Terminate. Choose a service end date. The client stays Active but moves to Termination Notice (new clients) or Termination (credits left) (legacy clients). The nightly job automatically moves them to Inactive when the date arrives.
Suspend a Client
Temporarily pauses the client. Status becomes Suspended. Widget is disabled. Can be manually unsuspended.
Cancel a Termination
If a termination was initiated but the client changes their mind, Cancel Termination moves SubStatus back to Rolling.
Move to Platform Only
Schedule a Platform Fee start date. On that date (during nightly processing), the client transitions to Active — Platform Only with a platform-fee package.
Reactivate from Platform Only
Finance can reactivate a Platform Only client back to Active — Multichannel with a new package. SubStatus becomes Rolling or MTC.
What Happens Automatically (Nightly Job)
_RecalculateCampaignsStatus to handle time-based transitions.| What changes | When |
|---|---|
| MTC → Rolling | Minimum contract term has passed |
| Fixed Term → Inactive | Fixed contract service end date reached |
| Termination Notice → Inactive | The termination service end date arrives |
| Termination (credits left) → Inactive | The delivery end date arrives (credits exhausted) |
| → Platform Only | Scheduled Platform Fee date arrives |
| Onboarding → Delayed | 60+ days in Onboarding without going live |
| Campaign deactivated | Scheduled deactivation date arrives |
| Finance Approved | All Xero invoices are paid/authorised |
Nightly Job Flow Diagram
Enum Definitions
Services/Services/Enums/ClientNewStatusEnum.cs and ClientNewSubStatusEnum.csClientNewStatusEnum
| Display Name | Enum Value | Int | Meaning |
|---|---|---|---|
| Active - Multichannel service | ActiveMultichannelService | 0 | Live client with active multichannel campaigns |
| Active - Platform Only | PlatformFeeOnly | 1 | Downgraded to platform-fee-only package |
| Inactive | Inactive | 2 | Terminated / fully deactivated |
| Onboarding | Onboarding | 3 | New client being set up |
| Suspended | Suspended | 4 | Temporarily paused |
| Reactivation Onboarding | ReactivationOnboarding | 5 | Previously inactive client being re-onboarded |
ClientNewSubStatusEnum
| Display Name | Enum Value | Int | Meaning |
|---|---|---|---|
| Delayed | Delayed | 1 | Onboarding >60 days without going live |
| MTC | MTC | 2 | Minimum Term Contract — within minimum commitment period |
| Rolling | Rolling | 3 | Past minimum term, month-to-month |
| Fixed Term | FixedTerm | 4 | Fixed-length contract |
| Termination Notice | TerminatioNotice | 5 | Notice period served, waiting for ServiceEndDate |
| (empty) | Empty | 6 | No substatus applicable |
| Termination (credits left) | TerminationCreditsLeft | 7 | Old-term client: ServiceEndDate reached but credits remain |
Client Creation: NewBookCampaign
ClientsController.NewBookCampaign (POST)Campaign Status Mapping
| Scenario | Client Status | Client SubStatus | Campaign Status |
|---|---|---|---|
| New client | Onboarding | "" (Empty) | New_Status_Onboarding |
| Reactivating inactive client | ReactivationOnboarding | "" (Empty) | New_Status_Reactivation_Onboarding |
| Existing client (adding campaign) | Unchanged | Unchanged | New_Status_Reactivation_Onboarding (resets FinanceApproved) |
Go Live (Campaign Activation)
CampaignController.GoLive → CampaignService.CampaignGoLiveUser-Triggered Status Transitions
ClientsController.csTerminate Client
Platform Fee Suspend — Back to Active
Other Actions
| Action | Precondition | Result |
|---|---|---|
| Suspend Client | — | Status → Suspended, SubStatus → "" |
| Terminate Immediately | — | Status → Inactive, SubStatus → "" |
| Cancel Termination | ActiveMultichannel + Termination Notice | SubStatus → Rolling |
| Platform Fee Schedule | — | Sets PlatformFeeDate (nightly job executes) |
| Platform Fee Terminate | PlatformFeeOnly | Status → Inactive |
| Reactivate from Platform Only | PlatformFeeOnly | Status → ActiveMultichannelService, SubStatus → Rolling |
| Reactivate Legacy Client | — | Status → ActiveMultichannelService, SubStatus → TerminationCreditsLeft |
Nightly _RecalculateCampaignsStatus
HangFireJobServiceDB.csComplete Lifecycle State Machine
Key Data Fields
| Entity | Field | Type | Purpose |
|---|---|---|---|
| Client | Status | string | Major lifecycle phase (friendly name from ClientNewStatusEnum) |
| Client | SubStatus | string | Contract/operational detail (friendly name from ClientNewSubStatusEnum) |
| Client | TerminationDate | DateTime? | When service ends (notice period expiration) |
| Client | DeliveryEndDate | DateTime? | Old-term clients: final date credits can be used |
| Client | PlatformFeeDate | DateTime? | Scheduled date to transition to PlatformFeeOnly |
| Client | ClientContractualStatus | int | NetNew(0), MigratedLegacy(1), ProtectedLegacy(2), ExceptionClients(3) |
| Client | ContractTermType | string | "MTC" or "Fixed" |
| Campaign | Status | string | New_Status_Onboarding, New_Status_Reactivation_Onboarding, New_Status_Active, New_Status_Inactive |
| Campaign | DeliveryDate | DateTime? | Go-live date |
| Campaign | DeactivationDate | DateTime? | Scheduled campaign deactivation |
| CampaignExtended | FinanceApproved | bool? | Finance sign-off (required for GoLive) |
| Contract | MinimumTermMonths | int | Minimum commitment before rolling |
Quick Reference: All Status Transitions
| From | To | Trigger | Method |
|---|---|---|---|
| (new) | Onboarding / "" | New client created | NewBookCampaign |
| Inactive / "" | ReactivationOnboarding / "" | Inactive client reactivated | NewBookCampaign |
| TerminationCreditsLeft | ReactivationOnboarding / "" | Previous term client rebooked | NewBookCampaign |
| Onboarding / "" | Active / MTC | Campaign goes live (MTC) | GoLive |
| Onboarding / "" | Active / FixedTerm | Campaign goes live (Fixed) | GoLive |
| ReactivationOnboarding / "" | Active / MTC | Reactivation goes live (MTC) | GoLive |
| ReactivationOnboarding / "" | Active / FixedTerm | Reactivation goes live (Fixed) | GoLive |
| Onboarding / "" | Onboarding / Delayed | 60+ days without going live | Nightly Block 12 |
| Active / MTC | Active / Rolling | Min term period passed | Nightly Block 3 |
| Active / FixedTerm | Inactive / "" | Service end date passed | Nightly Block 4 |
| Active / * | Active / Termination Notice | User terminates (new term) | TerminateClient |
| Active / * | Active / TerminationCreditsLeft | User terminates (old term) | TerminateClient |
| Active / Termination Notice | Active / Rolling | User cancels termination | CancelTermination |
| Active / Termination Notice | Inactive / "" | TerminationDate reached (new term) | Nightly Block 5 |
| Active / TerminationCreditsLeft | Inactive / "" | DeliveryEndDate reached (old term) | Nightly Block 7 |
| Active / * | Suspended / "" | User suspends | SuspendClient |
| Active / * | Inactive / "" | User terminates immediately | TerminateImmediatelyClient |
| Active / * | PlatformFeeOnly / "" | PlatformFeeDate reached | Nightly Block 8 |
| PlatformFeeOnly / "" | Active / MTC | Finance reactivation | PlatformFeeSuspend |
| PlatformFeeOnly / "" | Active / Rolling | Finance reactivation | ReactivateFromPlatformOnly |
| PlatformFeeOnly / "" | Inactive / "" | Platform terminate | PlatformFeeSuspend (Terminate=true) |
| PlatformFeeOnly / Termination Notice | Inactive / "" | TerminationDate reached | Nightly Block 9 |
| Inactive / "" | Active / TerminationCreditsLeft | Legacy reactivation | ReactivateLegacyClient |
Active vs Deprecated Code Paths
| Method | Controller | Status |
|---|---|---|
NewBookCampaign | ClientsController | ✅ Active — primary client/campaign creation |
GoLive | CampaignController | ✅ Active — Onboarding → Active transition |
TerminateClient | ClientsController | ✅ Active |
SuspendClient | ClientsController | ✅ Active |
TerminateImmediatelyClient | ClientsController | ✅ Active |
CancelTermination | ClientsController | ✅ Active |
PlatformFeeClient | ClientsController | ✅ Active |
PlatformFeeSuspend | ClientsController | ✅ Active |
ReactivateFromPlatformOnly | ClientsController | ✅ Active |
ReactivateLegacyClient | ClientsController | ✅ Active |
_RecalculateCampaignsStatus | HangFireJobServiceDB | ✅ Active — nightly Hangfire job |
EditNew | ClientsController | ⚠️ Deprecated |
BookCampaign | ClientsController | ❌ Fully commented out |