Enable Advanced Configurator and Constraint Models
| Requirement | Notes |
|---|---|
| Revenue Cloud Advanced license | Org must already have RCA enabled and the standard Sales Transaction context extended. |
| Admin or equivalent perm set | You’ll create fields, edit context definitions, and deploy Apex. |
| Developer Console / VS Code | Needed for the small Quote Line Item trigger. |
Step 1) Create a Text Area (Long) field called Constraint Engine Node Status to be low three objects.
i) Quote Line Item
ii) Order Product
iii) Asset Action Source
- Setup ▸ Object Manager ▸ Quote Line Item ▸ Fields & Relationships ▸ New
- Choose Text Area (Long) ▸ Next.
- Field Label =
Constraint Engine Node Status - Field Name =
ConstraintEngineNodeStatus(no underscores) - Length = 5 000 ▸ assign field‑level security ▸ Save.
Step 2)
- Setup ▸ Custom Context Definitions ▸ open your extended SalesTransactionContext_MK context.
- Edit Nodes
- SalesTransactionItem → Add Attribute
- Name:
ConstraintEngineNodeStatus - Type: Input & Output
- Data Type: String
- Name:
- AssetActionSource → Add Attribute
- Name:
AssetConstraintEngineNodeStatus - Type: Input & Output
- Data Type: String
- Name:
- SalesTransactionItem → Add Attribute
- Attribute Tags
- On each node, scroll to the new attribute, click Add Tag, use the same name (Salesforce will append
_c).
- On each node, scroll to the new attribute, click Add Tag, use the same name (Salesforce will append
- Save the context.
Step 3)
- In Context Definitions, click ▼ next to Quote Entities Mapping → Edit SObject Mapping.
- Map
ConstraintEngineNodeStatus(left) ➜ConstraintEngineNodeStatus__con Quote Line Item (right). - Verify TransactionType is also mapped.
- Save, then repeat for OrderEntitiesMapping & AssetEntitiesMapping (using the asset‑specific attribute for Asset Action Source).
Don’t forget to Activate the context after all mappings are saved.
Step 4) Deploy the Quote Line Item Trigger
trigger QuoteItemTrigger on QuoteLineItem (before insert) {
//collect QuoteActionIds
Set<Id> quoteActionIds = new Set<Id>();
for (QuoteLineItem qi : Trigger.new) {
if (qi.QuoteActionId != null && qi.ConstraintEngineNodeStatus__c == null) {
quoteActionIds.add(qi.QuoteActionId);
}
}
if (!quoteActionIds.isEmpty()) {
// Step 1: Get QuoteAction → SourceAsset
Map<Id, Id> quoteActionToAssetId = new Map<Id, Id>();
for (QuoteAction qAction : [
SELECT Id, SourceAssetId
FROM QuoteAction
WHERE SourceAssetId != null
AND Id IN :quoteActionIds
]) {
quoteActionToAssetId.put(qAction.Id, qAction.SourceAssetId);
}
// Step 2: Get AssetActions
List<AssetAction> assetActions = [
SELECT Id, AssetId, ActionDate
FROM AssetAction
WHERE AssetId IN :quoteActionToAssetId.values()
];
// Step 3: Get latest AssetAction per Asset
Map<Id, AssetAction> assetIdToLatestAction = new Map<Id, AssetAction>();
for (AssetAction aAction : assetActions) {
AssetAction existing = assetIdToLatestAction.get(aAction.AssetId);
if (existing == null || aAction.ActionDate > existing.ActionDate) {
assetIdToLatestAction.put(aAction.AssetId, aAction);
}
}
// Step 4: Get related AssetActionSource records
Map<Id, Id> assetIdToActionId = new Map<Id, Id>();
for (Id assetId : assetIdToLatestAction.keySet()) {
assetIdToActionId.put(assetId, assetIdToLatestAction.get(assetId).Id);
}
List<AssetActionSource> assetActionSources = [
SELECT ConstraintEngineNodeStatus__c, AssetAction.AssetId
FROM AssetActionSource
WHERE AssetActionId IN :assetIdToActionId.values() ORDER BY CreatedDate DESC
];
// Step 5: Map AssetId → Status
Map<Id, String> assetIdToStatus = new Map<Id, String>();
for (AssetActionSource actionSource : assetActionSources) {
if (!assetIdToStatus.containsKey(actionSource.AssetAction.AssetId) &&
actionSource.ConstraintEngineNodeStatus__c != null) {
assetIdToStatus.put(
actionSource.AssetAction.AssetId,
actionSource.ConstraintEngineNodeStatus__c
);
}
}
List<QuoteLineItem> toUpdate = new List<QuoteLineItem>();
// Step 6: Set ConstraintEngineNodeStatus__c directly on Trigger.new records
for (QuoteLineItem qi : Trigger.new) {
if (qi.QuoteActionId != null && qi.ConstraintEngineNodeStatus__c == null) {
Id assetId = quoteActionToAssetId != null ? quoteActionToAssetId.get(qi.QuoteActionId) : null;
if (assetId != null && assetIdToStatus != null) {
String status = assetIdToStatus.get(assetId);
if (status != null) {
qi.ConstraintEngineNodeStatus__c = status;
}
}
}
}
}
}
Step 5) Assign Below permissionSet to Required user
Permission Set Name : Product Configuration Constraints Designer
Step 6) Enable the Advanced Configurator Engine
- Setup ▸ Revenue Settings
- Scroll to Set Up Configuration Rules and Constraints with Constraints Engine.
- Toggle Enable → Save.
- App Launcher ▸ Constraint Models ▸ New
- Name:
Bundle Auto‑Add Demo - Context Definition: select your active context → Save.
- In Version 1 → Add Items:
Smart Office BundleRemote Work Bundle- (All option products auto‑import.)
Comments
Post a Comment