Product Offerings

/product-offerings — ProductOfferingsModule, guarded by DocuSignGuard.

The page presents Payability’s product catalog with the supplier’s personal eligibility against each. It is also one of the two pages DocuSign returns to, so a contract signed from here is processed before the page renders.

Availability

ProductOfferingsService.fetchProducts(freeAccess) calls CrossSellService.fetchAvailability(supplierKey) and turns the response into offer cards.

fetchProducts(freeAccess: boolean): Observable<ProductOfferingsCommonOfferConfig[]> {
    return this.crossSellService.fetchAvailability(this.user.getCurrentUserId()).pipe(
        map((data: CrossSellAvailability) => {
            this.setData(data);
            const response = {};
            Object.entries(data).forEach(([key, product]) => {
                if ([CrossSellProductEnum.InstantAdvance, CrossSellProductEnum.AccessPlus].includes(key as CrossSellProductEnum)
                    && product.status === CrossSellAvailabilityEnum.CannotRequest) {
                    return;                                            (1)
                }
                response[key] = productsConfig(this.injector, product, freeAccess)[key];
            });
            return Object.values(response);
        }),
    );
}
1 Instant Advance and Access Plus are hidden entirely when they cannot be requested. Seller Card and Instant Transfer are always rendered, with their status shown on the card.

PRODUCS_NO = 3 drives a three-card skeleton (fakeProducts$) while the real availability is loading — the placeholder count is fixed regardless of how many products actually come back.

The product catalog

product-offerings.config.ts builds one ProductOfferingsCommonOfferConfig per CrossSellProductEnum member.

Product Icon Sign-up action

SellerCard

pyb-credit-card (primary)

redirectUrl: '/seller-card'

InstantTransfer

pyb-zap (warning)

ProductOfferingsCommonOfferAction.ShowInstantTransferModal

InstantAdvance

via ProductInstantAdvanceModel

Model-defined

AccessPlus

via ProductAccessPlusModel

Model-defined (injector-aware)

Simple products are plain configuration objects; Instant Advance and Access Plus are model classes because their card content depends on runtime state. ProductAccessPlusModel additionally takes the Injector so it can resolve services while building its configuration.

Free-access copy

Every translation key is chosen at build time based on the freeAccess flag:

subheaderKey: freeAccess
    ? `${freeAccessProduct(CrossSellProductEnum.SellerCard)}.SUBHEADER`
    : `${commonProduct(CrossSellProductEnum.SellerCard)}.SUBHEADER`,

freeAccessProduct() and commonProduct() (product-offerings.utils.ts) build the namespace prefix. Four keys vary per product: SUBHEADER, DESC, GENERAL_ELIGIBILITY, GENERAL_PRICING. The flag comes from selectIsFreeAccess, backed by status.isFreeAccess.

Adding a product means adding eight translation keys — four for the common namespace and four for free access. A missing free-access key renders as the raw key string for that cohort only, which is easy to miss in testing.

Offer modes

export enum ProductOfferingModeEnum {
    DEFAULT                = 'DEFAULT',
    CAN_REFINANCE          = 'CAN_REFINANCE',
    REFINANCING_PROCESSING = 'REFINANCING_PROCESSING',
}

Refinancing modes change an offer card into a refinance prompt or a "processing" state for suppliers with an existing advance.

Components

product-offerings.component.ts

Page shell; subscribes to products$ and loading$.

common-offer/

The offer card — header, description, eligibility, pricing, CTA.

item-with-label/

A labelled feature row inside a card.

models/product-instant-advance.model.ts

Instant Advance card configuration.

models/product-access-plus.model.ts

Access Plus card configuration.

offers/access-plus-offer.service.ts

Access Plus sign-up behaviour.

product-offerings.utils.ts

Translation-namespace helpers.

DocuSign integration

DocuSignGuard on this route means a contract signed from a product card returns here and is processed before render. DocusignModeEnum.ProductOfferingsList tells DocusignVerificationService.refreshData() to call ProductOfferingsService.loadProducts() afterwards, so availability reflects the new contract.

Cross-sell analytics

Constant Segment event

ClickedSellerCardSignUpOnProductOfferings

Clicked Seller Card Sign Up on Product Offerings

ClickedInstantTransferSignUpOnProductOfferings

Clicked Instant Transfer Sign Up on Product Offerings

ClickedInstantAdvanceCrossSellAppliedOnProductOfferings

Instant Advance on Product Cross-Sell Page Applied

The product_cross_sell_page dashboard notification drives traffic here via CtaCrossSellStrategy — see Dashboard Notifications & CTAs.

Onboarding counterpart

views/onboarding/product-offering/ is a separate implementation used during onboarding, with its own components per product (advance-line/, instant-advance/, instant-access/, access-plus/, new-free-access/) and a repayment-slider/. The two are not shared. See Onboarding.