Terms Library now authors V3 deal terms
For Dealops V3 orgs, Terms Library edits move from in-place V2 term writes to V3 flowSpec.calculator.dealTerms writes that auto-publish and project back to V2.
V3 orgs could edit terms in the Terms Library, but those edits only touched the V2 pricingFlowSpec. The V3 flowSpec stayed stale.
A V3 Terms Library backend: read from calculator.dealTerms, transform the V2 UI Term shape, write through v3Admin.updateFlowSpec, and auto-publish.
Non-V3 orgs keep the legacy term.* path. V2-owned calculator content such as pricing tables, columns, and components remains owned by the Pricing Calculator.
1. Why this exists
On DEALOPS_V3 orgs, the Terms Library updated the old V2 term list in place.
- V3
flowSpec.calculator.dealTermsdid not receive the edit. - Publish could carry the old V2 calculator step forward, masking the mismatch.
- Reseed or full regeneration from V3 could wipe the Terms Library edits.
For V3 orgs, Terms Library edits become normal V3 flowSpec edits.
- V3 is authoritative for deal terms.
- Each create / update / delete / reorder writes a new V3 version.
- Publish projects those V3 terms into a new V2
pricingFlowSpecversion.
2. What changes
termFlowSpec.ts maps between V3 DealTermShape and the V2 Term shape used by the existing table and drawer.
Pure transforms: append, replace, remove, reorder.
useTermsBackend picks V3 or V2 behavior from organization.pricingFlowType === 'DEALOPS_V3'.
Same hook surface for create / update / delete / reorder.
mergeV3ProductSelectionIntoV2FlowSpec can now project deal-term grid items from the converted V3 doc into the current V2 calculator step.
Only enabled by publish / rollback full-flowSpec sync.
Meaningful files
apps/client/src/api/hooks/terms/termFlowSpec.ts
New adapter and pure transform module for V3 deal terms.
useListDealTerms.ts + usePersistDealTerms.ts
Reads V3 flowSpec and writes read-modify-write updates through updateFlowSpec.
useTermsBackend.ts
Central branch between V3 flowSpec backend and legacy V2 term.* mutations.
pricingFlowSpecMutations.ts
Adds calculator term projection while preserving V2-owned non-term items.
dealops3/flowSpec/types.ts + v2Converter.ts
Extends deal term schema and emits V2-compatible term fields.
pricingFlowSpecMutations.test.ts
New Mocha coverage for projection, final deletion, opt-out behavior, and no-current-V2 behavior.
3. How it works
useIsV3Org()checkspricingFlowType.- V3 orgs query
v3Admin.getFlowSpec. extractDealTerms()readsflowSpec.calculator.dealTerms ?? [].dealTermsToV2Terms()adapts to the existing Terms Library UI contract:{ terms }.
- Mutation hooks call
useTermsBackend(). - V3 ops become pure
DealTermShape[] → DealTermShape[]transforms. usePersistDealTerms()fetches the freshest flowSpec.withDealTerms()replaces onlycalculator.dealTerms, thenupdateFlowSpecpublishes.
| Operation | V3 org behavior | Legacy V2 org behavior |
|---|---|---|
| Create | appendDealTerm(term) then updateFlowSpec |
term.addTerm |
| Update | replaceDealTermById(term); preserves V3-only fields via merge |
term.updateTerm |
| Delete | removeDealTermById(termId); deleting the final term clears V2 projected term items |
term.deleteTerm, then renumber surviving terms |
| Reorder | reorderDealTerms(terms); array position is order |
term.updateMultipleTerms |
Projection rules in the V2 calculator step
- Always: V3 product-selection step replaces the V2 copy.
- When
projectDealTerms = true: term grid items come from converted V3 deal terms. - Still V2-owned: pricing table, non-term widgets, calculator step title, columns, and other calculator content.
- Layout: projected terms are placed first in rows
1..k; preserved non-term items shift down while keeping relative spacing. - Safety: callers that cannot vouch that V3 terms are authoritative leave
projectDealTermsfalse.
mergeV3ProductSelectionIntoV2FlowSpec(
currentFlowSpec.pricingFlowSpecData,
convertedV2FlowSpecData,
true // full V3 publish / rollback: dealTerms are authoritative
)
4. Schema and conversion details
Additive optional fields on dealTermSchema:
Absent status means ON.
The V3 enum now accepts Terms Library types that map directly into V2 UI config.
buildV2Term emits the new fields into the V2 shape.
statusdefaults toON.categorygoes touiConfig.category.orderFormNotestays term-level.
5. What it doesn't change
- No Terms Library component surface change;
TermsLibraryContaineronly swaps the list hook. - No V2-to-V3 backfill path. V3 is the source of truth for V3 org terms.
- No Pricing Calculator ownership change for tables, columns, calculator components, or other non-term content.
- No raw V2 editor behavior change.
- No Use Cases behavior change.
- No Approval Rules edit-path change; its V2 term list is invalidated after V3 writes so it can observe the projected V2 version.
- No REST API added; changes stay in existing tRPC-backed client hooks and server publish helpers.
6. Risks / rollback / open questions
- Reverting the client backend selector would send Terms Library writes back to the legacy V2
term.*path. - Reverting the server
projectDealTermspath would stop V3 terms from being projected during publish. - Those two pieces should roll back together; otherwise reads and writes can disagree again.
- Confirm
useTermsBackend()hook composition is acceptable even though it constructs both V2 and V3 backend objects before selecting one. - Confirm projection callers are correct: full V3 publish / rollback pass
true; partial or lossy sync leaves it false. - Confirm final-term deletion should clear V2 term items for V3 orgs, as covered by the new Mocha test.
New server Mocha tests cover term projection into V2, preservation of the V2 pricing table, final-term deletion, opt-out behavior with projectDealTerms = false, and the no-current-V2-row case. Existing publish tests are updated to assert that V3 deal terms now overwrite stale V2 term labels while non-term calculator content remains V2-owned.