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
Ronan O'Neill 6Ronan O'Neill 6 

Using a Trigger to update the Lat and Lng of Account when Address is updated

So first off I noticed there are built in Lattitute and Longitude fields for Account objects. Do these already get updated when address is filled in? Executing in Query Editor does not seem to give me a value in the Developers Console.

Either way I started building a Geocoding class via google maps and I wanted it to automatically fire when the address of an Account is inserted or updated. 

My Trigger was initially After Update, Insert but I got an error for read only values. I then tried Before Update, Insert which seemed anti intutive but I now get a null value for the ID I think.

My code is below but I essentially just want a way to fire a trigger to update a field in Accounts when the address field in Account is updated or created?

trigger AddLocation on Account (before insert, before update) {
    
    for (Account updatedAccount : Trigger.new) {
       
      // if( (Trigger.oldMap.get(updatedAccount.Id).BillingStreet != 
         // Trigger.newMap.get(updatedAccount.Id).BillingStreet)||( Trigger.oldMap.get(updatedAccount.Id).BillingCity != 
         // Trigger.newMap.get(updatedAccount.Id).BillingCity)||( Trigger.oldMap.get(updatedAccount.Id).BillingState != 
        // Trigger.newMap.get(updatedAccount.Id).BillingState)||( Trigger.oldMap.get(updatedAccount.Id).BillingPostalCode != 
        //  Trigger.newMap.get(updatedAccount.Id).BillingPostalCode)){
              
        Geocoding updater = new Geocoding(updatedAccount.Id);
        
        updatedAccount.BillingLatitude = updater.getLat();
        updatedAccount.BillingLongitude = updater.getLng();
        
            //}
   }     

Best Answer chosen by Ronan O'Neill 6
SarfarajSarfaraj
Hi Ronan, Please find below links to the codes. Let me know if you find any difficulty in downloading, Trigger, http:// www.codesend.com /view/a19110cc84094557b0ffdc54117e1a8b/ Geocoding class http://www.codesend.com/view/fd0b94fecace3b8c205f299bf0660fb5/ --Akram

All Answers

SarfarajSarfaraj
Hi

Id will not be generated in before insert trigger. You may consider passing the entire instance of account. Like this,
Geocoding updater = new Geocoding(updatedAccount);
And modifying your code for Geocoding class accordingly.

--Akram
Ronan O'Neill 6Ronan O'Neill 6
Hi Akram, thanks for the reply. I gave that a go and still not seeing any results. 

Would the ID for updatedAccount not still be null? As I need that to grab the address and generate the geocoding url.
SarfarajSarfaraj
Isn't it possible to do the geocoding without the account Id. Please post code for the Geocoding class. I will try to evaluate it and find solution for you.
Ronan O'Neill 6Ronan O'Neill 6
Thanks, any help would be great. This is the current code I have trying to make use of the object and avoid using ID. 


public class Geocoding {
    
    private static FINAL String GKEY = 'key';
    
    private static SObject accountObj;

    private static double lat;
    private static double lng;
    
    
    //Constructor, takes the account ID, calls URL Builder method, creates http connection
    //and uses URL to get the Geocoding response
    //Extracts the latitude and lngitude from response and sets to class variables
    
    public Geocoding (SObject updatedAccount) {
        
        accountObj = updatedAccount;
        
        callOut();
        
    }
    
    @future
    public static void callOut () {
        
        Http gCall = new Http();
        
        HttpRequest gReq = new HttpRequest();
        gReq.setEndpoint(urlBuilder());
        gReq.setMethod('GET');
        
        HttpResponse gRes = gCall.send(gReq);
        
        String response = gRes.getBody();
        
        lat = double.valueOf(response.substringBetween('"location" : { "lat" : ', ','));
        lng = double.valueOf(response.substringBetween('"lng : "', '},'));
        
        accountObj.put('BillingLatitude', lat);
        accountObj.put('BillingLongitude', lng);
        
    }
    
    //Takes accID of updating account and constructs the Google Geocoding URL
    //from the address

    public static String urlBuilder (){
        
        //List<Account> accAddress = Database.query('SELECT BillingStreet, BillingCity, ' +
        //                                          'BillingState, BillingPostalCode ' +  
        //                                          'FROM Account ');

        String gAddress = '';
        
        //for(Account addresses : accAddress) {
            
            gAddress = String.valueOf(accountObj.get('BillingStreet'));
            gAddress += '+';
            gAddress += String.valueOf(accountObj.get('BillingCity'));
            gAddress += '+';
            gAddress += String.valueOf(accountObj.get('BillingState'));
              gAddress += '+';
            gAddress += String.valueOf(accountObj.get('BillingPostalCode'));
            
       // }
        
        String gUrl =     'https://maps.googleapis.com/maps/api/geocode/json?address=' +
                        gAddress + 
                        '&key=' + 
                        GKEY;
           
        System.debug(gAddress);
        
        return gUrl;
        
    }
    
    public double getLat() {
        
        return lat;
    }
    
    public double getLng() {
        
        return lng;
    }
    
}
SarfarajSarfaraj
Hi Ronan,

I made some changes in your code. I don't have any gmap key. If you have one please incorporate it. Following code uses the free api and updates Lat and Lng values into the Account record. Seems like we have some limit on number of characters per post. I will split it into multiple message.
SarfarajSarfaraj
Funny. It is not allowing me to post any code. I will see if there is any other way to share code and get back to you later.
SarfarajSarfaraj
Hi Ronan, Please find below links to the codes. Let me know if you find any difficulty in downloading, Trigger, http:// www.codesend.com /view/a19110cc84094557b0ffdc54117e1a8b/ Geocoding class http://www.codesend.com/view/fd0b94fecace3b8c205f299bf0660fb5/ --Akram
This was selected as the best answer
Ronan O'Neill 6Ronan O'Neill 6
Hi Akram, 

I think I finally have this working. Thanks so much for your help. For any future readers, I had issues with enabling the correct api in google, ha stupid one, and also allowing google maps as an endpoint in remote site settings under security controls for salesforce. Additionally I created a custom object for the Lat and Lng as the built in ones may be used by the system and I didn't have confidence in them not being altered.

I noticed you changed it to an after update Trigger, Akram. I initially tried that but found I couldn't make changes to other fields in the account being updated as they were locked. How was it you avoid that?

I also like how to manage the JSON reply and build the URL, much less awkward then mine. 

Thanks again.

Ronan
SarfarajSarfaraj
Ronan, You are welcome. I didn't solved anything on the update issue. You did it. It is all in the future call. Without the future call you had to do this in before update. Also I have avoided the recursive call by checking current context in the constructor.