Subscription offer – system description
Parameters of the offer page, how offered plans are selected, the quota branch, and the endpoints for ordering plans and functions and for payment.
Overview
For a locked function the startup upsell guard, the access-denied page's link or a direct address leads here. The menu item is hidden. Parameters: locked_route, locked_action, reason (need_credit, need_plan, overage), feature_id, back, return_url, required_quantity, required_object, beneficiary_client_id, store_id. Full page: upsell; modal: upsell.modal.
What it shows
- For a locked function its name and description; plans by
Dlbtentitlement::plansFor(): the definition–plan pairs whose items contain the function (with plan inheritance); if the user's row has anoffer_definition_id, only that definition. - Recommended plan: the cheapest above the current level; individual price: the function's
list_price. - With debt (
debt) no plan is offered. - Quota branch: limit block (required, included, used, missing, cost) and options: top-up, package, plan change (to the catalogue), back.
- Without a lock the full matrix: active definitions × plans × functions.
- The
backaddress must be one of the system's own routes (safeBack).
Ordering endpoints
| Endpoint | Behaviour |
|---|---|
upsell.order | checks an active definition and a plan belonging to it; stops without Dlbtbilling (logged); quotePlan() – refuses without a price; gate(): pay → payment_required (amount, balance, shortfall), ok → charge(); then materialise(..., 'order', false) in ADD mode and syncCoreRouteAccess() |
upsell.orderfeature | quoteFeature(), same cover gate; addMeteredOrder() (source = 'order', metered); if already present, the charged amount is refunded |
upsell.pay | Dlbtbilling::payIn(..., 'testpay'): credit + invoice + draft voucher |
Permissions
list and order: SYSTEM – for every signed-in user; index() and modal() call no canAction. Data touched: definition and plan tables, feature, user_feature, subscription_credit, invoice, transaction.