Geocoding in Siebel Open UI with Google maps API
8. 10. 2021
In CRM processes, there can be situations where one needs to convert an address into GPS coordinates and vice versa or count the riding distance between two locations. We have a use case, where the assistance department must plan car transport from the location of accident to the location of repair station or where it is requested. The calculation of distance is requested as well.
As Siebel Open UI provides powerful framework for browser side scripting integration, we have proposed for this purpose the integration with Google maps API.
All the google maps integration we have encapsulated in class GoogleMapsUtils and its method geocodeAddresses, we will describe the class in more details later.
Firstly, the entry point for the integration is PM script of an applet, where the geocoding functionality is required. We have to initiate the class instance within constructor of the applet PM.
var GoogleMapsUtils = SiebelAppFacade.GoogleMapsUtils;
To instantiate Google maps API we have created an method loadGoogleMaps in class GoogleMapsUtils, the method initiate googleapi in Singleton mode, it looks as follows:
GoogleMapsUtils.loadGoogleMaps = function ()
{
if(!gMapsLoaded) {
$.getScript("https://maps.googleapis.com/maps/api/js?key={google_maps_api_key", function(data, status) {
console.log( data );
console.log( status );
gMapsLoaded = true;
if (geocoder == null)
geocoder = new google.maps.Geocoder();
if (service == null)
service = new google.maps.DistanceMatrixService();
});
} else {
gMapsLoaded = true;
if (geocoder == null)
geocoder = new google.maps.Geocoder();
if (service == null)
service = new google.maps.DistanceMatrixService();
}
}
The method loadGoogleMaps is then called from Init method of an applet PM script. The function for geocoding and distance calculation is called within button. Function reads to fields on the service request entity, starting and end location into variables and call the method from class GoogleMapsUtils.
GoogleMapsUtils.geocodeAddresses(sOrigin, sDestination, GeocodeFinished);
Very important is to note, that all google api calls are asynchronous, working through callbacks, so if we want to process the information returned from api call, we have to define the callback. In this case we define callback function GeocodeFinished.
function GeocodeFinished(returnObject)
{
//alert(JSON.stringify(returnObject));
if (returnObject.status === "OK") { // geocoding successfull
var fromZipCode = returnObject.locationFrom.postal_code;
var fromCity = returnObject.locationFrom.city;
var toZipCode = returnObject.locationTo.postal_code;
var toCity = returnObject.locationTo.city;
var distance = returnObject.distance;
distance = distance.replace(/[A-Za-z]|,/g,'');
var lat_orig = returnObject.locationFrom.lat;
var lon_orig = returnObject.locationFrom.lng;
var lat_dest = returnObject.locationTo.lat;
var lon_dest = returnObject.locationTo.lng;
// we have all the information here,
// ZIP code and city of origin, destination
// distance between origin and destination
// latitude and longitude of origin and destination
// we can store these information on the entity
var sActivityId = that.Get("GetBusComp").GetFieldValue("Id");
// any code to store it on activity
}
}
We have just shown here how to retrieve geocoding data returned by callback function, storing data on entity is not described here. This is done by Siebel Open UI methods of Business Component and Business Service.
Finally, we will explain here and then show whole code of our function geocodeAddresses to get complete address information, it means street, number, city, postal code, country, longitude and latitude of the origin and destination location. Those information are retrieved in cascade asynchronous calls of google api method geocoder.geocode. Afterwards when both addresses are geocoded and parsed (in auxiliary method parseGeocodeResults, attached below) , DistanceMatrixService is used to calculate the distance using its method: getDistanceMatrix. Retrieved information (postal codes, cities and distance) are shown in list applet.
Code for functions geocodeAddress and parseGeocodeResults are here:
GoogleMapsUtils.geocodeAddresses = function (addressFrom, addressTo, GeocodeFinished) {
locationFrom = {
status : status,
street_number : "",
street : "",
city : "",
postal_code : "",
country : "",
lat : 0,
lng : 0
}
locationTo = {
status : status,
street_number : "",
street : "",
city : "",
postal_code : "",
country : "",
lat : 0,
lng : 0
}
var returnObject = new Object();
returnObject.locationFrom = locationFrom;
returnObject.locationTo = locationTo;
returnObject.distance = "0 km";
returnObject.status = "NULL";
if (geocoder == null) {
GeocodeFinished(returnObject);
return;
}
geocoder.geocode({'address': addressFrom}, function(results, status) {
if (status === 'OK' && results.length>0) {
locationFrom.status = status;
parseGeocodeResult(results, locationFrom);
returnObject.locationFrom = locationFrom;
geocoder.geocode({'address': addressTo}, function(results, status) {
returnObject.status = "OK";
if (status === 'OK' && results.length>0) {
locationTo.status = status;
parseGeocodeResult(results, locationTo);
returnObject.locationTo = locationTo;
var origin1 = new google.maps.LatLng(locationFrom.lat, locationFrom.lng);
var destination1 = new google.maps.LatLng(locationTo.lat, locationTo.lng);
service.getDistanceMatrix({
origins: [origin1],
destinations: [destination1],
travelMode: 'DRIVING',
avoidHighways: false,
avoidTolls: false,
drivingOptions: {
departureTime: new Date(Date.now() + 1000), // for the time N milliseconds from now.
trafficModel: 'optimistic'
}
}, function callback(response, status) {
// See Parsing the Results for
// the basics of a callback function.
//alert(status);
if (status == 'OK') {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
var element = results[j];
var distance = element.distance.text;
var duration = element.duration.text;
var from = origins[i];
var to = destinations[j];
returnObject.distance = distance;
}
}
}
returnObject.status = status;
GeocodeFinished(returnObject);
});
} else {
returnObject.locationTo.status = status;
GeocodeFinished(returnObject);
}
});
} else {
returnObject.locationFrom.status = status;
GeocodeFinished(returnObject);
}
});
}
function parseGeocodeResult(results, addressObj)
{
var location = results[0].geometry.location;
addressObj.lat = location.lat().toFixed(6);
addressObj.lng = location.lng().toFixed(6);
var addrComp = results[0].address_components;
for (var index in addrComp) {
for (var typeIndex in addrComp[index].types)
{
switch (addrComp[index].types[typeIndex]) {
case "street_number" :
addressObj.street_number = addrComp[index].short_name;
break;
case "route" :
addressObj.street = addrComp[index].short_name;
break;
case "country" :
addressObj.country = addrComp[index].long_name;
break;
case "locality" :
addressObj.city = addrComp[index].long_name;
break;
case "postal_code" :
addressObj.postal_code = addrComp[index].long_name;
break;
case "administrative_area_level_2" :
if (addressObj.city === "")
addressObj.city = addrComp[index].long_name;
break;
}
}
}
}
In the following picture, one can see information retrieved from Google maps API, ( marked in red rectangle, GPS coordinates of origin, postal code and city of origin and destination and calculated distance in kilometers ) as well as visualised tracks from origin to destination.
Using this mechanism we can easily integrate any google api call and its results into Siebel Open UI framework. For further information or assistance in implementation, please do contact us.
Späť na Blog