Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions force-app/main/default/classes/ContactTriggerHandler.cls
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

DummyJSONCallout.getDummyJSONUserFromId(cont.DummyJSON_Id__c);
}
}
Expand All @@ -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<Id, Contact> contsById = new Map<Id, Contact>();
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));
}
}
}
65 changes: 33 additions & 32 deletions force-app/main/default/classes/DummyJSONCallout.cls
Original file line number Diff line number Diff line change
Expand Up @@ -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<Id> postCreateDummyJSONUser(Set<Id> contactIds) {
// Query the contact to get the field values to generate the JSON payload.
List<Contact> contacts = [
SELECT Id, FirstName, LastName, Email, Phone, DummyJSON_Id__c
FROM Contact
WHERE Id IN :contactIds
];

List<Id> contactIsToUpdate = new List<Id>();
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;
}

/*
Expand All @@ -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<String, Object> valuesMap = new Map<String, Object>();
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.

Expand Down
11 changes: 9 additions & 2 deletions force-app/main/default/classes/DummyJSONCalloutTest.cls
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,18 @@ public with sharing class DummyJSONCalloutTest {
Phone = '+123456789'
);
insert testContact;
// Suvorova
Map<Id, Contact> contsById = new Map<Id, Contact>();
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
Expand All @@ -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<String, Object> payloadMap = (Map<String, Object>) JSON.deserializeUntyped(payload);
Expand Down
22 changes: 22 additions & 0 deletions force-app/main/default/classes/PostDummyJSONUserQueueable.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
public class PostDummyJSONUserQueueable implements Queueable, Database.AllowsCallouts {

private Map<Id, Contact> contsById;

public PostDummyJSONUserQueueable(Map<Id, Contact> contactsById) {
this.contsById = contactsById;
}

public void execute(QueueableContext qc) {
List<Id> contactIdsForUpdate = DummyJSONCallout.postCreateDummyJSONUser(this.contsById.keySet());

List<Contact> contacts = [
SELECT Id, DummyJSON_Last_Updated__c
FROM Contact
WHERE Id IN :contactIdsForUpdate
];
for (Contact cont : contacts) {
cont.DummyJSON_Last_Updated__c = Datetime.now();
}
Comment on lines +17 to +19

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move this inside the postCreatedummyJSON.
It's okay to update them after the code has finished but this logic seems like a part of the post.

Database.update(contacts);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>59.0</apiVersion>
<status>Active</status>
</ApexClass>