+ Start a Discussion
Harjeet Singh 13Harjeet Singh 13 

How can I calculate and store hash value based on multliple picklist field value

Dear All,

I am working on a requiremnts which states something as belows:
Craete a new field on Account object which will calculate and store hash value based on a multiple picklist field field "Products" (Products__c)on account object.

Products(Products__c) field have below mentioned values:
  • Baha
  • Vistafix
  • Codacs
  • Hybrid
  • Nucleus
  • CI
  • Acoustic
Solution Approached by me:
I have craeted 1 numer field on Aaccount Object as ProductsHash__c and created 1 trigger as below:
trigger CalculateHash on Account (before insert,before update) { 

public void beforeInsert(Account newAcct){ 

AccountPopulator.populateProductsHash(null, newAcct); 
}
 public void beforeUpdate(Account oldAcc, Account newAcc){ 

AccountPopulator.populateProductsHash(oldAcc, newAcc);
 }
 }
Below is my class:
public class AccountPopulator{ 
public static void populateProductsHash(Account oldAcct, Account newAcct){

 if(oldAcct == null || oldAcct.Products__c != oldAcct.Products__c){ newAcct.ProductsHash__c=System.hashCode(Account.Products__c)‌​; 
}
 
}
 }

Problem Encouter:
Nothing is happening. The newly created field Products_Hash__c on account object is calculating nothing and storing nothing based on the Paroducts__c field on Account​.
Kindly help me what I am doing wrong or what I am missing.

Any help will be greatly appreciated!

Thanks in advance

Thanks & Regards,
Harjeet

 
v varaprasadv varaprasad
Hi Harjeet,


Please check once below code : 
=================Trigger Code=============
 trigger CalculateHash on Account (before insert,before update) { 
    
    If(Trigger.isBefore&&(Trigger.isInsert || trigger.isUpdate)){
        AccountPopulator.populateProductsHash(Trigger.new);        
    }
}

==========Class Code ======================== 
 public class AccountPopulator{ 
    public static void populateProductsHash(list<account> lstAccs){
        for(account acc : lstAccs){
            if(acc.Products__c != null){
			//If ProductsHash__c has text field you need to add string.valueof or it is number field you can assingn directly //system.hashCode(acc.Products__c)
                acc.ProductsHash__c = string.valueOf(system.hashCode(acc.Products__c)); 
            }
        }
      
    }
}
Trigger Best Practices : 

1) One Trigger Per Object
A single Apex Trigger is all you need for one particular object. If you develop multiple Triggers for a single object, you have no way of controlling the order of execution if those Triggers can run in the same contexts

2) Logic-less Triggers
If you write methods in your Triggers, those can’t be exposed for test purposes. You also can’t expose logic to be re-used anywhere else in your org.

3) Context-Specific Handler Methods
Create context-specific handler methods in Trigger handlers

4) Bulkify your Code
Bulkifying Apex code refers to the concept of making sure the code properly handles more than one record at a time.

5) Avoid SOQL Queries or DML statements inside FOR Loops
An individual Apex request gets a maximum of 100 SOQL queries before exceeding that governor limit. So if this trigger is invoked by a batch of more than 100 Account records, the governor limit will throw a runtime exception

6) Using Collections, Streamlining Queries, and Efficient For Loops
It is important to use Apex Collections to efficiently query data and store the data in memory. A combination of using collections and streamlining SOQL queries can substantially help writing efficient Apex code and avoid governor limits

7) Querying Large Data Sets
The total number of records that can be returned by SOQL queries in a request is 50,000. If returning a large set of queries causes you to exceed your heap limit, then a SOQL query for loop must be used instead. It can process multiple batches of records through the use of internal calls to query and queryMore

8) Use @future Appropriately
It is critical to write your Apex code to efficiently handle bulk or many records at a time. This is also true for asynchronous Apex methods (those annotated with the @future keyword). The differences between synchronous and asynchronous Apex can be found

9) Avoid Hardcoding IDs
When deploying Apex code between sandbox and production environments, or installing Force.com AppExchange packages, it is essential to avoid hardcoding IDs in the Apex code. By doing so, if the record IDs change between environments, the logic can dynamically identify the proper data to operate against and not fail.

Few more Best Practices for Triggers
There should only be one trigger for each object.
Avoid complex logic in triggers. To simplify testing and resuse, triggers should delegate to Apex classes which contain the actual execution logic. See Mike Leach's excellent trigger template for more info.
Bulkify any "helper" classes and/or methods.
Trigers should be "bulkified" and be able to process up to 200 records for each call.
Execute DML statements using collections instead of individual records per DML statement.
Use Collections in SOQL "WHERE" clauses to retrieve all records back in single query
Use a consistent naming convention including the object name (e.g., AccountTrigger)


Hope it helps you.
Please let me know in case of any other assistance.

Thanks
Varaprasad





 
Harjeet Singh 13Harjeet Singh 13
Dear Varaprasad,

Thanks for your quick response and yes its helpful to me.

I just checked afetr modifying my code as suggested by you and now ProductHash__c is updating with some Hash Value.
When I am selecting Product field as "Baha" then ProductHash__c becomes 2,062,744
When I am selecting Product field as "Vistafix" then ProductHash_c becomes 1,658,911,368

Now I have below 2 queries. Kindly answers/resolves them:

1. Since "Products" field is a multiple picklist field so an user can select more than 1 value in that case how hash will be calculated and stored in ProductHash__c field. Just now I checked I selected "Products" as "Baha" and "Vistafix" both and the resultant ProductHash__c was 58,351,915.
Now my question is suppose an user is selecting more than 1 value for "Products"  then how can we store hash value in "ProductHash__c" as addition of both numbers. Lets say if Baha is 2,062,744 and Vistafix is 1,658,911,368 and an user selects both the values then upon saving value in ProductHash__c field will be Baha+Vistafix= 1609744112.

2. Suppose  I need to calculate/store in ProductHash__c field based on below figures:
If Product selected is Baha then value stores in ProductHash__c will be 1,If Product selected is Vistafix then value stores in ProductHash__c will be 4 and if an user selects more than 1 value lets say Baha and Visaflix then value stores in ProductHash__c will be 1+4=5. Kindly refer below small table for more illustration
1 = Nucleus
2 = Baha
4 = Vistafix
8 = Hybrid
16 = Referral Clinic (For Sweden)
32 = Acoustic
Just add the numbers up if the "Products" provides more than one service. For example:
Nucleus + Baha = 1+2 = 3
Nucleus + Baha + Vistafix = 1+2+4 = 7

Kindly help me in 2nd use case

Any help will be greatly appreciated!

Thanks in advance

Thanks & Regards,
Harjeet

 
v varaprasadv varaprasad
Hi Harjeet,

We cant do like that hashcode is defined by the system.

For more info please check once below link : 
https://www.javaworld.com/article/2073618/java-s-system-identityhashcode.html
https://www.easydcp.com/support-faq.php?id=35


Hope it helps you.
If it helps you, please mark is as best answer, so it will be helpful for other developers.

Thanks
Varaprasad

 
Harjeet Singh 13Harjeet Singh 13
Dear Varaprasad,

Thanks for your response and link which you have shared to me. But the use case which I need to implement is like that only.I sthere any workaround o achieve the same OR is there any way atleast Product_Hash__c field will calculate and store correct summation if Products field has more than 1 service.Lets say if Baha is 2,062,744 and Vistafix is 1,658,911,368 and an user selects both the values then upon saving value in ProductHash__c field will be Baha+Vistafix= 1609744112.

I hope you can help me and rely on you and again on your quick response.

Any help will be greatly appreciated!

Thanks in advance

Thanks & Regards,
Harjeet
v varaprasadv varaprasad
Hi Harjeet,

Before changing your code just collect each picjlist value hashcode in one notepad.
 
Example :

'TS', 2687;
'AP', 2095;

add above hashcodes in below class : 

Please check once below code : 
 
public class AccountPopulator{ 
    public static void populateProductsHash(list<account> lstAccs){
        map<string,integer> mapOfHashCodes = new map<string,integer>();
        mapOfHashCodes.put('TS', 2687);
        mapOfHashCodes.put('AP', 2095);
        mapOfHashCodes.put('BR', 2128);
        
        
        for(account acc : lstAccs){
            if(acc.States__c != null){
                system.debug('==acc.States__c=='+acc.States__c);
                string states = acc.States__c;
                list<string> allStates = states.split(';');
                system.debug('==allStates=='+allStates);
                
                integer total = 0;
                for(string st : allStates){
                    total = total + mapOfHashCodes.get(st);
                }
                
                system.debug('==total='+total);
                //list<string> states = acc.States__c;
                //mapOfHashCodes.containsKey(acc.States__c);
				acc.Site = string.valueOf(total);
            }
        }
      
    }
}

Hope this helps you.

Thanks,
Varaprasad 
Salesforce Developer
more:  varaprasad4sfdc@gmail.com







 
Harjeet Singh 13Harjeet Singh 13
Dear Varaprasad,

Thanks for your quick response again.

I modified my code as per your suggestion above.Below is my observations:
1. I selected "Products" field value as 'Baha' and 'Vistafix'. Hash code value of 'Baha' is '2062744'and Hssh code for 'Vistafix', is '1658911368'.
So as per code the hash value which will be calculated inHash_Products__c field would be Baha+Vistafix, 2062744+1658911368='2025802193'.

 In UI value stored in Hash_Products__c is 2025802193 which is correct.Also I checked with multiple values and for all values the value calculated and stored in Hash_Products__c field is correct.

I dont know whether solution provided by me really what actual requirement demands for. 

If you see my question above clearly there I have mentioned 2 use case 1 and 2 .Solution which I am providing after modifying my code as per your suggestion is an adulterant of both usecase. I need hash value needs to be stored in a new field which is happening(correct). I also need when an user selects more than 1 values in Products field then in HashProduct__c field will store summation of all teh value selected for Products field which again happening correctly now.

Only thing which we differes from actual requiremnt is I guess Use case no 2 in my previous/earlier question.Lets say If user selects Baha as Products then Value stored in HashProduct__c will be 2 and if an user selects Vistafix as Product value then value stored in HashProducts__c will be 4. But if an user selects Baha and Vistafix as value in Products then va;ue stores in HashProducts__c will be 2+4=6. Instead of storing value as 2 and 4 for Baha and Vistafix respectively UI is storing 2062744 and 1658911368 for Baha and Vistafix.

I am happy of your solution but I am not sure whether that works. I am still trying to findout any workaround/solutions for the same.

Kudos to you for your excellent support and all quick responses

Any help will be greatly appreciated!

Thanks in advance

Thanks & Regards,
Harjeet