Tuesday, March 7, 2023

Business rule engine which would fullfill most common usecases in Salesforce

Building a business rule engine requires a lot of planning and consideration of different use cases. Below is an example of how to implement a simple business rule engine in Salesforce that fulfills common use cases: First, we need to define the rules in a way that can be easily configured and maintained. We can use custom metadata types to store the rules and their associated actions. Each rule will have a set of conditions that must be met, and an action that should be performed when the conditions are true. Next, we need to create a trigger that will evaluate the rules when records are created or updated. This trigger will loop through all the rules and check if the conditions for each rule are met. If the conditions are met, the trigger will execute the associated action for that rule. Here's an example code for the trigger: The Business_Rule__mdt custom metadata type will store the rules and their associated actions. It will have two fields, Conditions__c and Action__c, which will contain the conditions and actions for each rule. The evaluateConditions method will parse the conditions and evaluate them based on the data in the records. The exact implementation will depend on the format of the conditions. The executeAction method will perform the specified action on the records that meet the conditions. The exact implementation will depend on the actions that are defined. With this basic framework in place, we can add more complex functionality as needed, such as support for different types of conditions and actions, the ability to chain rules together, and the ability to specify rule priority.

Solution to overcome Heap Size error in Salesforce

When building Lightning Web Components (LWC), we may encounter the "Total heap size as 12 MB" error when working with large data sets or complex logic. This error occurs when the total size of data stored in memory (heap) exceeds 12 MB. To overcome this error, we can implement the following best practices: Use @wire to retrieve data from Apex instead of retrieving it directly in the component. This allows Salesforce to handle the data retrieval and pagination, reducing the amount of data stored in memory. Use LightningDatatable with pagination to avoid loading all data at once. Use track decorators to prevent unnecessary re-renders of the component. Avoid storing large amounts of data in arrays or objects, and use iterators to process the data in smaller chunks. Use a setTimeout function to break up long-running operations into smaller chunks and avoid blocking the main thread. Use @api to pass data between components instead of storing it in the component. Here's an example code that demonstrates some of these best practices: In this example, we're using @wire to retrieve contacts from an Apex controller. We're then using LightningDatatable to display the data with pagination. We're also using @track to ensure that only the changed data is re-rendered, and we're storing the data in an array with a getter that is only called once when the component is initialized. By following these best practices, we can reduce the amount of data stored in memory and avoid the "Total heap size as 12 MB" error in our LWC.

Friday, June 20, 2014

Configured Time Based Workflow for 5 mins or 10 or 15 etc... in salesforce

Salesforce supports only for hours and days time based workflows.But Some times we want to fire time based workflows for every 5 mins or 10 mins or 15mins etc..

I read @jdavidson909 article.This article will helpful for many developers to test time based workflow ,no need to wait for 1hr .simply  configure its to 5 mins and then developer can test easily .

First, on the object that you need the workflow on, create a new custom formula field that evaluates to a Date/Time value.  I called my field Trigger Time 05, meaning that it’s a time trigger that I use to fire a workflow in 5 minutes.
What Trigger Time 05 actually does is saves a Date / Time value to your record that is 55 minutes in the past.  If you save your record at 3:00 pm, the value in Trigger Time 05 will be 2:05 pm.
The formula for Trigger Time 05 = (Now() – 0.038)
Then, you write a Time Based Workflow rule that fires 1 hour after Trigger Time 05.  So, one hour after a time 55 minutes ago… is 5 minutes from now!
If you have multiple time intervals you need workflows to fire at, you’ll need to create multiple Trigger Time formula fields, like Trigger Time 05, Trigger Time 15, Trigger Time 30, etc.
I have found that the time intervals that the workflow rules aren’t exactly five minutes, but they are pretty close.
As with many of the other custom formula fields I’ve mentioned on this blog, you’ll want to make this field accessible to all users, but don’t put it on any page layouts.
Here’s a chart that shows the value you’ll need to subtract from Now() for each 5 minute interval.
Value in Formula
Minutes Ago
Will Fire In
 0.04145
60
Minutes
0
Minutes
 0.03800
55
Minutes
5
Minutes
 0.03455
50
Minutes
10
Minutes
 0.03109
45
Minutes
15
Minutes
 0.02764
40
Minutes
20
Minutes
 0.02418
35
Minutes
25
Minutes
 0.02073
30
Minutes
30
Minutes
 0.01727
25
Minutes
35
Minutes
 0.01382
20
Minutes
40
Minutes
 0.01036
15
Minutes
45
Minutes
 0.00691
10
Minutes
50
Minutes
 0.00345
5
Minutes
55
Minutes
 0.00069
1
Minute
59
Minutes

Sometimes you may only want the validation rule to prevent saves for some people

Sometimes you may only want the validation rule to prevent saves for some people. In that case, I like to use a hierarchical custom setting so I can turn off validation rules for the entire org, specific profiles or specific users. In your validation rule formula, you can reference hierarchical settings using $Setup.Setting_Name__c.Field_Name__c.
So, putting it all together, here is what I think a good validation rule should look like:
validation rule example

Source from : http://www.verticalcoder.com/

Friday, June 6, 2014

Important Summer 14 Release Notes

Hi, There are so many interesting things come in Summer 14 Release.Below are some important points.

Increased the size limit for attachments to objects from 5 MB to 25 MB.
Increased the size limit for incoming email messages from 10 MB to 25 MB.
The limit has been raised from three to seven for external IDs on custom fields
Increased the size limit for email messages that come in through On-Demand Email-to-Case from 10MB to 25MB,

Salesforce 1 :
Users can now submit records for approval from the Salesforce1 app.

Opportunity Splits:
Complete Customization Available for Opportunity Splits
You can customize opportunity splits in these ways:
• Add custom fields
• Set up validation rules
• Set up triggers
• Edit page layouts

Forecast :
Now you can Custom Field Forecasts.
Report on Historical Forecasting changes .
Track and Predict Revenue from Custom Opportunity Fields

PriceBook Entries:
Now You can Customize the PriceBook Entries.If your price book entry object has custom fields set as Required, you can’t create price book entries in theSalesforce user interface. You can create price book entries only by using Data Loader or the API.

Order :
Automatically create an order with order products from an opportunity or quote. You can also generate and relate the order to a contract.


Open CTI :
Open CTI helps partners integrate Salesforce with Computer-Telephony Integration (CTI) systems without installing adapter programs on call center users’ machines.

Ask questions and get answers in Chatter with Chatter Questions.


Batch Apex:
Submit more batch jobs simultaneously and actively manage the order of the queued jobs.Up to 100 batch jobs can be in the holding status.
You can monitor and reorder batch jobs that are held in the flex queue in the Salesforce user interface. To do so, from Setup,
click Jobs > Apex Flex Queue

Future Method :
Avoid reaching governor limits in your asynchronous future method by running your method with double or triple capacity for a resource.
@future(limits='2xHeap') Heap size limit is doubled (24 MB).
@future(limits='3xHeap') Heap size limit is tripled (36 MB).
@future(limits='2xCPU') CPU timeout is doubled (120,000 milliseconds).
@future(limits='3xCPU') CPU timeout is tripled (180,000 milliseconds).
@future(limits='2xSOQL') Number of SOQL queries limit is doubled (400).
@future(limits='3xSOQL') Number of SOQL queries limit is tripled (600).
@future(limits='2xDML') Number of DML statements limit is doubled (300).
@future(limits='3xDML') Number of DML statements limit is tripled (450).
Number of records that were processed as a result of DML
operations is doubled (20,000).
@future(limits='2xDMLRows')1
Number of records that were processed as a result of DML
operations is tripled (30,000).









Monday, April 21, 2014

Salesforce Integration with Twilio

Hi guys,

  For instance ,whenever contact is created or updated,Customer can get the welcome call or any custom voice message.

 for this i created "CustomerType" Picklist,based on this picklist customer will receive the call.

 Values of Picklist: Gold,Silver

 For below example ,call will send only for "Gold" type customers.

 First of all we have to create an account on twilio website. Twilio website provides two type of account .

a.) Free account:-   In this type account you can call to any number around the world, but the number  from which you call should be registered with twilio.

b.) Paid account:-  In this type account you can purchase new number, can port your number with twilio and can send sms also. With this account you can also use many other premium facilities like you can create client app and can use interactive deshboard etc.

But for now we will create only free account as follow:-

a.) Open  https://www.twilio.com/try-twilio and create an account

b.) Verify Your number by request a call or sms and then enter code which you get from call

c.)   Now the twilio will give you a chance to select a number.

 Add remote site settings :  https://www.twilio.com

BatchApex: As Of now triggers are not supporting Callouts , so we are going to creating batchapex and executing using apex trigger.

Batch Apex: 

global class TwiloBatchapex implements  Database.batchable<Sobject>,Database.AllowsCallouts{

Public string query ='Select id,CustomerType__c from Contact';

global Database.QueryLocator start(Database.BatchableContext BC) {
    return Database.getQueryLocator(query);
 }

     global void execute(Database.BatchableContext BC, List<Contact> records) {        
       String account = 'xxxxxxxxxxxxxxxxxxxxxxxx';
String token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
TwilioRestClient client = new TwilioRestClient(account, token);

Map<String,String> params = new Map<String,String> {
        'To'   => 'xxxxxxxxx',
        'From' => 'xxxxxxxxxxxx',
        'Url' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    };
TwilioCall call = client.getAccount().getCalls().create(params);
       }
 

    global void finish(Database.BatchableContext BC){
       //you can also do some after-the-job-finishes work here
    }

}

Trigger : 

trigger Sampletwilo on Contact (after insert,after update) {
 List<Contact> conList = new List<Contact>();
 for(Contact con : trigger.new){
     if(con.CustomerType__c =='Gold')
        conList.add(con);
 }
    if(conList.size() > 0)
      database.executebatch(new TwiloBatchapex(),200);
}

Hope so this will help you guys,

Sunday, April 13, 2014

Auto populate Primary contact role Email Id as ‘To’ and Non Primary Contact Roles Emails as ‘CC’ List.

Hello,


Scenario  : Client want to send Emails to Primary contact role as well as non primary contact roles,also in the form of Auto populate Primary contact role Email Id as ‘To’ and Non Primary Contact Roles Emails as ‘CC’ List .


Below  are the steps to follow.

Steps to Create List Button:
1) Create List Button On Task Object. 
2) Content Source type should be URL.
3) Give Url :/apex/SupportSalesOptyEmailMgmtPage?eid={!Opportunity.Id}

Visualforce Page:
<apex:page standardController="opportunity" extensions="SupportSalesOptyEmailMgmtPage" action="{!populateEmailRecipients}">
</apex:page>
Apex Class:
/** * File Name: 
* Description : Auto populate Primary contact role Email Id as ‘To’ and Non Primary Contact Roles Emails as ‘CC’ List.
* */ 
public class SupportSalesOptyEmailMgmtUtil {

    Public List<OpportunityContactRole> oppcontactrole{get;set;}
    Public List<OpportunityContactRole> con{get;set;}
    Public ID opp{get;set;}

    public SupportSalesOptyEmailMgmtUtil(ApexPages.StandardController controller) {
        List<OpportunityContactRole> oppcontactrole = new List<OpportunityContactRole>();
        
    }
    
    public PageReference populateEmailRecipients() {
       // Getting current opportunity ID
        opp = ApexPages.currentPage().getParameters().get('eid')
      //Querying for Primary Contact Role
        con  = [select ContactId from OpportunityContactRole where IsPrimary=true and OpportunityId=:opp Limit 1] ;
     // Querying for non-Primary Contact Roles Emails
        oppcontactrole = [Select Contact.Email from OpportunityContactRole where IsPrimary=false and OpportunityId=:opp];
   // If there are more than One non primary contact roles ,those email should be an comma separated.       
   String EmailCCList = '';
        for(OpportunityContactRole  opprole : oppcontactrole){
            if (opprole.Contact.Email!=null && !opprole.Contact.Email.equals(''))
            if (EmailCCList.equals('')){
                EmailCCList = opprole.Contact.Email;
            } else {
                EmailCCList = EmailCCList + ',' + opprole.Contact.Email;
            }
        }
        String primaryContactId = '';
        if (con.size()>0){
            primaryContactId = con[0].ContactId;
        }
        PageReference p = new PageReference('/_ui/core/email/author/EmailAuthor?p2_lkid='+primaryContactId+'&p3_lkid='+opp+'&rtype=003&p4='+EmailCCList+'&retURL='+opp); 
        p.setRedirect(true);
        return p;
    }   
}