I am new to Salesforce Apex developement, and am trying to update certain fields (e.g. Organization name, 'EIN' value, issue areas and target population) on the account object based on values brought back from an external API (Guidestar) response, that is called by a Salesforce workflow. However, I am not getting it to work, and I was wondering there is something structurally wrong with my logic?
public without sharing class trac_GuidestarOrgUpdateBatch implements Database.Batchable<sObject>, Database.AllowsCallouts{
private Set<String> eins;
@InvocableMethod(Label='Update Bulk Orgs' Description='Returns the list of orgs returned from guidestar.' Category='Account')
public static void getBulkOrganisations(List<String> searchKeywords){
System.debug(searchKeywords);
trac_GuidestarOrgUpdateBatch btch = new trac_GuidestarOrgUpdateBatch(searchKeywords);
Database.executeBatch(btch , 100);
}
public trac_GuidestarOrgUpdateBatch(List<String> eins){
this.eins = new Set<String>();
if(eins != null && !eins.isEmpty()){
this.eins = new Set<String>(eins);
}
}
public Database.QueryLocator start(Database.BatchableContext BC){
String query = 'SELECT Id, EIN__c, Name, Primary_Issue_Area__c, Secondary_Issue_Area__c, Target_Population__c';
query += 'FROM Account';
query += 'WHERE EIN__c IN: eins';
System.debug('Query from start method: ' + query);
return Database.getQueryLocator(query);
}
public void execute(Database.BatchableContext BC, List<Account> scope) {
Map<String, String> regionsMap = getAccountRegionMap();
//Get 'Grantee' record type id
Id GRANTEE_RECORDTYPE = Schema.SObjectType.Account.getRecordTypeInfosByDeveloperName().get('Grantee').getRecordTypeId();
//Initialize account list to update
List<Account> accountList = new List<Account>();
//For each of these EINs, make a call to the premiere api
for (Account acct : scope) {
System.debug('Current object in scope: ' + acct);
System.debug('Acct Id: ' + acct.Id);
String ein = acct.EIN__c;
if (String.isNotBlank(ein)) {
trac_GuideStarUtility.CandidWrapper premiereResponse = new trac_GuideStarUtility.CandidWrapper();
if (!Test.isRunningTest()) {
premiereResponse = trac_GuideStarUtility.makePremierApiCall(ein);
} else {
premiereResponse = TestDataFactory.fakePremiereResponse(ein);
}
// If the result is not empty, use it to create a new account record.
if (premiereResponse?.code == 200 && premiereResponse?.data?.summary != null) {
trac_GuideStarUtility.OrgDataWrapper responseObjData = premiereResponse.data.summary;
acct.Name = responseObjData.organization_name;
acct.EIN__c = responseObjData.ein;
acct.Primary_Issue_Area__c = responseObjData.primary_issue_area;
acct.Secondary_Issue_Area__c = responseObjData.secondary_issue_area;
acct.Target_Population__c = responseObjData.target_population;
//Append current account to account list
accountList.add(acct);
}
}
}
//Push account list updates to database
Database.update(accountList);
}
public void finish(Database.BatchableContext BC){
}
private Map<String, String> getAccountRegionMap() {
Map<String, String> stateToRegionsMap = new Map<String, String>{
'WA'=>'US: West',
'OR'=>'US: West',
'CA'=>'US: West',
'AK'=>'US: West',
'HI'=>'US: West',
'ID'=>'US: Central',
'MT'=>'US: Central',
'NV'=>'US: Central',
'WY'=>'US: Central',
'UT'=>'US: Central',
'CO'=>'US: Central',
'AZ'=>'US: South',
'NM'=>'US: South',
'TX'=>'US: South',
'OK'=>'US: South',
'ND'=>'US: Central',
'SD'=>'US: Central',
'NE'=>'US: Central',
'KS'=>'US: Central',
'MN'=>'US: Central',
'IA'=>'US: Central',
'MO'=>'US: Central',
'WI'=>'US: Central',
'IL'=>'US: Central',
'MI'=>'US: Central',
'IN'=>'US: Central',
'OH'=>'US: Central',
'AR'=>'US: South',
'LA'=>'US: South',
'MS'=>'US: South',
'KY'=>'US: South',
'TN'=>'US: South',
'AL'=>'US: South',
'GA'=>'US: South',
'WV'=>'US: South',
'VA'=>'US: South',
'NC'=>'US: South',
'SC'=>'US: South',
'FL'=>'US: South',
'NY'=>'US: East',
'NH'=>'US: East',
'PA'=>'US: East',
'MD'=>'US: East',
'DE'=>'US: East',
'NJ'=>'US: East',
'VT'=>'US: East',
'ME'=>'US: East',
'MA'=>'US: East',
'RI'=>'US: East',
'CT'=>'US: East',
'DC'=>'US: East'
};
return stateToRegionsMap;
}
Do you get any errors in Developer Console / debug logs / Setup -> Apex jobs when running it?
Add Database.Stateful to the class signature and see if it helps. (shouldn't be needed but I wonder if you're passing
einsOK. Does the query in start() return stuff OK? Do executes run?)Most importantly - you're swallowing all errors that might be thrown by doing the cowardly
Database.update(accountList);. Man up and doupdate accountList;, you should see some real errors thrown. And then decide how you want to proceed (is 1 fail enough to spoil the whole lot? Or save what you can? Or offload the error handling to a proper "platform event" trick and build a report or something to track the problems?