1

My company uses data.com premium. We want to create a trigger that will update a lead based on company information since the out-of-the-box functionality only matches based on the lead. (contact). I have learned how to write triggers/classes out of necessity (lone admin), but this seems to require someone with more experience than I have.

I have spent about 40 hours trying to piece together information from the Integration Workbook, the heroku Json2apex converter and many other articles and help documentation. Based on the example in the Integration Workbook I was able to write a trigger that passes a list of lead ids to a class.. The class seems to gather the right information for the JSON request (I think) but since the list of leads needs the lead ID to update the lead, and the info returned from the API does not include the ID.. I am just at a loss. I have asked for help from data.com but the (rightly) want to charge me for services. We were not aware that this was not out-of-the box functionality when we purchased the premium. Our bad.

Any help would be much appreciated. Currently this trigger is only attempting to populate the company name, my plan was to get this working, and then incorporate all of the other fields. Most of our leads will only contain company, email, phone, country for matching purposes, we want to return as much info as possible.

Class

public class JSON2Apex {
    public static void consumeObject(JSONParser parser) {
        Integer depth = 0;
        do {
            JSONToken curr = parser.getCurrentToken();
            if (curr == JSONToken.START_OBJECT || 
                curr == JSONToken.START_ARRAY) {
                depth++;
            } else if (curr == JSONToken.END_OBJECT ||
                curr == JSONToken.END_ARRAY) {
                depth--;
            }
        } while (depth > 0 && parser.nextToken() != null);
    }

    public class Attributes {
        public String type {get;set;}

        public Attributes(JSONParser parser) {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != JSONToken.VALUE_NULL) {
                        if (text == 'type') {
                            type = parser.getText();
                        } else {
                            System.debug(LoggingLevel.WARN, 'Attributes consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }

    public class Entities {
        public Attributes attributes {get;set;}
        public String City {get;set;}
        public String Country {get;set;}
        public String DunsNumber {get;set;}
        public String Name {get;set;}
        public String Phone {get;set;}
        public String Street {get;set;}
        public String Zip {get;set;}

        public Entities(JSONParser parser) {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != JSONToken.VALUE_NULL) {
                        if (text == 'attributes') {
                            attributes = new Attributes(parser);
                        } else if (text == 'City') {
                            City = parser.getText();
                        } else if (text == 'Country') {
                            Country = parser.getText();
                        } else if (text == 'DunsNumber') {
                            DunsNumber = parser.getText();
                        } else if (text == 'Name') {
                            Name = parser.getText();
                        } else if (text == 'Phone') {
                            Phone = parser.getText();
                        } else if (text == 'Street') {
                            Street = parser.getText();
                        } else if (text == 'Zip') {
                            Zip = parser.getText();
                        } else {
                            System.debug(LoggingLevel.WARN, 'Entities consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }

    public List<Entities> entities {get;set;}
    public MatchOptions matchOptions {get;set;}

    public JSON2Apex(JSONParser parser) {
        while (parser.nextToken() != JSONToken.END_OBJECT) {
            if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                String text = parser.getText();
                if (parser.nextToken() != JSONToken.VALUE_NULL) {
                    if (text == 'entities') {
                        entities = new List<Entities>();
                        while (parser.nextToken() != JSONToken.END_ARRAY) {
                            entities.add(new Entities(parser));
                        }
                    } else if (text == 'matchOptions') {
                        matchOptions = new MatchOptions(parser);
                    } else {
                        System.debug(LoggingLevel.WARN, 'Root consuming unrecognized property: '+text);
                        consumeObject(parser);
                    }
                }
            }
        }
    }

    public class MatchOptions {
        public String fields {get;set;}

        public MatchOptions(JSONParser parser) {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != JSONToken.VALUE_NULL) {
                        if (text == 'fields') {
                            fields = parser.getText();
                        } else {
                            System.debug(LoggingLevel.WARN, 'MatchOptions consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }

     @future (callout=true) // indicates that this is an asynchronous call
    public static void postOrder(List<Id> leadIds) {

     List<Lead> ld = [SELECT Id, Company, Country, phone, street, postalcode FROM Lead where Id IN :leadIds];
         for (Lead l : ld)    {
                // Create a JSON generator object
        JSONGenerator gen = JSON.createGenerator(true);
        // open the JSON generator
            gen.writeStartObject();

            gen.writeStringField('Name', l.Company);

            gen.writeEndObject(); 

        // close the JSON generator

        // create a string from the JSON generator
        String jsonOrders = gen.getAsString();
        // debugging call, which you can check in debug logs
        System.debug('jsonOrders: ' + jsonOrders);



        // create an HTTPrequest object    
        HttpRequest req = new HttpRequest();

        req.setMethod('POST');

        req.setEndpoint('https://cs15.salesforce.com/services/data/v32.0/match/DunsRightMatchEngine/DatacloudCompany/DunsRightMatchRule');
        req.setHeader('Content-Type', 'application/json');
        req.setBody(jsonOrders);    
        // create a new HTTP object
        Http http = new Http();
        // create a new HTTP response for receiving the remote response
        // then use it to send the configured HTTPrequest
        HTTPResponse res = http.send(req);




{
            // Retrieve all of the Lead records
            // originally passed into the method call to prep for update.           
            List<Lead> leads =
              [SELECT Id FROM Lead WHERE Id IN :ld];
            // Create a list of entities by deserializing the
            // JSON data returned by the fulfillment service.
            List<Entities> ddcdata =
              (List<Entities>)JSON.deserialize(res.getBody(),
                List<Entities>.class);
            // Create a map of Lead IDs from the retrieved
            // invoices list.
            Map<Id, Lead> leadMap =
              new Map<Id, Lead>(leads);

            for ( Entities ddc : ddcdata ) {
              Lead lead = leadMap.get(ddc.Id);
              lead.Company = String.valueOf(ddc.Name);
            }
            // Update all leads in the database with a bulk update
            update leads;
        }

         }      
    }   

}

Trigger

trigger LeadDDCAccountMatch on Lead (after insert) {

    List<Id> leadIds = new List<Id>();

    for (Lead lead: Trigger.new) {
        if (lead.status == 'Cold'){
            leadIds.add(lead.Id);
        }
    }

    if (leadIds.size() > 0) {
        Lead_fromJSON.postOrder(leadIds);
    }
 }

Info needed in the JSON request

{
  "entities": [
    {
      "attributes": {
        "type": "DatacloudCompany"
      }, 
      "City":  //city from lead
      "Country": //country from lead
      "DunsNumber": //companydunsnumber from lead
      "Name": //company name from lead
      "Phone": //phone from lead
      "Street": //street from lead
      "Zip": //postalcode from lead
    }
  ], 
  "matchOptions": {"fields": "City, CompanyId, Country, Description, DunsNumber, Name, Website, YearStarted, Zip"
  }
}   
3
  • Have you tried using a simple query with LIKE statements to get the companies instead of doing it with matchAPI? Something like this company = [select id from company where name LIKE : l.Company]; Nov 19, 2014 at 0:26
  • I tried it with a trigger, but the trigger could not make the callout. However, I have not tried it in a class... hmmm I hope I can make it that easy, and kind of sad it had not occurred to me before now. Nov 19, 2014 at 4:28
  • give it a try, no callouts required. Nov 19, 2014 at 11:38

2 Answers 2

1

Well, I got it figured out - with the callout. However, for those of you thinking of using this (DatacloudMatchEngine) - if you don't have the "city" nothing will ever match.

Trigger

trigger LeadDDCAccountMatch on Lead (after insert) {

    List<String> leadIds = new List<String>();

    for (Lead lead: Trigger.new) {
        if (lead.status == 'Cold'){
            leadIds.add(lead.company);
        }
    }

    if (leadIds.size() > 0) {
        Lead_fromJSON.postOrder(leadIds);
    }
 }

Class

public class Lead_fromJSON{

    public class Entities {
        public String Id {get; set;}
        public String Name {get; set;}
        public String phone {get; set;}
        public String city {get; set;}
    }

     @future (callout=true) // indicates that this is an asynchronous call
    public static void postOrder(List<String> leadIds) {

     List<Lead> ld = [SELECT Id, Company, Country, phone, Email_Domain__c FROM Lead where Company IN :leadIds];
         for (Lead l : ld)    {
                // Create a JSON generator object
        JSONGenerator gen = JSON.createGenerator(true);
        // open the JSON generator
            gen.writeStartObject();
            gen.writeStringField('Type', 'DatacloudCompany');
            gen.writeStringField('Name', l.Company);

            gen.writeStringField('Country', l.Country);
            gen.writeStringField('Website', l.Email_Domain__c);
            gen.writeEndObject(); 

        // close the JSON generator

        // create a string from the JSON generator
        String jsonOrders = gen.getAsString();
        // debugging call, which you can check in debug logs
        System.debug('jsonOrders: ' + jsonOrders);



        // create an HTTPrequest object    
        HttpRequest req = new HttpRequest();
        // set up the HTTP request with a method, endpoint, header, and body
        req.setMethod('POST');
        req.setEndpoint('https://cs15.salesforce.com//services/data/v32.0/match/DatacloudMatchEngine/DatacloudCompany/');
        req.setHeader('Content-Type', 'application/json');
        req.setBody(jsonOrders);    
        // create a new HTTP object
        Http http = new Http();
        // create a new HTTP response for receiving the remote response
        // then use it to send the configured HTTPrequest
        HTTPResponse res = http.send(req);




{
            // Retrieve all of the Lead records
            // originally passed into the method call to prep for update.           
            List<Lead> leads =
              [SELECT Id FROM Lead WHERE Id IN :ld];
            // Create a list of entities by deserializing the
            // JSON data returned by the fulfillment service.
            List<Entities> ddcdata =
              (List<Entities>)JSON.deserialize(res.getBody(),
                List<Entities>.class);
                    System.debug('ddcdata: ' + ddcdata);
            // Create a map of Lead IDs from the retrieved
            // invoices list.
            Map<String, Lead> leadMap =
              new Map<String, Lead>(leads);

            for ( Entities ddc : ddcdata ) {
              Lead lead = leadMap.get(ddc.Name);
              if (ddc.Name != null)
              lead.Company = String.valueOf(ddc.Name);
              lead.city = String.valueOf(ddc.Name);
            }
            // Update all leads in the database with a bulk update
            update leads;
        }

         }      
    }
}
0

Here is the real time request and Respone with successfull Request and Response

Request JSON TO APEX

public class fromJSON{
    public cls_entities[] entities;
    public cls_matchOptions matchOptions;
    Public class cls_entities {
        public cls_attributes attributes;
        public String City; //Mountain View
        public String Country;  //United States
        public String Name; //Google I Inc
        public String Phone;    //+1.650.253.0000
        public String State;    //CA
        public String Street;   //1600 Amphitheatre Pkwy
        public String Zip;  //94043-1351
    }
    Public class cls_attributes {
        public String type; //DatacloudCompany
    }
    Public class cls_matchOptions {
        public String fields;   //AnnualRevenue, City, CompanyId, Country, Description, DunsNumber, Fax, Industry, IsInactive, NaicsCode, NaicsDesc, Name, NumberOfEmployees, Ownership, Phone, Sic, SicDesc, Site, State, Street, TickerSymbol, TradeStyle, Website, YearStarted, Zip
    }
    public static fromJSON parse(String json){
        return (fromJSON) System.JSON.deserialize(json, fromJSON.class);
    }

Now the Class for Making API Call with Data.com . This will be Best case for making calls for Custom Address or location Objects based on Business needs jsonResponse will return the result . Next step would be paring the response and extract required details .

Public Class testDataAPIforCustomObject{

    public String accessToken;
    public String instanceUrl;
    public Wrapper wrapObj{get;set;}
    // Wrapper Class to Store the value from the Json.
    public class Wrapper{
        String id;
        String instance_url;
        String access_token;
        String issued_at;
        String signature;
    }
    public void postOrder(List<Id> leadIds) {

          fromJSON frmJson = new fromJSON();
          fromJSON.cls_matchOptions mcthOptions = new  fromJSON.cls_matchOptions();
          fromJSON.cls_entities listAddr = new fromJSON.cls_entities();
          fromJSON.cls_attributes attributs = new fromJSON.cls_attributes();
          fromJSON.cls_matchOptions matchop= new fromJSON.cls_matchOptions();
          List<fromJSON.cls_entities> LstEntities = new List<fromJSON.cls_entities>();

            // Logic to get access token           
            String clientId = '3MVG9Oe7T3Ol0ea5zCVJ5_Hf6MeuJM0jpI9UGbszmEX4jIon6mXlnJFvwqOhEIrg0pqBS0BCcuAoQAhm6nxJN';
            String clientSecret = '713695559755260947';

            //We can also store our username password in custom setting.
            String username='************';//salesforce username 
            String password='**passwordwithsecurityToken';//salesforce password
            // Generating the Access Token
            HttpRequest req = new HttpRequest();
            req.setMethod('POST');
            req.setEndpoint('yoursalesforceintance/services/oauth2/token');// this is the OAuth endpoint where this request will be hit
            req.setBody('grant_type=password&client_id='+clientId+'&client_secret='+clientSecret+'&username='+username+'&password='+password);

            Http http = new Http();
            HTTPResponse res = http.send(req);
            String str = res.getBody();
            wrapObj = (Wrapper)Json.deserialize(str,Wrapper.class);
            accessToken = wrapObj.access_token;
            instanceUrl = wrapObj.instance_url;
            system.debug('######'+accessToken );

          // Logic ends here 
          // Request Generation
          List<Lead> ld = [SELECT Id, Company,City, Country, phone, State,street, postalcode FROM Lead where Id IN :leadIds];
          for (Lead l : ld)    {
              attributs.type='DatacloudCompany';
              listAddr.attributes=attributs;
              listAddr.City=l.City;
              listAddr.Country=l.Country;
              listAddr.Name=l.Company;
              listAddr.Phone=l.phone;
              listAddr.State=l.state;
              listAddr.Street=l.street;
              listAddr.Zip=l.PostalCode;
              system.debug(''+listAddr);
              LstEntities.add(listAddr);
              mcthOptions.fields='AnnualRevenue, City, CompanyId, Country, Description, DunsNumber, Fax, Industry, IsInactive, NaicsCode, NaicsDesc, Name, NumberOfEmployees, Ownership, Phone, Sic, SicDesc, Site, State, Street, TickerSymbol, TradeStyle, Website, YearStarted, Zip';
              frmJson.matchOptions=mcthOptions;
              frmJson.entities=LstEntities;
              // Request Call to Data.com API 
               HttpRequest datareq = new HttpRequest();
               datareq .setMethod('POST');
               datareq .setEndpoint('https://nacrm--nacedev.cs12.my.salesforce.com/services/data/v43.0/match/DunsRightMatchEngine/DatacloudCompany/DunsRightMatchRule');
               datareq .setHeader('Authorization', 'OAuth '+wrapObj.access_token);
               datareq .setHeader('Content-Type', 'application/json');
               datareq .setBody(Json.serialize(frmJson));
                //req1.setBody(json); 
               Http httpsend = new Http();
               HTTPResponse responsefromRequest = httpsend .send(datareq );
               system.debug('###REQ####'+datareq+ '###Response####'+responsefromRequest);
               String jsonResponse=responsefromRequest.getBody();
               system.debug('$$$$$$$$$$$$$'+jsonResponse);
          }     

    }

}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .