Here’s a comprehensive solution addressing all three aspects - product bundle mapping, nested bundle handling, and schema validation:
1. Product Bundle Mapping Strategy:
Implement a recursive bundle flattener that builds a complete product tree before transformation. Create a custom Apex class that queries the full bundle hierarchy:
List<SBQQ__ProductOption__c> options = [
SELECT SBQQ__OptionalSKU__c, SBQQ__Number__c,
SBQQ__ConfiguredSKU__c, SBQQ__ConfigurationType__c
FROM SBQQ__ProductOption__c WHERE SBQQ__ConfiguredSKU__c IN :bundleIds
];
This ensures you capture all nested relationships including the configuration type which is critical for validation.
2. Nested Bundle Handling:
Since your external CPQ has a 2-level limit, implement a bundle collapse algorithm. For any product found at level 3, re-parent it to level 2 and store the original parent ID in a custom field (e.g., Original_Bundle_Path__c). Calculate adjusted quantities by multiplying the level-2 and level-3 quantities. This preserves pricing accuracy while meeting the external system’s constraints.
Key implementation: Before sending to external CPQ, run a validation check that counts bundle depth. If depth > 2, trigger the collapse logic. Store the transformation metadata in a custom object (Bundle_Transform_Log__c) with fields: Quote_ID, Original_Structure (JSON), Transformed_Structure (JSON), Transform_Date. This enables bidirectional sync if quotes are modified.
3. CPQ Schema Validation:
The validation failure you’re seeing indicates missing required fields in your payload. Ensure your integration includes:
- SBQQ__ConfigurationType__c (determines validation rules)
- SBQQ__OptionalSKU__c (the actual product reference)
- SBQQ__Number__c (bundle sequence for ordering)
- Any custom fields your external system requires
Add pre-flight validation in your integration layer that checks the payload against the external CPQ’s schema before sending. Use a try-catch block to capture validation errors and log them with full context:
try {
validateBundleStructure(bundleData);
externalCPQ.syncQuote(transformedPayload);
} catch(CPQValidationException e) {
logValidationError(quoteId, e.getMessage());
}
Implementation Steps:
- Add the Original_Bundle_Path__c custom field to SBQQ__QuoteLine__c
- Create the Bundle_Transform_Log__c custom object for audit trail
- Build the recursive bundle query and flattening logic in Apex
- Implement pre-flight schema validation
- Add error logging with full payload context
- Test with quotes containing 3-level bundles
This approach has resolved similar issues for multiple clients. The key is handling the transformation before validation, not during it. The bidirectional metadata ensures you can sync changes back to Salesforce without losing the original bundle structure.