Как я интегрирую Salesforce с Google Maps?

Как я интегрирую Salesforce с Google Maps? Я просто ищу информацию о как к...

  1. Поиск контактов в Salesforce
  2. Выведите на печать тех, которые на карте Google.
5
задан Jonathan Allen 25 June 2010 в 23:19
поделиться

1 ответ

EDIT:

Благодаря комментарию tggagne я понял, что люди все еще видят этот ответ. Коду, который был здесь, уже более 2,5 лет. Если вы хотите увидеть его - проверьте историю правок.

За это время многое изменилось, было создано больше примеров мэшапов. Не последним из них является приложение "SF Bus Radar" (github, youtube) Кори Коугилла (созданное на Dreamforce'11, я думаю).

Тем не менее - вот мой обновленный пример с геокодированием на стороне сервера, новым полем типа Geolocation и использованием парсеров JSON.

Он пытается кэшировать результаты геокодирования в записях контактов. Имейте в виду, что это может быть не "готово к производству" (нет ключа Google Business API = поскольку все наши запросы исходят из одного пула IP-серверов Salesforce могут быть сообщения об ошибках). Вот почему я оставил геокодирование на стороне клиента.


Вам нужно будет сделать 2 изменения в вашей среде перед проверкой:

  1. Добавьте "Remote Site Setting", который указывает на https://maps.googleapis.com, чтобы включить вызовы из Apex
  2. Добавьте поле "Location" в Setup -> Customize -> Contacts -> fields. Тип должен быть "Геолокация". Я выбрал отображение в виде десятичных дробей и точность 6 знаков после запятой.

    public with sharing class mapController {
    public String searchText {get;set;}
    public List contacts{get; private set;}
    
    public static final String GEOCODING_URI_BASE = 'https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=';
    
    // Для целей этого демо я буду геокодировать только пару адресов на стороне сервера. Реальный код может использовать закомментированное значение.
    public static final Integer MAX_CALLOUTS_FROM_APEX = 3; // Limits.getLimitCallouts()
    
    public mapController(){
     searchText = ApexPages.currentPage().getParameters().get('q');
    }
    
    public void find() {
     if(searchText != null && searchText.length() > 1){
     List> results = [FIND :('*' + searchText + '*') IN ALL FIELDS RETURNING 
     Contact (Id, Name, Email, Account.Name,
     MailingStreet, MailingCity, MailingPostalCode, MailingState, MailingCountry, 
     Location__Latitude__s, Location__Longitude__s)
     ];
     contacts = (List)results[0];
     if(contacts.isEmpty()){
     ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'No matches for "' + searchText + '"'));
     } else {
     serverSideGeocode();
     }
     } else {
     if(contacts != null) {
     contacts.clear();
     }
     ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Please provide at least 2 characters for the search.'));
     }
    }
    
    public void clearGeocodedData(){
     for(Contact c : contacts){
     c.Location__Latitude__s = c.Location__Longitude__s = null;
     }
     Database.update(contacts, false);
     contacts.clear();
    }
    
    public String getContactsJson(){
     return JSON.serialize(contacts);
    }
    public String getDebugContactsJson(){
     return JSON.serializePretty(contacts);
    }
    
    private void serverSideGeocode(){
     List contactsToUpdate = new List();
     Http h = new Http(); 
     HttpRequest req = new HttpRequest();
     req.setMethod('GET'); 
     req.setTimeout(10000);
    
     for(Contact c : contacts){
     if((c.Location__Latitude__s == null || c.Location__Longitude__s == null)){
     String address = c.MailingStreet != null ? c.MailingStreet + ' ' : '' +
     c.MailingCity != null ? c.MailingCity + ' ' : ''' +
     c.MailingState != null ? c.MailingState + ' ' : '' +
     c.MailingPostalCode != null ? c.MailingPostalCode + ' ' : ''' +
     c.MailingCountry != null ? c.MailingCountry : '';
     if(address != ''){
     req.setEndpoint(GEOCODING_URI_BASE + EncodingUtil.urlEncode(address, 'UTF-8'));
     try{
     HttpResponse res = h.send(req);
     GResponse gr = (GResponse) JSON.deserialize(res.getBody(), mapController.GResponse.class);
     if(gr.status == 'OK'){
     LatLng ll = gr.results[0].geometry.location;
     c.Location__Latitude__s = ll.lat;
     c.Location__Longitude__s = ll.lng;
     contactsToUpdate.add(c);
     } else {
     ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Geocoding of "' + address + '" failed:' + gr.status));
     }
     }catch(Exception e){
     ApexPages.addMessages(e);
     }
     }
     // Выйти из игры, если мы достигли предела количества звонков (возможно, не все контакты были обработаны).
     if(Limits.getCallouts() == MAX_CALLOUTS_FROM_APEX) {
     break;
     }
     }
     }
     if(!contactsToUpdate.isEmpty()) {
     Database.update(contactsToUpdate, false); // некоторые данные в редакциях для разработчиков недействительны (я думаю, специально).
     // Если обновление не удастся, потому что "j.davis@expressl&t.net" не является действительным Email, я хочу, чтобы остальные данные были успешными.
     }
    }
    
    // Класс-помощник - шаблон, в который будут разобраны результаты поиска. Некоторые поля пропускаются!
    // Посетите https://developers.google.com/maps/documentation/geocoding/#Results, если вам нужно создать полный маппинг.
    public class GResponse{
     public String status;
     public GComponents[] results;
    }
    public class GComponents{
     public String formatted_address;
     public GGeometry geometry;
    }
    public class GGeometry {
     public LatLng location;
    }
    public class LatLng{
     public Double lat, lng;
    }
    }
    

<apex:page controller="mapController" tabStyle="Contact" action="{!find}" id="page">
    <head>
        <style>
            div #map_canvas { height: 400px; }
        </style>
        <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
    </head>
    <apex:sectionHeader title="Hello StackOverflow!" subtitle="Contact full text search + Google Maps integration" />
    <apex:pageMessages />
    <apex:form id="form">
        <apex:pageBlock id="searchBlock">
            <apex:inputText value="{!searchText}" />
            <apex:commandButton value="Search" action="{!find}"/>
            <p>Examples: <a href="/apex/{!$CurrentPage.Name}?q=USA">"USA"</a>, "Singapore", "Uni", "(336) 222-7000". If it works in the global search box, it will work here.</p>
        </apex:pageBlock>
        <apex:pageBlock title="Found {!contacts.size} Contact(s)..." rendered="{!NOT(ISNULL(contacts)) && contacts.size > 0}" id="resultsBlock">
            <apex:pageBlockButtons location="top">
                <apex:commandButton value="Clear cached locations" title="Click if you want to set 'null' as geolocation info for all these contacts" action="{!clearGeocodedData}" />
            </apex:pageBlockButtons>
            <apex:pageBlockTable value="{!contacts}" var="c" id="contacts">
                <apex:column headerValue="{!$ObjectType.Contact.fields.Name.label}">
                    <apex:outputLink value="../{!c.Id}">{!c.Name}</apex:outputLink>
                </apex:column>
                <apex:column headerValue="Address">
                    {!c.MailingStreet} {!c.MailingCity} {!c.MailingCountry}
                </apex:column>
                <apex:column value="{!c.Account.Name}"/>
                <apex:column headerValue="Location (retrieved from DB or geocoded server-side)">
                    {!c.Location__Latitude__s}, {!c.Location__Longitude__s}
                </apex:column>
            </apex:pageBlockTable>
            <apex:pageBlockSection columns="1" id="mapSection">
                <div id="map_canvas" />
            </apex:pageBlockSection>
            <apex:pageBlockSection title="Click to show/hide what was geocoded server-side and passed to JS for further manipulation" columns="1" id="debugSection">
                <pre>{!debugContactsJson}</pre>
            </apex:pageBlockSection>
            <pre id="log"></pre>
        </apex:pageBlock>
    </apex:form>
    <script type="text/javascript">
    twistSection(document.getElementById('page:form:resultsBlock:debugSection').childNodes[0].childNodes[0]); // initially hide the debug section

    var contacts = {!contactsJson};    // Array of contact data, some of them might have lat/long info, some we'll have to geocode client side
    var coords = [];                   // Just the latitude/longitude for each contact
    var requestCounter = 0;

    var markers = [];                  // Red things we pin to the map.
    var balloon = new google.maps.InfoWindow(); // Comic-like baloon that floats over markers.

    function geocodeClientSide() {
        for(var i = 0; i < contacts.length; i++) {
            if(contacts[i].Location__Latitude__s != null && contacts[i].Location__Longitude__s != null) {
                coords.push(new google.maps.LatLng(contacts[i].Location__Latitude__s, contacts[i].Location__Longitude__s));
            } else {
                ++requestCounter;
                var address = contacts[i].MailingStreet + ' ' + contacts[i].MailingCity + ' ' + contacts[i].MailingCountry;
                var geocoder = new google.maps.Geocoder();
                if (geocoder) {
                    geocoder.geocode({'address':address}, function (results, status) {
                        if (status == google.maps.GeocoderStatus.OK) {
                            coords.push(results[0].geometry.location);
                        } else {
                            var pTag = document.createElement("p");
                            pTag.innerHTML = status;
                            document.getElementById('log').appendChild(pTag);
                        }
                        if(--requestCounter == 0) {
                            drawMap();
                        }
                    });
                }
            }
        }
        // It could be the case that all was geocoded on server side (or simply retrieved from database).
        // So if we're lucky - just proceed to drawing the map.
        if(requestCounter == 0) {
            drawMap();
        }
    }

    function drawMap(){
        var mapOptions = {
            center: coords[0],
            zoom: 3,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map(document.getElementById("map_canvas"),  mapOptions);

        for(var i = 0; i < coords.length; ++i){
            var marker = new google.maps.Marker({map: map, position: coords[i], title:contacts[i].Name, zIndex:i});

            google.maps.event.addListener(marker, 'click', function() {
                var index = this.zIndex;
                balloon.content = '<b>'+contacts[index].Name + '</b><br/>' + contacts[index].Account.Name + '<br/>' + contacts[index].Email;
                balloon.open(map,this);
            });
            markers.push(marker);
        }
    }

    geocodeClientSide();
    </script>
</apex:page>
11
ответ дан 18 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: