Long Term Contract

A Long Term Contract (LTC) locks a supplier into a commitment period in exchange for a discounted fee rate on their advance products.

Contract action types

// src/app/core/pyb/constants/ltc-flow.constants.ts
export enum LtcContractActionType {
    New    = 'new',
    Renew  = 'renew',
    Change = 'change',
}

The value travels through the flow context, into the DocuSign return URL, and back out into LtcSummaryModalComponent, so the summary can say whether the supplier just signed, renewed or changed a contract.

State signals

status.hasLTCHistory

Ever signed an LTC. Grants LCT_HISTORY.

status.hasActiveLTC

An LTC is currently active. Selector selectLtcActive.

status.renewLTCSigned

A renewal has been signed. Selector selectRenewLTCSigned.

status.LTCGenericContract

The generic contract descriptor from the API.

Permission LONG_TERM_CONTRACT

Granted by default to every supplier.

Entry points

LTC offers arrive as dashboard notifications, not as a product page:

DashboardNotificationType.LongTermContract (new_long_term_contract)

A new LTC offer → LtcFlowService.

DashboardNotificationType.LongTermContractRenewal (renew_long_term_contract)

A renewal offer → LtcRenewalFlowService.

Both carry DashboardNotificationLtcDataDto[] — the available options with their durations, original fees and discounted fees.

New contract — LtcFlowService

private buildFlow(optionsModalData: LtcOptionsModalData): TasksFlow {
    return this.builder
        .addTask(this.ltcOptionsTask,           this.ltcOptionsTaskHandler)
        .addTask(this.ltcOptionConfirmationTask, this.ltcSelectedOptionTaskHandler)
        .addTask(this.ltcDocuSignTask)
        .setContextData('optionsModalData',   optionsModalData)
        .setContextData('contractActionType', LtcContractActionType.New)
        .getFlow();
}

Three steps: choose an option, confirm it, sign it.

private ltcOptionsTaskHandler = (flow: TasksFlow): FlowTaskDoneHandler<DashboardNotificationLtcDataDto> => {
    return result => {
        switch (result?.type) {
            case FlowTaskResultType.Done:
                flow.getContext().set('selectedOption', result.data);   (1)
                flow.runNext();
                break;
            case FlowTaskResultType.Cancel:
                this.declineCta();                                      (2)
                break;
        }
    };
};
1 The chosen option is written into the shared flow context so the confirmation and DocuSign tasks can read it.
2 Cancelling at the first step declines the notification outright, rather than running backwards out of the flow.

Context data is built from the first option’s originalFee, with LtcOptionPlatform.Amazon as the platform.

Renewal — LtcRenewalFlowService

Renewal is a two-stage journey. It first offers the supplier their current contract, and only shows the full option list if they decline it.

run(data)
  → buildConfirmCurrentLtcFlow(data)
        selectedOption   = data.find(c => c.isRealRenewal)
        contractActionType = Renew
        [ ltcOptionConfirmationTask ] → [ ltcDocuSignTask ]
        registerOnDone(...)

        Cancel ⇒ runChangeContractFlow(data)
                     contractActionType = Change
                     [ ltcOptionsTask ] → [ ltcOptionConfirmationTask ] → [ ltcDocuSignTask ]
                     registerOnDone(...)

                     Cancel ⇒ declineCta()
private getCurrentContractOption(contracts: DashboardNotificationLtcDataDto[]): DashboardNotificationLtcDataDto {
    return contracts.find(contract => contract.isRealRenewal);
}

The Change flow prices its modal against currentContract.discountedFeePercent rather than originalFee, so a supplier changing contracts compares against what they pay today, not the undiscounted rate.

LtcFlowService injects the shared root TaskFlowBuilder, while LtcRenewalFlowService constructs new TaskFlowBuilder() per flow. Both are valid — getFlow() resets the shared builder — but the renewal service needs two independent flows in one journey, hence the local instances.

Signing

LtcDocuSignTask starts DocusignFlowEnum.LongTermContract. On return:

this.docusignService.confirmLongTermContractDocuSignRequest(supplierKey, { event }).pipe(
    map(() => {
        if (event === DocusignEventTypeEnum.SingingComplete) {
            this.store.dispatch(clearDashboardNotifications());
            this.refreshData(data?.mode);
            this.openLtcDocusignSummaryModal(data);
        }
        return true;
    }),
);

LtcSummaryModalComponent is opened with { duration, discountedFeePercent, contractActionType, mode } and maxWidth: 870. Its close action decides where the supplier lands:

LtcSummaryModalActionType.GoToReportsPage

/reports/contracts-overview-report

LtcSummaryModalActionType.GoToProductOfferingsPage

/product-offerings

anything else

/dashboard

Modals

ltc-options-modal

The option list. Data: LtcOptionsModalData — { fee, options, platform, contractActionType }.

ltc-option-confirm-details-modal

Confirm the selected option.

ltc-sumarry-modal

Post-signature summary. (Folder name is misspelled in the repo.)

generic-ltc-modal

Shared shell for LTC dialogs.

Reporting

The Contracts Overview report at /reports/contracts-overview-report (ContractsOverviewPageModule) lists LTC history — duration, discounted rate and status. ContractsOverviewTextService builds its descriptive copy.

Analytics

Constant Segment event

LongTermContractEventType.OfferAccepted

LongTermContractOfferAccepted

LongTermContractEventType.OfferSavedForLater

LongTermContractOfferSaveForLater

LongTermContractEventType.OfferDeclined

LongTermContractOfferDeclined

LongTermContractEventType.DocusignVerified

LongTermContractDocusignVerified

OfferSavedForLater maps to LongTermContractOfferSaveForLater — "Save", not "Saved". This differs from the Advance Line equivalent (AdvanceLineOfferSavedForLater). Both spellings are live in Segment.