top of page

How to Display Error Messages or Alerts in Salesforce CPQ Using a Custom Object

Updated: Dec 1, 2023


Link Github : https://github.com/AourLegacy/AourFactory/tree/Alerts

Salesforce CPQ (Configure, Price, Quote) is a robust tool designed to swiftly and accurately configure, price, and quote products. Occasionally, there's a need to flash error messages or alerts during a quote's configuration process. In this article, we'll explore how this can be achieved using a custom object to store product and error code information.

Background :

Imagine you have a plethora of products in your catalog, and some of them have specific statuses or conditions that warrant special communication to users when added to a quote. For instance, a product might be in an early launch phase or phasing out. In these instances, you'd want to inform your users about the status of these products.

The Solution


The ideal way to handle this is to store this status information in a custom object (e.g., `ProductSetting__c`). This object could house fields like `Product__c` (the product) and `Status__c` (the error code or status).

Here's how this could be executed:


1. Creating the Custom Object: Initially, you should have a `ProductSetting__c` object with the necessary fields in place.

2. Integrating with the CPQ Process: When products get added to the `quoteLine`, a check against this object is imperative to determine if there are any alerts or error messages to be displayed.

Implementation :

This code initializes a query that fetches the product settings based on the quote lines. It then traverses these settings to ascertain whether any alerts or messages are warranted. If a product in the quote has a status that calls for an alert, that alert is then shown to the user.

For instance, if the status is `"S1-X3"`, this might imply that the product is in an early launch phase. The user would then see a message prompting them to reach out to the marketing team for product availability.


export function errorMessage(quote, lines, conn) {
  console.log("Start: errorMessage");
  // FIXME : name this variable products to be consistent
  var productArray = [];

  // FIXME : simplify
  // var products = lines.map((line) => line.record.SBQQ__Product__c);
  lines.forEach(function (line) {
    productArray.push(line.record.SBQQ__Product__c);
  });
  console.log(" productArray");
  console.log(productArray);

  var productList = "('" + productArray.join("', '") + "')";
  var subsidiary = [quote.record.CPQ_Subsidiary__c];
  var subsidiaryList = "('" + subsidiary.join("', '") + "')";

  var queryStringProductSetting =
    "SELECT Id, Product__c, Status__c FROM ProductSetting__c ";
  queryStringProductSetting +=
    "WHERE Product__c IN " +
    productList ;

  console.log("error queryStringProductSetting : " + queryStringProductSetting);

  var mapProductStatusComb = new Map();

  console.log("28. Fetch SF product status");
  return new Promise((resolve) =>
    conn
      .query(queryStringProductSetting)
      .then(function (results) {
        console.log("29. SF product status fetched");
        // FIXME : early return if no results
        if (results.totalSize) {
          results.records.forEach(function (record) {
            mapProductStatusComb.set(
              record.Product__c,
              record.Status__c
            );
          });
        }
        console.log("error mapProductStatusComb");
        console.log(mapProductStatusComb);

        var errorMessage = "";
        var statusComb;
        var br = "/n";
        var productCodesInMessage = [];
        lines.forEach(function (line) {
          if (
            !productCodesInMessage.includes(line.record.SBQQ__Product__c) &&
            mapProductStatusComb.has(line.record.SBQQ__Product__c)
          ) {
            console.log(
              "error line.record.SBQQ__Product__c" +
                line.record.SBQQ__Product__c
            );
            productCodesInMessage.push(line.record.SBQQ__Product__c);
            statusComb = mapProductStatusComb.get(line.record.SBQQ__Product__c);
            console.log(line.record.SBQQ__ProductName__c);
            if (statusComb != undefined) {
              if (statusComb == "S1-X3") {
                console.log("S1-X3");
                errorMessage += "The product ";
                errorMessage += line.record.SBQQ__ProductName__c;
                errorMessage +=
                  " is in early launch phase. Please contact your marketing team for product availability. ";
              } else if (statusComb == "SL-X3") {
                errorMessage += "The product ";
                errorMessage += line.record.SBQQ__ProductName__c;
                errorMessage +=
                  ' status is in "ATCC Block ".Please contact your supply chain for product availability. ';
              } else if (statusComb == "SZ-X3") {
                console.log("SZ-X3");
                errorMessage += "The product ";
                errorMessage += line.record.SBQQ__ProductName__c;
                errorMessage +=
                  ' status is in "Material Shortage Block". Please contact your marketing team for product availability. ';
              } else if (statusComb == "S2-X4") {
                errorMessage += "The product ";
                errorMessage += line.record.SBQQ__ProductName__c;
                errorMessage +=
                  " is being phased out. Please contact your marketing team for product availability. ";
              } else if (statusComb == "SL-X4") {
                errorMessage += "The product ";
                errorMessage += line.record.SBQQ__ProductName__c;
                errorMessage +=
                  ' status is in "ATCC Block ". Please contact your supply chain for product availability. ';
              } 
            }
          }
        });
        if (errorMessage != "") {
          window.alert(errorMessage);
        }
        resolve();
      })
      .catch((err) => {
        console.log(err);
        resolve();
      })
  );
}

Conclusion


By leveraging a custom object to store product status information and embedding this within the CPQ process, you can seamlessly communicate pivotal information to your users dynamically. This strategy ensures the freshest and most pertinent information is always at the fingertips of those configuring quotes, thereby promising a better user experience and streamlined business processes.

9 views0 comments

Recent Posts

See All

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page