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
Mark G. SchaferMark G. Schafer 

Map country name from AppExchange lead to Country picklist

I recently switched on the state and country picklist feature in my org, but I'm running into a problem with many of the leads we get routed into our org from my company's AppExchange listing. We're getting emails with the subject 'Salesforce Could Not Create This Lead' because the leads contain a country name (most commonly 'US') that doesn't map to the country value in the standard Country picklist.

I've attempted to write some Apex that will take the text value from the incoming lead and attempt to correct the non-standard country value using a list of countries I store in a custom object. In the debug log, the code I wrote below seems to succesfully find the standard country name and code and write it to the CountryName and CountryCode fields on the Lead.

Even so, I still receive an error when I try to insert a test Lead record with the value of 'US' in the Country field via the DataLoader, even the the debug log confirms I've updated the Country field to 'United States' and the CountryCode field to 'US'. The returned error is (There's a problem with this country, even though it may appear correct. Please select a country from the list of valid countries.: Country).

This seems weird, because I think Salesforce does system validations after before triggers are run.

I've tried editing the code to only update the Country field, only update the CountryCode field, and to update both (as written below). They all end up throwing the same error.

Anyone have any ideas?

public class StateCountryGeoLookup {

	public static void validateLeadCountry (List<Lead> leadList){
		
		//query of a custom object containing all country names, codes, and alternate spellings
		List <Country_Lookup__c> Countries = [SELECT Name, ID, ISO_2_Code__c, ISO_3_Code__c, 
											Alternate_Name_1__c, Alternate_Name_2__c
											FROM Country_Lookup__c];
											
		Map<String,String> countryMap = new Map<String,String>();
		Map<String,String> countryCodeMap = new Map<String,String>();
		
		//map every variant of the country name to the standard country name and code in the picklist
		for (Country_Lookup__c country : Countries){
			countryMap.put(country.Name, country.Name);
			countryCodeMap.put(country.Name, country.ISO_2_Code__c);
			
			countryMap.put(country.ISO_2_Code__c, country.Name);
			countryCodeMap.put(country.ISO_2_Code__c, country.ISO_2_Code__c);
			
			countryMap.put(country.ISO_3_Code__c, country.Name);
			countryCodeMap.put(country.ISO_3_Code__c, country.ISO_2_Code__c);
			
			if(country.Alternate_Name_1__c != null){
				countryMap.put(country.Alternate_Name_1__c, country.Name);
			}
			if(country.Alternate_Name_2__c != null){
				countryMap.put(country.Alternate_Name_2__c, country.Name);
			}	
		}
		
		for (Lead l : leadList){
			String countryName = countryMap.get(l.Country);
			String countryCode = countryCodeMap.get(l.Country);
			
			System.debug('The returned country name is ' + countryName);
			System.debug('The returned country code is ' + countryCode);
			
			if (countryName != null && countryCode !=null){
				
				//update Lead fields with valid country name and code
				l.Country = countryName;
				l.CountryCode = countryCode;
				
				System.debug('The lead field Country has a value of ' + l.Country);
				System.debug('The lead field CountryCode has a value of ' + l.CountryCode);
				
			//remove the value entirely if a valid country name can't be found	
			} else {
				l.Country = null;
				l.CountryCode = null;
			}	
		}	
	}
}
 



 

Best Answer chosen by Mark G. Schafer
Mark G. SchaferMark G. Schafer

Found the answer. There is a known issue that is currently under review. It's currently impossible to correct the data using Apex until the issue is corrected by Salesforce.

https://success.salesforce.com/issues_view?id=a1p30000000T4OMAA0

My workaround for now is I created a country with the name of 'US' and a country code of 'XX' that is active but not visible in the picklist. A workflow rule then updates all leads with the value of 'US' to the standard 'United States'.

I will still get some errors using this method, but 90% of the AppExchange leads that cause this error have a country value of 'US', so the workaround will take care of most of the errors.

All Answers

Mark G. SchaferMark G. Schafer

And the trigger itself just looks like this:

trigger leadTrigger on Lead (before insert, before update) {
	StateCountryGeoLookup.validateLeadCountry(Trigger.new);
}
Sagar PareekSagar Pareek
Yes you got it right , it is because of salesforce internal validations 

This is how order of execution in salesforce looks like 

Point 4 is creating trouble for you

1. The original record is loaded from the database (or initialized for an insert statement)
2. The new record field values are loaded from the request and overwrite the old values
3. All before triggers execute (TRIGGERS)
4. System validation occurs, such as verifying that all required fields have a non-null value, and running any user-defined validation rules (VALIDATIONS)
5. The record is saved to the database, but not yet committed
6. All after triggers execute
7. Assignment rules execute
8. Auto-response rules execute
9. Workflow rules execute (WORKFLOW)
10. If there are workflow field updates, the record is updated again
11. If the record was updated with workflow field updates, before and after triggers fire one more time (and only one more time)
12. Escalation rules execute
13. All DML operations are committed to the database
14. Post-commit logic executes, such as sending email
Mark G. SchaferMark G. Schafer
Thanks Sagar, but my trigger is firing in step 3 and correcting the bad data by updating the Country to a valid value or else removing the non-valid value entirely. If the value is correct by the end of step 3, why would step 4 cause me any trouble?
Mark G. SchaferMark G. Schafer

And one more addition....

I also updated the code to set the Country field to null in all cases, just as a test. My attempt to insert a lead record still failed in this case, even though the Apex code ran succesfully and entirely removed the invalid country value BEFORE the system validation is run.

Mark G. SchaferMark G. Schafer

Found the answer. There is a known issue that is currently under review. It's currently impossible to correct the data using Apex until the issue is corrected by Salesforce.

https://success.salesforce.com/issues_view?id=a1p30000000T4OMAA0

My workaround for now is I created a country with the name of 'US' and a country code of 'XX' that is active but not visible in the picklist. A workflow rule then updates all leads with the value of 'US' to the standard 'United States'.

I will still get some errors using this method, but 90% of the AppExchange leads that cause this error have a country value of 'US', so the workaround will take care of most of the errors.

This was selected as the best answer
Steven OdorczykSteven Odorczyk
Almost 4 years later and this known issue is still not fixed. For anyone else dealing with this issue - what I've found is that adding a 'dummy' country with the Name 'US' and CountryCode 'XX' will allow the field validation to pass. But instead of writing a workflow rule as Mark suggests above, you can still perform the updates in an Apex Trigger. The platform will validate on the initial value passed in (hence the need for the dummy value), but the apex code still runs. I found this to be much better than writing workflow field updates:

public static void assignAddressCodesBeforeMapping(List<Lead> leads) {
  for (Lead l : leads) {
    l.CountryCode = l.Country;
    l.Country = null;
    l.StateCode = l.State;
    l.State = null;
  }
  // then proceed to insert leads or send the list to another method
}