diff --git a/force-app/main/default/classes/ContactTriggerHandler.cls b/force-app/main/default/classes/ContactTriggerHandler.cls index 5dbdc67..67af4c0 100644 --- a/force-app/main/default/classes/ContactTriggerHandler.cls +++ b/force-app/main/default/classes/ContactTriggerHandler.cls @@ -35,7 +35,7 @@ public with sharing class ContactTriggerHandler extends TriggerHandler { if (cont.DummyJSON_Id__c == null) { cont.DummyJSON_Id__c = String.valueOf(Math.round(Math.random() * 100)); } - if (Integer.valueOf(cont.DummyJSON_Id__c) <= 100 && !System.isFuture()) { + if (Integer.valueOf(cont.DummyJSON_Id__c) <= 100 && !System.isFuture() && !System.isQueueable()) { DummyJSONCallout.getDummyJSONUserFromId(cont.DummyJSON_Id__c); } } @@ -48,10 +48,15 @@ public with sharing class ContactTriggerHandler extends TriggerHandler { * if DummyJSON_Id__c is greater than 100, call the postCreateDummyJSONUser API */ public override void afterUpdate() { - for (Contact cont : newConts) { - if (Integer.valueOf(cont.DummyJSON_Id__c) > 100 && !System.isFuture()) { - DummyJSONCallout.postCreateDummyJSONUser(cont.Id); + if (!System.isQueueable() && !System.isFuture()) { + Map contsById = new Map(); + for (Contact cont : newConts) { + if (Integer.valueOf(cont.DummyJSON_Id__c) > 100) { + // DummyJSONCallout.postCreateDummyJSONUser(cont.Id); + contsById.put(cont.Id, cont); + } } + System.enqueueJob(new PostDummyJSONUserQueueable(contsById)); } } } \ No newline at end of file diff --git a/force-app/main/default/classes/DummyJSONCallout.cls b/force-app/main/default/classes/DummyJSONCallout.cls index 8981103..a4b775d 100644 --- a/force-app/main/default/classes/DummyJSONCallout.cls +++ b/force-app/main/default/classes/DummyJSONCallout.cls @@ -111,31 +111,36 @@ public with sharing class DummyJSONCallout { * * @param contactId The Salesforce Contact ID used to generate the JSON payload for the external system. */ - @future(callout = true) - public static void postCreateDummyJSONUser(String contactId) { - // Create HTTP request to send. - HttpRequest request = new HttpRequest(); - // Set the endpoint URL. Use direct URL or for best practices use Named Credential. - request.setEndpoint('callout:DummyJsonUser/add'); - // Set the HTTP method to POST. - request.setMethod('POST'); - // Set the body using generateDummyJsonUserPayload method. - // String jsonBody = generateDummyJsonUserPayload(); - // if (jsonBody.length() > 0) - request.setBody(generateDummyJsonUserPayload(contactId)); - - // Send the HTTP request and get the response. - Http http = new Http(); - HttpResponse response = http.send(request); - // If the HTTP response code is successful, update the contact. - if (response.getStatusCode() >= 200 || response.getStatusCode() <= 299) { - Contact cont = [ - SELECT Id, DummyJSON_Last_Updated__c - FROM Contact - WHERE Id = :contactId]; - cont.DummyJSON_Last_Updated__c = Datetime.now(); - update cont; + + public static List postCreateDummyJSONUser(Set contactIds) { + // Query the contact to get the field values to generate the JSON payload. + List contacts = [ + SELECT Id, FirstName, LastName, Email, Phone, DummyJSON_Id__c + FROM Contact + WHERE Id IN :contactIds + ]; + + List contactIsToUpdate = new List(); + for (Contact cont : contacts) { + String json = generateDummyJsonUserPayload(cont); + // Create HTTP request to send. + HttpRequest request = new HttpRequest(); + // Set the endpoint URL. Use direct URL or for best practices use Named Credential. + request.setEndpoint('callout:DummyJsonUser/add'); + // Set the HTTP method to POST. + request.setMethod('POST'); + // Set the body using generateDummyJsonUserPayload method. + request.setBody(json); + + // Send the HTTP request and get the response. + Http http = new Http(); + HttpResponse response = http.send(request); + // If the HTTP response code is successful, update the contact. + if (response.getStatusCode() >= 200 || response.getStatusCode() <= 299) { + contactIsToUpdate.add(cont.Id); + } } + return contactIsToUpdate; } /* @@ -154,22 +159,18 @@ public with sharing class DummyJSONCallout { * @return String The JSON string payload that represents the Contact's details. */ @TestVisible // Allows test class to see this method. Since it is private, it would not be visible otherwise. - private static String generateDummyJsonUserPayload(String contactId) { - // Query the contact to get the field values to generate the JSON payload. - Contact cont = [ - SELECT Id, FirstName, LastName, Email, Phone, DummyJSON_Id__c - FROM Contact - WHERE Id = :contactId - ]; + private static String generateDummyJsonUserPayload(Contact cont) { + // Create a map of the field values. Map valuesMap = new Map(); - valuesMap.put('salesforceId', contactId); + valuesMap.put('salesforceId', String.valueOf(cont.Id)); valuesMap.put('firstName', String.isNotBlank(cont.FirstName) ? cont.FirstName : 'unknown'); valuesMap.put('lastName', String.isNotBlank(cont.LastName) ? cont.LastName : 'unknown'); valuesMap.put('email', String.isNotBlank(cont.Email) ? cont.Email : 'unknown'); valuesMap.put('phone', String.isNotBlank(cont.Phone) ? cont.Phone : 'unknown'); // Serialize the map into a JSON string. String json = JSON.serialize(valuesMap); + // Make sure to check that required contacts fields have a value. Default the value to unknown if it does not exists. // Integration data can change over time. It is a best practice to add safeguards/validation to ensure the integration does not break. diff --git a/force-app/main/default/classes/DummyJSONCalloutTest.cls b/force-app/main/default/classes/DummyJSONCalloutTest.cls index dbc6043..1af3921 100644 --- a/force-app/main/default/classes/DummyJSONCalloutTest.cls +++ b/force-app/main/default/classes/DummyJSONCalloutTest.cls @@ -66,13 +66,18 @@ public with sharing class DummyJSONCalloutTest { Phone = '+123456789' ); insert testContact; + // Suvorova + Map contsById = new Map(); + contsById.put(testContact.Id, testContact); // Set the mock callout class Test.setMock(HttpCalloutMock.class, new DummyJSONCalloutMockGenerator()); // As this is a future method, we need to enclose it in Test.startTest() and Test.stopTest() to ensure it's executed in the test context. Test.startTest(); - DummyJSONCallout.postCreateDummyJSONUser(testContact.Id); + // Suvorova + // DummyJSONCallout.postCreateDummyJSONUser(testContact.Id); + System.enqueueJob(new PostDummyJSONUserQueueable(contsById)); Test.stopTest(); // Retrieve the updated contact to verify the changes @@ -99,7 +104,9 @@ public with sharing class DummyJSONCalloutTest { insert testContact; // Call the method - String payload = DummyJSONCallout.generateDummyJsonUserPayload(testContact.Id); + // Suvorova + // String payload = DummyJSONCallout.generateDummyJsonUserPayload(testContact.Id); + String payload = DummyJSONCallout.generateDummyJsonUserPayload(testContact); // Parse the generated JSON Map payloadMap = (Map) JSON.deserializeUntyped(payload); diff --git a/force-app/main/default/classes/PostDummyJSONUserQueueable.cls b/force-app/main/default/classes/PostDummyJSONUserQueueable.cls new file mode 100644 index 0000000..1b15017 --- /dev/null +++ b/force-app/main/default/classes/PostDummyJSONUserQueueable.cls @@ -0,0 +1,22 @@ +public class PostDummyJSONUserQueueable implements Queueable, Database.AllowsCallouts { + + private Map contsById; + + public PostDummyJSONUserQueueable(Map contactsById) { + this.contsById = contactsById; + } + + public void execute(QueueableContext qc) { + List contactIdsForUpdate = DummyJSONCallout.postCreateDummyJSONUser(this.contsById.keySet()); + + List contacts = [ + SELECT Id, DummyJSON_Last_Updated__c + FROM Contact + WHERE Id IN :contactIdsForUpdate + ]; + for (Contact cont : contacts) { + cont.DummyJSON_Last_Updated__c = Datetime.now(); + } + Database.update(contacts); + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/PostDummyJSONUserQueueable.cls-meta.xml b/force-app/main/default/classes/PostDummyJSONUserQueueable.cls-meta.xml new file mode 100644 index 0000000..019e850 --- /dev/null +++ b/force-app/main/default/classes/PostDummyJSONUserQueueable.cls-meta.xml @@ -0,0 +1,5 @@ + + + 59.0 + Active + \ No newline at end of file