Field Propagation
As a deal moves Quote → Opportunity → Contract, Pinion carries field values forward at two points. The two hops use different mechanisms, and knowing which is which tells you what you get automatically versus what needs wiring:
| Hop | When | Mechanism |
|---|---|---|
| Quote line → Opportunity line | on Quote Sync | Twin fields — automatic, by matching API name |
| Opportunity line → Contract / Subscription / Asset | on close-won | Explicit carry — a fixed set of fields |
1. Quote → Opportunity: twin fields (automatic)
When a Quote syncs to its Opportunity, Salesforce copies the standard line fields (Quantity, UnitPrice, Discount). Pinion extends that with Salesforce CPQ’s twin-field model: any custom field that exists on both QuoteLineItem and OpportunityLineItem with the same API name and the same data type is copied automatically when the quote syncs — no mapping, no configuration, no field list to maintain.
Admin takeaway: to carry your own custom field from a quote line to the opportunity line, add the field to both objects with the same API name and type. It then rides through Quote Sync automatically. (Every custom field Pinion ships already exists as a twin on both objects.)
2. Opportunity → Contract / Subscription / Asset: the close-won carry
When an Opportunity reaches your Closed-Won stage (ClosedWonStage__c, see Lifecycle Defaults) and its Type is contract-eligible, Pinion activates the deal — it creates the downstream records and copies the line’s pricing, quantity, dates, and configuration onto them.
Unlike the twin-field hop, this is an explicit, fixed mapping — a defined set of fields, not same-API-name matching. Adding a new custom field to the line item does not automatically carry it onto the Subscription or Asset; that mapping is part of the package.
What gets created
- One Contract per Opportunity. Created and activated. Idempotent — re-saving or re-closing the same won opportunity won’t create a duplicate (it’s keyed on the source opportunity).
- A Subscription per recurring line. Every line whose product is flagged as a subscription becomes a
Subscription__c. Fan-out follows the product’s asset-conversion mode: one per line (the default, carrying the line quantity), one per unit (N records of quantity 1), or none. - An Asset per one-time line. Every non-subscription line becomes a standard
Asset.
Subscriptions replace standard Assets for tracking recurring products; one-time products still become Assets.
What carries onto the Subscription
The line’s economics and configuration copy across, grouped here by purpose:
- Product & links — the product, a back-link to the source line item, the parent Contract, and bundle role (parent subscription / parent asset), plus the configuration group and bundle instance name.
- Pricing — the net unit price, itemized price, and MDQ uplift + uplifted price. Discounts are already baked into the unit price, so the carried unit price is the contracted price — there is no separate discount or “special price” field on the subscription.
- Quantity — the billable quantity and the raw user-entered quantity.
- Dates — start and end dates.
- MDQ / segments — segment key, index, and label, the price dimension, and any per-segment dimensional overrides.
- Attributes & provenance — the configuration attribute snapshot, and which pricing waterfall priced the line.
- Stamped values — status set to Installed, change type New, and the currency copied from the Opportunity.
What carries onto the Asset
Each one-time line becomes a standard Asset carrying the product, the Account (from the Opportunity), price, quantity, purchase/install dates, description, the bundle parent, and a back-link to the source line and parent subscription. Status is set to Shipped.
What’s on the Contract
The Contract header carries the Account, a start date (from the opportunity’s contract-start field, or its close date), a term (from the opportunity’s contract-duration field, or 12 months by default), the pricebook, and the source-opportunity link that makes activation idempotent. Its status moves Draft → Activated. (The renewal-opportunity link is filled in later by the renewal flow, not at creation.)
Why close-won writes run in system mode
By least-privilege design, the rep persona holds no create/edit permission on Subscription__c (and no profile create on Contract/Asset) — a rep can’t hand-forge contract records. But a rep does trigger activation by closing their own opportunity Won. So the activation performs its writes in system mode, copying the already-authoritative pricing values (validated upstream when the configuration was saved) onto the new records.
This is a deliberate, documented carve-out: it lets close-won succeed for every rep without granting them write access to the contract objects, and it never silently drops a pricing field — which would mean a wrong contracted price with no error. You don’t need to grant reps any Subscription access for close-won to work.
Related
- Lifecycle Defaults — the settings that drive close-won: the stage, contract dates, term, and renewal/amendment stamps.
- Personas & Permission Sets — why reps don’t hold write access on the contract objects.
- Scheduled Jobs — the auto-renewal and contract-expiration jobs that act on the records created here.