0

Based on my understanding the mailing address on a person account will not be auto geolocated as is the case with normal accounts.

What is the easiest way to get a lat/lng for a person account? I need to have these values in an apex controller where I look for the closest x business accounts in an SOQL query.

  • Yes it is not available now. Here is the Salesforce Idea: success.salesforce.com/ideaView?id=0873A000000cNaFQAU – Sudipta Deb Apr 26 '18 at 0:01
  • Yes, I saw that but is there a way I can accomplish this in code? Is there a 3rd party app that would help? Hoping there is some workaround for this, it seems like it must be a relatively normal use case. – Graham Coombe Apr 26 '18 at 0:03
  • Are you looking for how to populate the geolocation on person account, or you are looking how to access the lat/lang fields for a person account in soql/apex? – Jayant Das Apr 26 '18 at 0:33
  • Ultimately how to access them to use in the query, but I am unsure of a good way of setting/deriving them. – Graham Coombe Apr 26 '18 at 0:40
  • I added details as an answer, hope that helps. You can access the fields in soql as with regular business accounts for person accounts as well. I verified this on person account and the query executed fine, except for I did not have values available on these fields. – Jayant Das Apr 26 '18 at 0:55
1

Assuming that you already have Geocodes added for the Person Account record, you can access the latitude and longitude fields in SOQL query as for any account record. Your query should look like (say if you are fetching the values from Billing Address) as:

Account a = [select Id, Name, BillingLatitude, BillingLongitude from Account where id = 'xxxxx' limit 1];

For api names on the fields and on which addresses those are supported, you can find more on the help link.

Geocodes for Person Accounts cannot be added using data integration rules, for that purpose you will need to use API or third-party services. Below is an excerpt from the considerations for Person Account.

Geocodes for addresses can’t be added to person accounts using data integration rules. Use the API or third-party services to add geocode data to person accounts.

Additional information can be found on this link on Geolocation custom fields.

To be able to add geocodes on the record, you can set those fields as regular fields. An example below.

Account a = [select id, BillingLatitude, BillingLongitude from account where id = 'xxx' limit 1];

a.BillingLatitude = <value>;
a.BillingLongitude = <value>;

update a;
  • Thanks! My issue is more that I don't know how to get the geocodes added. It mentions api or 3rd party services but I couldn't find any options. – Graham Coombe Apr 26 '18 at 16:01
  • I just added that in the answer. You can set values on these fields as regular updates. Hope this helps. – Jayant Das Apr 26 '18 at 16:31
  • @JayantDas do you mean Data Integration rules that automatically populate geocode on normal account also works on person account? – Pranay Jaiswal Apr 26 '18 at 16:59
  • @PranayJaiswal No. Those rules are not available for Person Accounts as the documentation states. I updated the answer with the potential approach of updating the geocode fields on a person account (using regular DMLs), as long as you have those values available. – Jayant Das Apr 26 '18 at 17:02
  • @JayantDas can you review my solution?salesforce.stackexchange.com/a/216216/19118 Thanks. – Pranay Jaiswal Apr 26 '18 at 18:06
1

I know this is the ugliest solution out there, But this allows you to have Free Geolocation on Person account without using Any 3rd Party API.

The solution is Native to Salesforce, its faster cleaner and doesn't consume any data, I used it for one of NFP client.

Here are the steps mentioned.

  1. Create A new Record Type for Account. Name it as Geo Location.
  2. In Data Integration Rule , Uncheck Bypass trigger field. enter image description here
  3. Create a Lookup on Account Object Point to Account. Name that field as Geo Location Account.
  4. Now When you create a Person Account, in Before Insert of it Create a new Account of Record Type 'GeoLocation' and Populate its Billing Address fields with Person Accounts Mailing Address Field.
  5. Write After Update Trigger for Geolocation Account. Copy the Populated latitude, Longitude to PersonAccount's Contact MailingLatitude and Mailing Longitude.
  6. Delete the Geolocation Account.

    trigger AccountTrigger on Account (before insert, before update, after update) {
     if(Trigger.isBefore && Trigger.isInsert){
       if(Trigger.new[0].RecordTypeId=='012580000005pgu'){//Record Type of Person Account
    
           //Creating Geolocation Type Account with recordType 
          Account normalAccount = new Account(RecordTypeId='0129E0000007IRD',BillingStreet=Trigger.new[0].PersonMailingStreet,
          BillingCity=Trigger.new[0].PersonMailingCITY,BillingCOuntry=Trigger.new[0].PersonMailingCountry,BillingPostalCode=Trigger.new[0].PersonMailingPostalCode,Name= Trigger.new[0].LastName);
          insert normalAccount ;
          Trigger.new[0].Geo_Location_Account__c=normalAccount.Id ;
    
          }
    
    
     } 
     if(Trigger.isafter && Trigger.isupdate){
        if(Trigger.new[0].RecordTypeId=='0129E0000007IRD'!=null && Trigger.new[0].BillingLatitude!=null && Trigger.new[0].BillingLongitude !=null){
                Account parentPersonAccount=[Select id,PersonContactId from Account where Geo_Location_Account__c=:Trigger.new[0].Id ];
                contact personContact=new Contact(Id=parentPersonAccount.PersonContactId );
                personContact.MailingLatitude=Trigger.new[0].BillingLatitude;
                personContact.MailingLongitude=Trigger.new[0].BillingLongitude ;
                update personContact;
    
                //delete geolocation Account
                delete new Account(Id=Trigger.new[0].id);
        }
     }
    
      }
    

Above code does same for a Single record.It works like charm. Its unbulkidied and can be improved. But you can do it with the algorithm I mentioned above.

  • So if I understand this right, you are creating a regular business account, using the data integration rules to populate the geocode fields on it and then convert that to person account, right? – Jayant Das Apr 27 '18 at 12:44
  • Yeap.. I am. It's hacking the way out.. Using Business Account to get geolocation and save it in persona account. I tried nd it works with big enterprise level project. I agree I am still running triggers when I should not. But its resource friendly. No 3rd Party API calls. No future queueable. Native SF. – Pranay Jaiswal Apr 27 '18 at 12:58
  • Looks like to be workable hack :) This solves the issue of how to populate the geocodes on person account, and as long as that is addressed, think this works just fine. And there are plenty of ways to improve the solution, but this is a good start. – Jayant Das Apr 27 '18 at 13:11
  • Its a shame. Geolocation is available in Account and Contact address. Its bit weird why it should be readily available on person account which is just a combination of both. – Pranay Jaiswal Apr 27 '18 at 13:14
0

As suggested in this Salesforce doc Considerations for Using Person Accounts you have to get the Lat/Lng values from either some AppExchange Apps or through API integration.

(Snippets from the link -- > Geocodes : Geocodes for addresses can’t be added to person accounts using data integration rules. Use the API or third-party services to add geocode data to person accounts.)

This is an example of how you can get the Lat/Lng values using Google Geocoder API. This is a working example also you can incorporate this into a trigger so that while creating or updating the Account you can add/update the Geocode values in the Account record.

Double latVal = null;
Double lngVal = null; 
Account acc = [SELECT BillingStreet, BillingCity, BillingCountry, BillingPostalCode FROM Account WHERE Id = '0017F000004ddHsQAI' LIMIT 1];
String addr = acc.BillingStreet + ',' + acc.BillingCity + ',' + acc.BillingCountry + ',' + acc.BillingPostalCode;
addr = EncodingUtil.urlEncode(addr, 'UTF-8');
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('https://maps.googleapis.com/maps/api/geocode/json?address='+addr+'&sensor=true'+'&key=YOUR_API_KEY');
req.setMethod('GET');
try {
    HttpResponse res = h.send(req);
    JSONParser parser = JSON.createParser(res.getBody());
    while(parser.nextToken() != null ) {
        if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'location')) {
            parser.nextToken();
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                String txt = parser.getText();
                parser.nextToken();
                if (txt == 'lat'){
                    latVal = parser.getDoubleValue();
                }else if (txt == 'lng'){
                    lngVal = parser.getDoubleValue();
                }
            }
        }
    }
    System.debug('latVal ='+latVal);
    System.debug('lngVal ='+lngVal);
} catch( Exception e) {
    System.debug('== Exception Occured ====' + e.getMessage());
}
  • Just to warn others who may catch this - adding this call out on a trigger could cause you serious performance issues, even if this could be made bulkified. If you wanted to go down this route you should seriously consider looking at batch, queueable, platform events and other such mechanisms in order to decouple your inserts and updates from an HTTP callout. – Rob Baillie Sep 24 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.