Cancellation & Reactivation
A supplier can request deactivation from account settings. Because Payability advances against future receipts, cancellation is not immediate — each connected marketplace has an opt-out date after which funding stops, and the supplier may carry a residual liability until then.
Status model
export enum CancelationStatus {
Canceled = 'canceled',
Pending = 'pending',
}
|
Not cancelling. |
|
Cancellation requested; opt-out dates are running. |
|
Cancellation complete. Combined with |
Availability
CancellationWorkflowService decides which action to offer by reading
cancellationPermissions off the supplier status:
this.store.select(selectCurrentUserId).pipe(
filter(supplierKey => coerceBooleanProperty(supplierKey)),
take(1),
switchMap(supplierKey => this.suppliersService.getSupplierStatus(supplierKey)),
pluck('cancellationPermissions'),
).subscribe(v => { this.showBtn(v); this.loadingActualStatusSubject$.next(false); });
export enum CancellationWorkflowOptionAvailableEnum {
DEACTIVATE = 'DEACTIVATE',
REACTIVATE = 'REACTIVATE',
NONE = 'NONE',
}
canReactivate takes precedence over canCancel; if neither is set the section
renders nothing. The service exposes activeOption$, loadingActualStatus$ and
showLoaderOnButton$ so the UI can show a skeleton while the status resolves.
|
The service calls |
Deactivation
supplier clicks "Deactivate account"
→ track(CancellationWorkflowEventType.DeactivateAccountStartBtnClicked)
→ startDeactivateAccountProcess()
→ confirmation modal (MessageModalService)
→ cancellation survey
CancellationSurveyShowWhenDeactivatingAccountService
→ track(CancellationWorkflowEventType.SubmittingTheCancellationSurvey)
→ CancellationWorkflowApiService submits the request
→ success toast (PybToastService)
→ cancelationStatus becomes Pending
Reactivation
supplier clicks "Reactivate account" → track(CancellationWorkflowEventType.ReactivateAccountStartBtnClicked) → confirmation modal → track(CancellationWorkflowEventType.ReactivateAccountConfirmBtnClicked) → CancellationWorkflowApiService reactivation call
The cancellation survey
views/partials/modals/cancellation-survey/, registered globally by
CancellationSurveyModule in AppModule so it can be opened from anywhere.
Fields:
export enum CancellationSurveyFormFieldsTypes {
REASON = 'reasonCode',
COMMENT = 'comment',
RECOMMENDATION = 'rating',
}
Reason options arrive on the cancellation_survey dashboard notification as
DashboardNotificationCancellationSurveyOptionDataDto[], so the option list is
server-controlled and can change without a release.
The survey is also reachable from the notification itself, not only from the deactivation flow.
Cancellation banners
CancellationBannerInitializerService runs from
GlobalSubscriptionsService.init() and only acts when
cancelationStatus === Pending. It fetches the supplier’s marketplaces and
partitions them by opt-out date.
private isOptOutDateSet(optOutDate: string): boolean {
return optOutDate && new PybDate(optOutDate, this.rawDateFormat).get('year') !== 9999; (1)
}
private pendingCancellationFilter = (mp: SupplierMarketplacesModel): boolean => {
const optOutDate = new PybDate(mp.fundingParticulars.lastOptOutDate, this.rawDateFormat);
return new PybDate().isBefore(optOutDate, 'd'); (2)
};
private reachedCancellationFilter = (mp) => !this.pendingCancellationFilter(mp);
| 1 | Year 9999 is the sentinel for "no opt-out date" — such marketplaces are
excluded entirely. |
| 2 | Opt-out still in the future → pending. Otherwise → reached. |
Pending banner
Composed from three translation keys:
|
Lead sentence. |
|
One per marketplace, interpolating |
|
Trailing link. |
Reached banner
Lists the marketplaces whose opt-out date has passed, then branches on the supplier’s potential liability, read from the balance slice:
|
|
otherwise |
|
Both banners are BannerTypes.WARNING with hideClose: false, and previous
banners are cleared before new ones are shown so repeated evaluation cannot stack
duplicates.
Account-cancelled banner
InternalMessagesService.initAccountCancelledBanner(), also called from
GlobalSubscriptionsService.init(), shows the terminal banner once the account is
fully cancelled.
Analytics
| Constant | Segment event |
|---|---|
|
|
|
|
|
|
|
|
|
Deactivation has a start event but no confirm event, while reactivation has both. Funnel analysis of completed deactivations must use the survey-submission event as the proxy. |