Skip to main content
Gruppo in evidenza

* Salesforce Revenue Cloud *

Welcome! This group is dedicated to your success with Salesforce Revenue Cloud. Join the conversation here to stay up to date on the product, learn best practices, and everything in between. Use this group to review resources, ask questions, help each other, and share experiences. --------------------------------------- This group is maintained and moderated by Salesforce employees. The content received in this group falls under the official Forward-Looking Statement: http://investor.salesforce.com/about-us/investor/forward-looking-statements/default.aspx

I’m having trouble with a Revenue Cloud instance. Every time I try to add a bundle to a quote, I get the following error:

“Verify if fields like Component, Virtual Component, or backend configuration block it from being quoted outside of its parent bundle.”

The system works normally when I try to add a standalone product. The issue only occurs with the bundle, and I’m not trying to perform an amendment—just add a new product.

Is anyone else encountering this same error?

4 risposte
  1. 8 set, 12:03

    @Guilherme Mattei  

    The fact that it happens only for accounts with existing Assets makes me suspect the issue may be related to the asset-to-bundle configuration or existing asset context, rather than the bundle product itself.

    I’d compare a working new account vs. an account with existing Assets, especially the asset relationships and any configuration rules/CML evaluated during bundle configuration. The “Failed to parse response” message on accounts without Assets also makes me think it would be worth checking the configuration-rule response/logs for both scenarios. 

0/9000

MocAdapter for Tax

MocAdapter Document link

 

Shipping Country and State

Tax Logic Implemented

🔹 India → 30% Tax

🔹 USA → 40% Base Country Tax + State Tax

Example State Tax Configuration:

  • Utah → 2%
  • South Dakota → 2.5%
  • Minnesota → 3%
  • North Dakota → 3.5%
  • Nebraska → 4%
  • New Hampshire → 4.5%
  • Idaho → 5%
  • Washington → 5.5%
  • Vermont → 6%

🔹 Other Countries → Default 20% Tax 

 

global virtual class MockAdapter implements commercetax.TaxEngineAdapter {

global commercetax.TaxEngineResponse processRequest(

commercetax.TaxEngineContext taxEngineContext

) {

commercetax.RequestType requestType =

taxEngineContext.getRequestType();

commercetax.CalculateTaxRequest request =

(commercetax.CalculateTaxRequest)

taxEngineContext.getRequest();

if (request.documentCode == null) {

return new commercetax.ErrorResponse(

commercetax.resultcode.TaxEngineError,

'404',

'documentCode is mandatory'

);

}

if (requestType ==

commercetax.RequestType.CalculateTax) {

commercetax.calculatetaxtype type =

request.taxtype;

String docCode = '';

if (request.DocumentCode != null) {

docCode = request.DocumentCode;

} else if (request.ReferenceEntityId != null) {

docCode = request.ReferenceEntityId;

} else {

docCode = String.valueOf(

getRandomInteger(0, 2147483647)

);

}

commercetax.CalculateTaxResponse response =

new commercetax.CalculateTaxResponse();

if (request.isCommit == true) {

response.setStatus(

commercetax.TaxTransactionStatus.Committed

);

} else {

response.setStatus(

commercetax.TaxTransactionStatus.Uncommitted

);

}

response.setDocumentCode(docCode);

response.setReferenceDocumentCode(

request.referenceDocumentCode

);

response.setTaxType(type);

response.setStatusDescription(

'statusDescription'

);

response.setDescription('description');

response.setEffectiveDate(System.now());

if (request.transactionDate == null) {

response.setTransactionDate(System.now());

} else {

response.setTransactionDate(

request.transactionDate

);

}

if (request.taxTransactionType == null) {

response.setTaxTransactionType(

commercetax.TaxTransactionType.Debit

);

} else {

response.setTaxTransactionType(

request.taxTransactionType

);

}

if (String.isBlank(request.currencyIsoCode)) {

response.setCurrencyIsoCode('USD');

} else {

response.setCurrencyIsoCode(

request.currencyIsoCode

);

}

response.setReferenceEntityId(

request.ReferenceEntityId

);

String country = '';

String shippingState = '';

try {

if (request.ReferenceEntityId != null) {

Id refId = (Id) request.ReferenceEntityId;

String objectName = refId.getSObjectType()

.getDescribe()

.getName();

if (objectName == 'Quote') {

Quote q = [

SELECT ShippingCountry,

ShippingState

FROM Quote

WHERE Id = :refId

LIMIT 1

];

country = q.ShippingCountry;

shippingState = q.ShippingState;

}

else if (objectName == 'Order') {

Order o = [

SELECT ShippingCountry,

ShippingState

FROM Order

WHERE Id = :refId

LIMIT 1

];

country = o.ShippingCountry;

shippingState = o.ShippingState;

}

else if (objectName == 'Invoice') {

try {

List<InvoiceLine> lines = [

SELECT Id,

ShippingAddressId,

ShippingAddress.Country,

ShippingAddress.State

FROM InvoiceLine

WHERE InvoiceId = :refId

AND ShippingAddressId != null

ORDER BY Name ASC

LIMIT 1

];

if (!lines.isEmpty()

&& lines[0].ShippingAddress != null) {

country =

lines[0].ShippingAddress.Country;

shippingState =

lines[0].ShippingAddress.State;

} else {

}

} catch (Exception invoiceHeaderEx) {

}

}

else if (objectName == 'InvoiceLine') {

try {

InvoiceLine il = [

SELECT Id,

ShippingAddressId,

ShippingAddress.Country,

ShippingAddress.State

FROM InvoiceLine

WHERE Id = :refId

LIMIT 1

];

if (il.ShippingAddress != null) {

country =

il.ShippingAddress.Country;

shippingState =

il.ShippingAddress.State;

}

} catch (Exception invoiceEx) {

}

}

else {

}

}

} catch (Exception e) {

}

if (!String.isBlank(country)) {

country = country.trim().toLowerCase();

}

if (!String.isBlank(shippingState)) {

shippingState = shippingState.trim().toLowerCase();

}

Double totalTax = 0.0;

Double totalAmount = 0.0;

List<commercetax.LineItemResponse>

lineItemResponses =

new List<commercetax.LineItemResponse>();

Integer lineCounter = 0;

for (commercetax.TaxLineItemRequest lineItem :

request.lineItems) {

lineCounter++;

commercetax.AddressesResponse addressesRes =

new commercetax.AddressesResponse();

commercetax.AddressResponse addRes =

new commercetax.AddressResponse();

addRes.setLocationCode('locationCode');

addressesRes.setShipFrom(addRes);

addressesRes.setShipTO(addRes);

addressesRes.setSoldTo(addRes);

commercetax.LineItemResponse lineItemResponse =

new commercetax.LineItemResponse();

Double totalLineTax = 0;

List<commercetax.TaxDetailsResponse>

taxDetailsResponses =

new List<commercetax.TaxDetailsResponse>();

for (Integer i = 0; i < 1; i++) {

Double rate = 0.20;

if (country == 'india'

|| country == 'in') {

rate = 0.30;

}

else if (

country == 'usa'

|| country == 'us'

|| country == 'united states'

|| country ==

'united states of america'

) {

Double usaCountryRate = 0.40;

Double stateTaxRate = 0.00;

if (

shippingState == 'utah'

|| shippingState == 'ut'

) {

stateTaxRate = 0.02;

}

else if (

shippingState == 'south dakota'

|| shippingState == 'sd'

) {

stateTaxRate = 0.025;

}

else if (

shippingState == 'minnesota'

|| shippingState == 'mn'

) {

stateTaxRate = 0.03;

}

else if (

shippingState == 'north dakota'

|| shippingState == 'nd'

) {

stateTaxRate = 0.035;

}

else if (

shippingState == 'nebraska'

|| shippingState == 'ne'

) {

stateTaxRate = 0.04;

}

else if (

shippingState == 'new hampshire'

|| shippingState == 'nh'

) {

stateTaxRate = 0.045;

}

else if (

shippingState == 'idaho'

|| shippingState == 'id'

) {

stateTaxRate = 0.05;

}

else if (

shippingState == 'washington'

|| shippingState == 'wa'

) {

stateTaxRate = 0.055;

}

else if (

shippingState == 'vermont'

|| shippingState == 'vt'

) {

stateTaxRate = 0.06;

}

rate =

usaCountryRate +

stateTaxRate;

}

else {

}

Double taxableAmount = lineItem.amount;

commercetax.TaxDetailsResponse

taxDetailsResponse =

new commercetax.TaxDetailsResponse();

taxDetailsResponse.setRate(rate);

taxDetailsResponse.setTaxableAmount(

taxableAmount

);

Double tax =

taxableAmount * rate;

totalLineTax += tax;

taxDetailsResponse.setTax(tax);

taxDetailsResponse.setExemptAmount(0);

taxDetailsResponse.setExemptReason(

'exemptReason'

);

taxDetailsResponse.setTaxRegionId(

'taxRegionId'

);

taxDetailsResponse.setTaxId(

String.valueOf(

getRandomInteger(

0,

2323233

)

)

);

taxDetailsResponse.setSerCode(

'serCode'

);

taxDetailsResponse.setTaxAuthorityTypeId(

'taxAuthorityTypeId'

);

commercetax.ImpositionResponse imposition =

new commercetax.ImpositionResponse();

imposition.setSubType('subtype');

imposition.setType('type');

taxDetailsResponse.setImposition(

imposition

);

commercetax.JurisdictionResponse jurisdiction =

new commercetax.JurisdictionResponse();

jurisdiction.setCountry(country);

jurisdiction.setRegion('region');

jurisdiction.setName('name');

jurisdiction.setStateAssignedNumber(

'stateAssignedNo'

);

jurisdiction.setId('id');

jurisdiction.setLevel('level');

taxDetailsResponse.setJurisdiction(

jurisdiction

);

taxDetailsResponses.add(

taxDetailsResponse

);

}

lineItemResponse.setTaxes(

taxDetailsResponses

);

totalTax += totalLineTax;

totalAmount += lineItem.amount;

commercetax.AmountDetailsResponse amountResponse =

new commercetax.AmountDetailsResponse();

amountResponse.setTotalAmountWithTax(

totalTax + totalAmount

);

amountResponse.setExemptAmount(0);

amountResponse.setTotalAmount(

totalAmount

);

amountResponse.setTaxAmount(

totalTax

);

lineItemResponse.setAmountDetails(

amountResponse

);

lineItemResponse.setEffectiveDate(

System.now()

);

lineItemResponse.setTaxCode(

lineItem.taxCode

);

lineItemResponse.setProductCode(

lineItem.ProductCode

);

lineItemResponse.setLineNumber(

lineItem.linenumber

);

lineItemResponse.setIsTaxable(true);

lineItemResponse.setQuantity(

lineItem.quantity

);

lineItemResponse.setAddresses(

addressesRes

);

lineItemResponses.add(

lineItemResponse

);

}

response.setLineItems(

lineItemResponses

);

commercetax.AmountDetailsResponse

headerAmountResponse =

new commercetax.AmountDetailsResponse();

headerAmountResponse.setTotalAmountWithTax(

totalTax + totalAmount

);

headerAmountResponse.setExemptAmount(0);

headerAmountResponse.setTotalAmount(

totalAmount

);

headerAmountResponse.setTaxAmount(

totalTax

);

response.setAmountDetails(

headerAmountResponse

);

commercetax.AddressesResponse headerAddresses =

new commercetax.AddressesResponse();

commercetax.AddressResponse headerAddRes =

new commercetax.AddressResponse();

headerAddRes.setLocationCode(

'locationCode'

);

headerAddresses.setShipFrom(

headerAddRes

);

headerAddresses.setShipTO(

headerAddRes

);

headerAddresses.setSoldTo(

headerAddRes

);

response.setAddresses(

headerAddresses

);

return response;

}

return null;

}

public static Integer getRandomInteger(

Integer min,

Integer max

) {

return min +

(Integer.valueOf(Math.random()) *

(max - min));

}

}

0/9000

Asset Creation API

 

Asset Creation Link

 

API Information:

 

ENDPOINT URL 

 

/services/data/v66.0/composite

 

METHOD: 

POST

 

 

MESSAGE BODY:

 

 

{

"allOrNone": true,

"compositeRequest": [

{

"method": "POST",

"url": "/services/data/v66.0/sobjects/Asset",

"referenceId": "refAsset1",

"body": {

"AccountId": "001f600000dZWxvAAG",

"Name": "Google Workspace",

"Product2Id": "01tf6000004GVNnAAO",

"ContactId": "003f600000JX730AAD",

"HasLifecycleManagement": true,

"LifecycleStartDate": "2026-01-01T00:00:00.000+0000",

"LifecycleEndDate": "2026-12-31T00:00:00.000+0000",

"CurrentMRR": 250,

"CurrentQuantity": 10,

"TotalLifecycleAmount": 3000

}

},

{

"method": "POST",

"url": "/services/data/v66.0/sobjects/AssetAction",

"referenceId": "refAA1",

"body": {

"AssetId": "@{refAsset1.id}",

"Type": "Generate",

"CategoryEnum": "Initial Sale",

"ActionDate": "2026-01-01T00:00:00.000+0000",

"quantityChange": 10,

"mrrChange": 250,

"amount": 12000,

"TotalInitialSaleAmount": 3000,

"TotalMrr": 250

}

},

{

"method": "POST",

"url": "/services/data/v66.0/sobjects/AssetStatePeriod",

"referenceId": "refASP1",

"body": {

"AssetId": "@{refAsset1.id}",

"startDate": "2026-01-01T00:00:00.000+0000",

"endDate": "2026-12-31T23:59:59.000+0000",

"quantity": 10,

"amount": 0,

"mrr": 250

}

},

{

"method": "POST",

"url": "/services/data/v66.0/sobjects/AssetActionSource",

"referenceId": "refAAS1",

"body": {

"AssetActionId": "@{refAA1.id}",

"transactionDate": "2026-01-01T00:00:00.000+0000",

"adjustmentAmount": 0,

"productAmount": 3000,

"estimatedTax": 0,

"actualTax": 0,

"startDate": "2026-01-01T00:00:00.000+0000",

"endDate": "2026-12-31T00:00:00.000+0000",

"quantity": 10

}

}

]

}

0/9000

We have a product rule set up as follows in Sandbox and Production. Below is the Current Product Rule Configuration.  

 

Product Rule Header: 

  • Type=Selection 
  • Conditions Met = All 
  • Scope = Product 
  • Evaluation Event = Always 
  • Evaluation Order = 10 

Error Condition: 

  • Tested Object = Quote 
  • Tested Field = Boost = True
  • Operator = equals 
  • Filter Type = Value
  •  Filter Value = TRUE 

Price Action 1

  • Product = Product A 
  • Type = Enable 

Price Action 2

  • Product = Product B 
  • Type: Enable & Add 

Price Action 3

  • Product = Product C 
  • Type = Enable & Add 
  • Required = True 

Price Action 4

  • Product = Product C 
  • Type = Hide 

Configuration Rule

:  

Product = Bundle 1  

 

Results in the Configurator

 

In Sandbox the following is occurring in the Configurator:

  • Product A is not appearing
  • Product B is not appearing
  • Product C is appearing and checked

In Production the following is occurring in the Configurator:

  • Product A is appearing
  • Product B is appearing and checked
  • Product C is not appearing

What the Sales team would like to have happen is:

  • Product A is appearing
  • Product B is appearing and checked
  • Product C is appearing and checked

What correction needs to happen to get this to occur? At a minimum I would think I would delete Product Action 4. 

 

Thank you. 

Rachel 

 

#Salesforce CPQ & Billing  #CPQ @* Salesforce Revenue Cloud *

1 risposta
  1. 6 set, 02:36

    Your instinct to delete Price Action 4 is right, and here's why it's likely the actual root cause of the environment difference, not just a cleanup step. 

    You have two Product Actions targeting the same product (Product C) within one rule, with directly contradictory outcomes: Action 3 says Enable & Add + Required, Action 4 says Hide. Unlike Product Rules themselves (which have an explicit Evaluation Order field to control which rule "wins" when multiple rules affect the same product), individual Product Actions within a single rule don't have a documented, configurable sequence field in the UI. When two actions in the same rule conflict like this, which one is applied can come down to internal record creation order - and if this rule was built independently in Sandbox and in Production (rather than deployed as a single unit via change set/package that preserves record order), it's entirely plausible the two environments evaluate Action 3 vs. Action 4 in a different order, which would produce exactly the opposite behavior you're seeing on Product C between the two orgs. 

    Given the outcome the Sales team actually wants — Product C appearing and checked — the fix is straightforward: delete Price Action 4 (Hide on Product C) entirely, and keep only Price Action 3 (Enable & Add, Required) for Product C. That removes the ambiguity rather than relying on action-order behavior that isn't guaranteed to be consistent across orgs. 

    One more thing worth confirming before you conclude it's purely a config issue: since Product A and B's behavior also flipped between environments (not just C), double-check that the Quote.Boost__c field is actually set to TRUE in both orgs during your test — if the condition itself isn't evaluating the same way in both places (e.g., a default value difference on that field between Sandbox and Production data), that alone could explain the whole rule appearing to "not fire" in one environment before you even get to the Product C ordering issue.

0/9000

Hi everyone, Is there a way to populate the Quote field "Region__c" from the Account field "Region__c" using Context Definition only? 

I'm curious if this is achievable purely through Context Definition (without Flow or Apex) — has anyone done this before? Please help. 

Thanks! 

5 risposte
  1. 4 set, 06:43

    @Manish Sharma

     

    Yes, it is possible using

    Context Definition alone. Map a context attribute such as Region from Account.Region__c through the Quote’s Account relationship to Quote.Region__c. No Flow or Apex is required. 

    For example: 

    Account.Region__c → Context Attribute (Region) → Quote.Region__c 

    Make sure the mapping uses supported matching data types and the context definition is active. 

0/9000

We're planning a large migration of legacy Asset records into Revenue Cloud and want to confirm we're not missing a bulk-friendly path. 

 

We've confirmed HasLifecycleManagement, LifecycleStartDate/EndDate, and the underlying AssetStatePeriod object are all read-only via standard DML - Data Loader/Bulk API reject any attempt to write them (INVALID_FIELD_FOR_INSERT_UPDATE). 

 

The only supported path we've found is the Connect REST API generate endpoint (asset-management/assets/actions/generate). It looks like a single-asset-per-call API with no bulk/batch equivalent, and the start date of the first asset state period is locked once the call completes. 

 

Has anyone done a large historical Asset migration into lifecycle management this way? Curious about: 

- Whether a bulk-friendly path exists that we're missing 

- Realistic call volumes/patterns others have used against the generate endpoint 

- Whether it's common practice to leave older/inactive assets non-lifecycle-managed and only onboard active ones 

 

  1. Appreciate any recommendations.

#Revenue Cloud

3 risposte
  1. 30 ago, 15:44

    we did it using PST api. the approach here is to bulk create Order using PST and then activate the Order, it will create Asset lifecycle managed records automatically, this is will give audit history as well.  

    PST api supports bulk record creation (1500 records in a single api call).

0/9000

Hi everyone, 

I'm currently working on attribute-based pricing in Salesforce Revenue Cloud and came across a scenario I'd like some guidance on. 

For example, I have an attribute called Color. If Color = Blue, I want to apply a 5% discount. This pricing rule should apply to every product in my product catalog. 

Using Price Adjustment Schedules , the pricing adjustment is tied to a specific product. This works well for a small catalog, but in a large product catalog with thousands of products, creating and maintaining separate Price Adjustment Schedules for each product is time-consuming and difficult to manage. 

Is there a way to define the pricing logic once and have it apply to all products instead of configuring it product by product? 

I'd appreciate any suggestions or best practices. Thanks!   

 

@* Salesforce Revenue Cloud * 

2 risposte
  1. 2 set, 20:43

    For something like this id recommend using the Pre hook to write the Attribute value say "Colour" to a "Colour" Field on the quote line. 

     

    You could then add into your pricing procedure to add a 5% discount if that colour field = "Blue"

0/9000

Specifically, how are you managing dunning, payment reminders, and collections follow-up? Built in-house with Flow, a third-party AR tool, or still mostly manual/spreadsheet-based?  

 

Disclosure: I work on Quick Receivable, a Salesforce-native AR automation app. I'm trying to understand what's actually working for teams before assuming we have the answer

2 risposte
  1. 2 set, 10:07

    That matches what we've been hearing too. Flow covers the "send a reminder" part fine, but promises to pay and exception handling (partial payments, disputed invoices, escalation rules) need actual state tracking, and that's where Flow logic gets brittle fast.  

     

    Curious when collections got messy for you, was it more the volume of exceptions, or just not having a clean audit trail of who promised what and by when?

0/9000
Aadhar Agarwal ha fatto una domanda in #Revenue Cloud

What I'm building

A custom Lightning Web Component that embeds inside a cloned Product Configurator Screen Flow (the standard "Save As" third-party-configurator extension pattern — lightning__FlowScreen). The component calls the Product Configurator Business APIs directly via Apex HTTP callout (Named Credential auth, OAuth 2.0 Client Credentials Flow via an External Client App — not UserInfo.getSessionId(), which is rejected for interactive-UI sessions anyway).

Environment

  • Developer Edition org with Revenue Cloud / Agentforce Revenue Management enabled (enableProductConfigurator = true)
  • API version v64.0
  • Not a scratch org, no source tracking — deployed directly
  • Native in-app configurator UI works correctly for the running user; this is only about the headless REST layer

What works

POST /services/data/v64.0/connect/cpq/configurator/actions/configure — works reliably. Returns transactionContext.SalesTransaction[].SalesTransactionItem[], prices lines correctly, runs configuration rules, surfaces rule violations in messages. This endpoint alone is not gated.

What fails

Every other documented action in the same family returns a 403:

 

POST /services/data/v64.0/connect/cpq/configurator/actions/load-instancePOST /services/data/v64.0/connect/cpq/configurator/actions/get-instancePOST /services/data/v64.0/connect/cpq/configurator/actions/add-nodesPOST /services/data/v64.0/connect/cpq/configurator/actions/save-instance

Response body:

 

{  "errorCode": "FUNCTIONALITY_NOT_ENABLED",  "message": "[IHeadlessConfiguratorFamily]"}

(403 status, same error regardless of payload shape or whether the call carries a transactionContextId.) 

 

#Revenue Cloud  #Salesforce Revenue Cloud  #Lightning Product Setup Configurator  #CPQ  #Revenue Management System @* Salesforce Revenue Cloud *

3 risposte
  1. 2 set, 03:56

    Hi @Christopher Strecker

    , That's the missing piece. By assigning "Product Configurator API User" permission to my user, I was able to connect without any error. 

    Hi , That's the missing piece. By assigning

     

     

0/9000

I have created a product category disqualification.  But, under quote when I click "Browse Catalogs" that particular category is visible.  I have even refreshed decision tables(Product Qualification, Product Disqualification) but still it isn't working.  Can anyone help me?     @* Salesforce Revenue Cloud * 

2 risposte
0/9000