function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SpunkySpunky 

synchronize picklist values

Hoping someone can help-i'v been at this for some time and it's 3am and i just cant think straight anymore and I'm not a developer.

 

This is really urgent as the stage field is incorrectly updating for a particular record type and I would truly appreciate any assistance with my trigger,

 

I have a trigger on opportunities to sync fields on insert and on update.

 

The use case is;

All StageNames have a corresponding  sales stage value

 

What I need is

if the sales stage is updated, then the sales stage should automatically be updated to the defined value 

alternatively, if the stage name is updated-then I need the sales stage to be dynamically updated

How do I keep both synchronized?

 

My code updates the stage name if sales stage is changed but it won't update the sales stage if stage name is changed

 

 

 

trigger sync on Opportunity (before update,before insert) {
For (Opportunity opp:Trigger.new) {
   if (opp.recordtypeid=='012C0000000GBxA'){
if(opp.stagename=='closed')opp.sales_stage__c='closed';     
if (Trigger.isupdate){
   if(opp.Sales_Stage__c == 'Recognition' ){opp.StageName='Determining Differentiated Problems';}
   if(opp.Sales_Stage__c == 'Determine Needs'){opp.StageName='Confirming Vision Match';}
   if(opp.Sales_Stage__c == 'Evaluate Options'){opp.StageName='Confirming Value and Power';}
   if(opp.Sales_Stage__c == 'Resolve Concerns'){opp.StageName='Finalizing Mutual Plan';}
   if(opp.Sales_Stage__c == 'Negotiate'){opp.StageName='Negotiating';}
   if(opp.Sales_Stage__c == 'Closed'){opp.StageName='Closed';}
   if(opp.Sales_Stage__c == 'Lost'){opp.StageName='Lost';}
   if(opp.Sales_Stage__c == 'No Decision'){opp.StageName='No Decision';}
   if(opp.Sales_Stage__c == 'Opportunity Identified'){opp.StageName='Opportunity Identified';}
   if(opp.Sales_Stage__c == 'Prospecting'){opp.StageName='Prospecting';}
   }

}
   }
   }

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

My favorite method for this type of problem is a map:

 

 

trigger sync on Opportunity (before update,before insert) {
  // record type map. makes checking the record type dynamic by name.
  Map<String,Id> recordTypeNames = new Map<String,Id>();

  // map the sales stage to the opportunity stage.
  map<string,string> salesToOpp = new map<string,string> {
    'Recognition' => 'Determining Differentiated Problems',
    'Determine Needs' => 'Confirming Vision Match',
    'Evaluate Options' => 'Confirming Value and Power',
    'Resolve Concerns' => 'Finalizing Mutual Plan',
    'Negotiate' => 'Negotiating',
    'Closed' => 'Closed',
    'Lost' => 'Lost',
    'No Decision' => 'No Decision',
    'Opportunity Identified' => 'Opportunity Identified',
    'Prospecting' => 'Prospecting'
  };

  // also map them in reverse, dynamically.
  map<string,string> oppToSales = new map<string,string>();
  for(string key:salesToOpp.keySet())
    oppToSales.put(salesToOpp.get(key),key);

  // load up the record type names for dynamic usage.
  for(RecordType rt:[select id,developername from recordtype where sobjecttype='opportunity'])
    recordtypenames.put(rt.developername,rt.id);

  // for each record in our trigger...
  for(opportunity opp:trigger.new) {
    // if it's the wrong record type, go to the next record.
    if(opp.recordtypeid == null || opp.recordtypeid != recordtypenames.get('RecordTypeToCheckFor'))
      continue;

    // If the sales stage has changed, and is valid, change the opportunity stage name.
    // NOTE: If it's an insert, sales stage takes precedence over stage name.
    // Reverse this if statement with the next to change this priority.
    if(salesToOpp.containsKey(opp.sales_stage__c) && (Trigger.isInsert || Trigger.oldMap.get(opp.id).Sales_Stage__c != opp.Sales_Stage__c))
      opp.stagename = salesToOpp.get(opp.sales_stage__c);

    // if the opportunity stage has changed, and is a valid change, change the sales stage.
    if(oppToSales.containsKey(opp.stagename) && (Trigger.isInsert || Trigger.oldMap.get(opp.id).StageName != opp.Stagename))
    opp.sales_stage__c = oppToSales.get(opp.stagename);
  }
}

 This will cause a synchronization both ways, although if stage name and sales stage are changed both at the same time, sales stage will take precedence over the sales stage.

 

All Answers

Ritesh AswaneyRitesh Aswaney

Hey

Have you checked that the Case in your statement is correct

 

if(opp.stagename=='closed')

opp.sales_stage__c='closed';

 

Should it read

 

if(opp.stagename=='Closed')opp.sales_stage__c='Closed'; i.e. a CAPITALISED C in Closed

 

If you'd like to ignore case, you could use

 

if(opp.stagename.toLowerCase() =='closed')

opp.sales_stage__c='closed';

SpunkySpunky

I'll give it a try.

 

Maybe I'll restate the use case -it might be a bit more coherent than it was at 3am:)

 

Ideally I would like to SET the values in the sales stage field. 

so if stage =x, sales stage = y (these values are fixed)

Then if the sales stage" is changed, the trigger should update  the " stage name"

 

 

 

 

 

 
sfdcfoxsfdcfox

My favorite method for this type of problem is a map:

 

 

trigger sync on Opportunity (before update,before insert) {
  // record type map. makes checking the record type dynamic by name.
  Map<String,Id> recordTypeNames = new Map<String,Id>();

  // map the sales stage to the opportunity stage.
  map<string,string> salesToOpp = new map<string,string> {
    'Recognition' => 'Determining Differentiated Problems',
    'Determine Needs' => 'Confirming Vision Match',
    'Evaluate Options' => 'Confirming Value and Power',
    'Resolve Concerns' => 'Finalizing Mutual Plan',
    'Negotiate' => 'Negotiating',
    'Closed' => 'Closed',
    'Lost' => 'Lost',
    'No Decision' => 'No Decision',
    'Opportunity Identified' => 'Opportunity Identified',
    'Prospecting' => 'Prospecting'
  };

  // also map them in reverse, dynamically.
  map<string,string> oppToSales = new map<string,string>();
  for(string key:salesToOpp.keySet())
    oppToSales.put(salesToOpp.get(key),key);

  // load up the record type names for dynamic usage.
  for(RecordType rt:[select id,developername from recordtype where sobjecttype='opportunity'])
    recordtypenames.put(rt.developername,rt.id);

  // for each record in our trigger...
  for(opportunity opp:trigger.new) {
    // if it's the wrong record type, go to the next record.
    if(opp.recordtypeid == null || opp.recordtypeid != recordtypenames.get('RecordTypeToCheckFor'))
      continue;

    // If the sales stage has changed, and is valid, change the opportunity stage name.
    // NOTE: If it's an insert, sales stage takes precedence over stage name.
    // Reverse this if statement with the next to change this priority.
    if(salesToOpp.containsKey(opp.sales_stage__c) && (Trigger.isInsert || Trigger.oldMap.get(opp.id).Sales_Stage__c != opp.Sales_Stage__c))
      opp.stagename = salesToOpp.get(opp.sales_stage__c);

    // if the opportunity stage has changed, and is a valid change, change the sales stage.
    if(oppToSales.containsKey(opp.stagename) && (Trigger.isInsert || Trigger.oldMap.get(opp.id).StageName != opp.Stagename))
    opp.sales_stage__c = oppToSales.get(opp.stagename);
  }
}

 This will cause a synchronization both ways, although if stage name and sales stage are changed both at the same time, sales stage will take precedence over the sales stage.

 

This was selected as the best answer
SpunkySpunky

Thank you so much!!! This is perfect!