├── README.md
└── src
├── classes
├── AddressAutocompleteController.cls
├── AddressAutocompleteController.cls-meta.xml
├── AddressAutocompleteControllerTest.cls
└── AddressAutocompleteControllerTest.cls-meta.xml
├── components
├── AddressAutocomplete.component
└── AddressAutocomplete.component-meta.xml
├── objects
├── Account.object
├── AddressAutocompleteGoogleKey__c.object
├── Contact.object
└── Lead.object
├── package.xml
├── pages
├── AddressAutocompleteAccount.page
├── AddressAutocompleteAccount.page-meta.xml
├── AddressAutocompleteContact.page
├── AddressAutocompleteContact.page-meta.xml
├── AddressAutocompleteLead.page
└── AddressAutocompleteLead.page-meta.xml
└── staticresources
├── AddressAutocomplete.resource
└── AddressAutocomplete.resource-meta.xml
/README.md:
--------------------------------------------------------------------------------
1 | # Salesforce Address Autocomplete
2 |
3 | This package includes components to enable address autocomplete for objects in Salesforce using the Google Places API.
4 |
5 | This current package includes functionality for the following standard objects:
6 | - Account
7 | - Contact
8 | - Lead
9 |
10 | To add additional objects, simply copy the existing VisualForce pages, set the component parameters and create a Custom Button for the page.
11 |
12 | If looking to implement this package, be sure to read the Terms of Service for the Google Places API:
13 | https://developers.google.com/maps/terms
14 |
15 | And the usage limits:
16 | https://developers.google.com/places/webservice/usage
17 |
18 | ## Installation
19 |
20 | 1. Deploy this package to a Salesforce environment
21 |
22 | - [Deploy to Org](https://githubsfdeploy.herokuapp.com/app/githubdeploy/benedwards44/sf-address-autocomplete)
23 | - [Package Install for Production/Developer](https://login.salesforce.com/packaging/installPackage.apexp?p0=04tb00000001XtV)
24 | - [Package Install for Sandbox](https://test.salesforce.com/packaging/installPackage.apexp?p0=04tb00000001XtV)
25 |
26 | 2. Sign up for a Google Account and obtain your API key (https://code.google.com/apis/console), and enable the Google Maps JavaScript API v3.
27 | 3. Put your Google API key in the Address Autocomplete custom setting
28 | 4. Add Address Autocomplete buttons to page layouts as required
29 |
30 | ## Screenshots
31 |
32 | 
33 |
34 | ## Limits
35 |
36 | This application is bound by the Google Terms of Service, and its associated limits. These are also subject to change, so it's worth understanding this before implementing on any enterprise wide projects. Generally speaking, those Terms of Service that impact a Salesforce implementation are:
37 | - 1,000 address validations per day, or 150k per day for a paid service (ask Google for pricing)
38 | - You cannot use the free service if "Your site is only accessible within your company or on your intranet.". This is ultimately the deal-breaker for use within Salesforce. Contact Google to get pricing for the Google Maps for Work API.
39 |
40 | The most recent quote I had from Google (May '15) was £7,700 GDP / $11,000 USD per year for 500k queries.
41 |
--------------------------------------------------------------------------------
/src/classes/AddressAutocompleteController.cls:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Ben Edwards (Tquila)
3 | * Date: 12/05/2015
4 | * Description: Controller for the AddressValidation component
5 | *
6 | * ******************* Change Log *******************
7 | * Modified by Change Date Change
8 | * Ben Edwards 12/05/2015 Initial creation.
9 | **/
10 | public with sharing class AddressAutocompleteController {
11 |
12 | // Variables passed through from Component
13 | public Id recordId {get;set;}
14 | public String objName {get;set;}
15 |
16 | // Address one details
17 | public String streetOne {get;set;}
18 | public String cityOne {get;set;}
19 | public String stateOne {get;set;}
20 | public String postalcodeOne {get;set;}
21 | public String countryOne {get;set;}
22 |
23 | // Whether to include 2nd address
24 | public Boolean secondAddress {get;set;}
25 |
26 | // ADdress two details
27 | public String streetTwo {get;set;}
28 | public String cityTwo {get;set;}
29 | public String stateTwo {get;set;}
30 | public String postalcodeTwo {get;set;}
31 | public String countryTwo {get;set;}
32 |
33 |
34 | // CONSTRUCTOR
35 | public AddressAutocompleteController() {}
36 |
37 | // When save method is clicked from page
38 | public PageReference save() {
39 |
40 | try {
41 | // Save the sObject record
42 | update obj;
43 |
44 | // Return back to the standard record detail view
45 | return new PageReference('/' + obj.Id);
46 | }
47 | catch (Exception ex) {
48 |
49 | // Add error to page messages if none already exist. Some would exist if page validation fails, so no need to enter twice
50 | if (!ApexPages.hasMessages()) {
51 |
52 | ApexPages.addMessages(ex);
53 | }
54 |
55 | system.debug('### Error saving object: ' + ex);
56 |
57 | // Return null if an error exists - to display error on page.
58 | return null;
59 | }
60 | }
61 |
62 | // When Cancel method is clicked on page
63 | public PageReference cancel() {
64 | return new PageReference('/' + obj.Id);
65 | }
66 |
67 | // Object for the page
68 | public sObject obj {
69 |
70 | get {
71 |
72 | if (obj == null) {
73 |
74 | // Build query for address fields
75 | String objectQuery = 'Select Name,';
76 | objectQuery += String.isNotBlank(streetOne) ? streetOne + ',' : '';
77 | objectQuery += String.isNotBlank(cityOne) ? cityOne + ',' : '';
78 | objectQuery += String.isNotBlank(stateOne) ? stateOne + ',' : '';
79 | objectQuery += String.isNotBlank(postalcodeOne) ? postalcodeOne + ',' : '';
80 | objectQuery += String.isNotBlank(countryOne) ? countryOne : '';
81 |
82 | // If there is a 2nd address, add fields to query
83 | if (secondAddress != null && secondAddress) {
84 |
85 | objectQuery += ',';
86 | objectQuery += String.isNotBlank(streetTwo) ? streetTwo + ',' : '';
87 | objectQuery += String.isNotBlank(cityTwo) ? cityTwo + ',' : '';
88 | objectQuery += String.isNotBlank(stateTwo) ? stateTwo + ',' : '';
89 | objectQuery += String.isNotBlank(postalCodeTwo) ? postalCodeTwo + ',' : '';
90 | objectQuery += String.isNotBlank(countryTwo) ? countryTwo : '';
91 |
92 | }
93 |
94 | // Add object and where clause
95 | objectQuery += ' From ' + objName + ' Where Id = \'' + recordId + '\'';
96 |
97 | // Execute query for record
98 | obj = database.query(objectQuery);
99 | }
100 | return obj;
101 | }
102 | set;
103 | }
104 |
105 | }
--------------------------------------------------------------------------------
/src/classes/AddressAutocompleteController.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/src/classes/AddressAutocompleteControllerTest.cls:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Ben Edwards (Tquila)
3 | * Date: 12/05/2015
4 | * Description: Test class for the AddressAutocompleteController
5 | *
6 | * ******************* Change Log *******************
7 | * Modified by Change Date Change
8 | * Ben Edwards 12/05/2015 Initial creation.
9 | **/
10 | @isTest
11 | public class AddressAutocompleteControllerTest {
12 |
13 | // Test ALL method for the controller
14 | // This test method is really only for test coverage. It's not really "unit testing" the logic
15 | // This is because the Google callout and validation is done from the VisualForce. Not worth re-implenmenting
16 | // in Apex just for testing purposes.
17 | static testMethod void addressAutocompleteControllerTest() {
18 |
19 | // Instantiate controller
20 | AddressAutocompleteController testCon = new AddressAutocompleteController();
21 |
22 | // Create Account (this will need additional fields added if validation rules are in place)
23 | Account testAccount = new Account(
24 | Name = 'Test Account',
25 | Phone = 'Test Phone'
26 | );
27 | insert testAccount;
28 |
29 | // Set variables (normally passed through from component)
30 | testCon.recordId = testAccount.Id;
31 | testCon.objName = 'Account';
32 |
33 | // Set 1st address details
34 | testCon.streetOne = 'BillingStreet';
35 | testCon.cityOne = 'BillingCity';
36 | testCon.stateOne = 'BillingState';
37 | testcon.postalcodeOne = 'BillingPostalCode';
38 | testCon.countryOne = 'BillingCountry';
39 |
40 | // Set Second Address to true.
41 | testCon.secondAddress = true;
42 |
43 | // Set 2nd address details
44 | testCon.streetTwo = 'ShippingStreet';
45 | testCon.cityTwo = 'ShippingCity';
46 | testCon.stateTwo = 'ShippingState';
47 | testcon.postalcodeTwo = 'ShippingPostalCode';
48 | testCon.countryTwo = 'ShippingCountry';
49 |
50 | // Assert obj is returned
51 | system.assertEquals(
52 | testAccount.Id,
53 | testCon.obj.get('id'),
54 | 'The object Id in the controller should match the created Account Id.'
55 | );
56 |
57 | // Test methods
58 | testCon.cancel();
59 | testCon.save();
60 |
61 | }
62 |
63 | }
--------------------------------------------------------------------------------
/src/classes/AddressAutocompleteControllerTest.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/src/components/AddressAutocomplete.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
190 |
191 |
--------------------------------------------------------------------------------
/src/components/AddressAutocomplete.component-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | Address autocomplete component for populating addresses for objects in Salesforce. Uses the Google Places API to auto-complete.
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/objects/Account.object:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Address_Autocomplete
5 | online
6 | button
7 | page
8 | Address Autocomplete
9 | replace
10 | AddressAutocompleteAccount
11 | false
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/objects/AddressAutocompleteGoogleKey__c.object:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hierarchy
4 | Protected
5 | Your Google API Key, used to authenticate with Google server.
6 | false
7 |
8 | Key__c
9 | The Google API key. Can be obtained from:
10 | https://console.developers.google.com/
11 | false
12 |
13 | 255
14 | true
15 | false
16 | Text
17 | false
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/objects/Contact.object:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Address_Autocomplete
5 | online
6 | button
7 | page
8 | Address Autocomplete
9 | replace
10 | AddressAutocompleteContact
11 | false
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/objects/Lead.object:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Address_Autocomplete
5 | online
6 | button
7 | page
8 | Address Autocomplete
9 | replace
10 | AddressAutocompleteLead
11 | false
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AddressAutocompleteController
5 | AddressAutocompleteControllerTest
6 | ApexClass
7 |
8 |
9 | AddressAutocomplete
10 | ApexComponent
11 |
12 |
13 | AddressAutocompleteAccount
14 | AddressAutocompleteContact
15 | AddressAutocompleteLead
16 | ApexPage
17 |
18 |
19 | AddressAutocompleteGoogleKey__c
20 | CustomObject
21 |
22 |
23 | AddressAutocomplete
24 | StaticResource
25 |
26 |
27 | Account.Address_Autocomplete
28 | Contact.Address_Autocomplete
29 | Lead.Address_Autocomplete
30 | WebLink
31 |
32 | 32.0
33 |
34 |
--------------------------------------------------------------------------------
/src/pages/AddressAutocompleteAccount.page:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
--------------------------------------------------------------------------------
/src/pages/AddressAutocompleteAccount.page-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | false
5 | false
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/pages/AddressAutocompleteContact.page:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
--------------------------------------------------------------------------------
/src/pages/AddressAutocompleteContact.page-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | false
5 | false
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/pages/AddressAutocompleteLead.page:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
--------------------------------------------------------------------------------
/src/pages/AddressAutocompleteLead.page-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | false
5 | false
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/staticresources/AddressAutocomplete.resource:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benedwards44/sf-address-autocomplete/4efebb8dfb38f8007cd47e243c646c0caff98537/src/staticresources/AddressAutocomplete.resource
--------------------------------------------------------------------------------
/src/staticresources/AddressAutocomplete.resource-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Public
4 | application/zip
5 |
6 |
--------------------------------------------------------------------------------