Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving sms conversations into crm task #72

Closed
wants to merge 1 commit into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,13 @@ public Optional<SObject> getUserByEmail(String email) throws ConnectionException
return querySingle(query);
}

protected static final String TASK_FIELDS = "Id, WhoId, OwnerId, Subject, description, status, priority, activityDate";

public Optional<SObject> getTaskBySubject(String subject) throws ConnectionException, InterruptedException {
String query = "select " + TASK_FIELDS + " from task where subject = '" + subject + "'";
return querySingle(query);
}

/**
* Use with caution, it retrieves ALL active users. Unsuitable for orgs with many users.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
import com.impactupgrade.nucleus.environment.EnvironmentFactory;
import com.impactupgrade.nucleus.model.ContactFormData;
import com.impactupgrade.nucleus.model.ContactSearch;
import com.impactupgrade.nucleus.model.CrmActivity;
import com.impactupgrade.nucleus.model.CrmContact;
import com.impactupgrade.nucleus.model.CrmCustomField;
import com.impactupgrade.nucleus.model.CrmImportEvent;
import com.impactupgrade.nucleus.model.CrmRecurringDonation;
import com.impactupgrade.nucleus.security.SecurityUtil;
import com.impactupgrade.nucleus.service.segment.CrmService;
import com.impactupgrade.nucleus.util.GoogleSheetsUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
Expand Down Expand Up @@ -60,6 +62,57 @@ public CrmController(EnvironmentFactory envFactory) {
this.envFactory = envFactory;
}

//TODO: remove once done with testing
@Path("/message")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response insertTask(
Message message,
@Context HttpServletRequest request
) throws Exception {
Environment env = envFactory.init(request);
//SecurityUtil.verifyApiKey(env);

CrmActivity crmActivity;
if (!Strings.isNullOrEmpty(message.conversationId)) {
Optional<CrmActivity> crmActivityOptional = env.primaryCrmService().getActivityByTypeAndConversationId(CrmActivity.Type.SMS_CONVERSATION, message.conversationId);
if (crmActivityOptional.isPresent()) {
// Existing conversation
crmActivity = crmActivityOptional.get();
} else {
// New conversation
crmActivity = new CrmActivity();
crmActivity.type = CrmActivity.Type.SMS_CONVERSATION;
crmActivity.conversationId = message.conversationId;
}
addMessage(message, crmActivity);
} else {
crmActivity = new CrmActivity();
crmActivity.type = CrmActivity.Type.SMS_CONVERSATION;
crmActivity.messageIds = List.of(message.id);
}
env.primaryCrmService().upsertActivity(crmActivity);


return Response.ok(crmActivity).build();
}

private static final class Message {
public String id;
public String conversationId;
}

private static void addMessage(Message message, CrmActivity crmActivity) {
List<String> ids = new ArrayList<>();
if (CollectionUtils.isNotEmpty(crmActivity.messageIds)) {
ids.addAll(crmActivity.messageIds);
}

ids.add(message.id);
crmActivity.messageIds = ids;
}

/**
* Retrieves a contact from the primary CRM using a variety of optional parameters. For use in external integrations,
* like Twilio Studio's retrieval of the CRM's Contact ID by phone number.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ public static class Salesforce extends Platform {
public CRMFieldDefinitions fieldDefinitions = new CRMFieldDefinitions();
public SalesforceCustomFields customQueryFields = new SalesforceCustomFields();
public String defaultCampaignId = "";
public String defaultTaskAssignee = "";

public static class SalesforceCustomFields {
public Set<String> account = new HashSet<>();
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/com/impactupgrade/nucleus/model/CrmActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.impactupgrade.nucleus.model;

import java.util.List;

public class CrmActivity {
Copy link
Contributor

Choose a reason for hiding this comment

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

A little confused about the difference between CrmActivity, CrmTask, and why we need both. Lean into that for me?

Copy link
Contributor

Choose a reason for hiding this comment

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

@VSydor Thoughts on this one?

Copy link
Contributor Author

@VSydor VSydor Dec 5, 2022

Choose a reason for hiding this comment

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

@brmeyer The idea is that crmActivity is a sub-type of crmTask that has crmActivityType (conversation or email) and conversationId fields. However, when converting to crmTask - these 2 fields just form the subject of the task (type + ":" + conversationId) so technically it's the same thing.

should I work directly with task and remove crmActivity?

Copy link
Contributor Author

@VSydor VSydor Dec 7, 2022

Choose a reason for hiding this comment

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

without CrmActivity will look like this:
#98

Please select the one that fits best


public String id;
public String targetId;
public String assignTo; // User ID

public CrmActivity.Type type;
public String conversationId;

public List<String> messageIds;

public enum Type {
SMS_CONVERSATION,
EMAIL;
}

}
1 change: 1 addition & 0 deletions src/main/java/com/impactupgrade/nucleus/model/CrmTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

public class CrmTask {

public String id;
public String targetId;
public String assignTo; // User ID
public String subject;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.impactupgrade.nucleus.service.segment;

import com.impactupgrade.nucleus.model.CrmAccount;
import com.impactupgrade.nucleus.model.CrmActivity;
import com.impactupgrade.nucleus.model.CrmContact;
import com.impactupgrade.nucleus.model.CrmCustomField;
import com.impactupgrade.nucleus.model.CrmDonation;
Expand Down Expand Up @@ -126,6 +127,18 @@ default String insertTask(CrmTask crmTask) throws Exception {
return null;
}

default String updateTask(CrmTask crmTask) throws Exception {
return null;
}

default String upsertActivity(CrmActivity crmActivity) throws Exception {
return null;
}

default Optional<CrmActivity> getActivityByTypeAndConversationId(CrmActivity.Type type, String externalId) throws Exception {
return Optional.empty();
}

default Map<String, List<String>> getActiveCampaignsByContactIds(List<String> contactIds) throws Exception {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.model.ContactSearch;
import com.impactupgrade.nucleus.model.CrmAccount;
import com.impactupgrade.nucleus.model.CrmActivity;
import com.impactupgrade.nucleus.model.CrmAddress;
import com.impactupgrade.nucleus.model.CrmContact;
import com.impactupgrade.nucleus.model.CrmCustomField;
Expand Down Expand Up @@ -574,6 +575,21 @@ public String insertTask(CrmTask crmTask) throws Exception {
return null;
}

@Override
public String updateTask(CrmTask crmTask) throws Exception {
return null;
}

@Override
public String upsertActivity(CrmActivity crmActivity) throws Exception {
return null;
}

@Override
public Optional<CrmActivity> getActivityByTypeAndConversationId(CrmActivity.Type type, String externalId) throws Exception {
return Optional.empty();
}

@Override
public List<CrmCustomField> insertCustomFields(String layoutName, List<CrmCustomField> crmCustomFields) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.model.ContactSearch;
import com.impactupgrade.nucleus.model.CrmAccount;
import com.impactupgrade.nucleus.model.CrmActivity;
import com.impactupgrade.nucleus.model.CrmContact;
import com.impactupgrade.nucleus.model.CrmCustomField;
import com.impactupgrade.nucleus.model.CrmDonation;
Expand Down Expand Up @@ -224,6 +225,9 @@ default void updateContact(OpportunityEvent opportunityEvent) throws Exception {
Optional<CrmUser> getUserById(String id) throws Exception;
Optional<CrmUser> getUserByEmail(String email) throws Exception;
String insertTask(CrmTask crmTask) throws Exception;
String updateTask(CrmTask crmTask) throws Exception;
String upsertActivity(CrmActivity crmActivity) throws Exception;
Optional<CrmActivity> getActivityByTypeAndConversationId(CrmActivity.Type type, String externalId) throws Exception;

List<CrmCustomField> insertCustomFields(String layoutName, List<CrmCustomField> crmCustomFields);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.model.ContactSearch;
import com.impactupgrade.nucleus.model.CrmAccount;
import com.impactupgrade.nucleus.model.CrmActivity;
import com.impactupgrade.nucleus.model.CrmAddress;
import com.impactupgrade.nucleus.model.CrmContact;
import com.impactupgrade.nucleus.model.CrmCustomField;
Expand Down Expand Up @@ -270,6 +271,21 @@ public String insertTask(CrmTask crmTask) throws Exception {
return response == null ? null : response.getId() + "";
}

@Override
public String updateTask(CrmTask crmTask) throws Exception {
return null;
}

@Override
public String upsertActivity(CrmActivity crmActivity) throws Exception {
return null;
}

@Override
public Optional<CrmActivity> getActivityByTypeAndConversationId(CrmActivity.Type type, String externalId) throws Exception {
return Optional.empty();
}

@Override
public List<CrmCustomField> insertCustomFields(String layoutName, List<CrmCustomField> crmCustomFields) {
Map<String, List<CrmCustomField>> propertiesByObjectTypes = crmCustomFields.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.model.ContactSearch;
import com.impactupgrade.nucleus.model.CrmAccount;
import com.impactupgrade.nucleus.model.CrmActivity;
import com.impactupgrade.nucleus.model.CrmContact;
import com.impactupgrade.nucleus.model.CrmCustomField;
import com.impactupgrade.nucleus.model.CrmDonation;
Expand Down Expand Up @@ -211,6 +212,21 @@ public String insertTask(CrmTask crmTask) throws Exception {
return null;
}

@Override
public String updateTask(CrmTask crmTask) throws Exception {
return null;
}

@Override
public String upsertActivity(CrmActivity crmActivity) throws Exception {
return null;
}

@Override
public Optional<CrmActivity> getActivityByTypeAndConversationId(CrmActivity.Type type, String externalId) throws Exception {
return null;
}

@Override
public List<CrmCustomField> insertCustomFields(String layoutName, List<CrmCustomField> crmCustomFields) {
return Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package com.impactupgrade.nucleus.service.segment;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
Expand All @@ -16,6 +17,7 @@
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.model.ContactSearch;
import com.impactupgrade.nucleus.model.CrmAccount;
import com.impactupgrade.nucleus.model.CrmActivity;
import com.impactupgrade.nucleus.model.CrmAddress;
import com.impactupgrade.nucleus.model.CrmCampaign;
import com.impactupgrade.nucleus.model.CrmContact;
Expand All @@ -33,6 +35,7 @@
import com.sforce.soap.metadata.FieldType;
import com.sforce.soap.partner.sobject.SObject;
import com.sforce.ws.ConnectionException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand Down Expand Up @@ -227,6 +230,89 @@ public String insertTask(CrmTask crmTask) throws Exception {
return sfdcClient.insert(task).getId();
}

@Override
public String updateTask(CrmTask crmTask) throws Exception {
SObject task = new SObject("Task");
setTaskFields(task, crmTask);
return sfdcClient.update(task).getId();
}

@Override
public String upsertActivity(CrmActivity crmActivity) throws Exception {
CrmTask crmTask = toCrmTask(crmActivity);
if (Strings.isNullOrEmpty(crmActivity.id)) {
return insertTask(crmTask);
} else {
return updateTask(crmTask);
}
}

@Override
public Optional<CrmActivity> getActivityByTypeAndConversationId(CrmActivity.Type type, String externalId) throws Exception {
String subject = type + ":" + externalId;
Optional<SObject> sObjectO = sfdcClient.getTaskBySubject(subject);
CrmTask crmTask = sObjectO.map(this::toCrmTask).orElse(null);
return Optional.of(toCrmActivity(crmTask));
}

protected CrmTask toCrmTask(SObject sObject) {
CrmTask crmTask = new CrmTask(
//sObject.getField("WhoId").toString(),
null,
sObject.getField("OwnerId").toString(),
sObject.getField("Subject").toString(),
sObject.getField("Description").toString(),
//CrmTask.Status.valueOf(sObject.getField("Status").toString()),
null,
//CrmTask.Priority.valueOf(sObject.getField("Priority").toString())
null,
null);
crmTask.id = sObject.getId();
return crmTask;
}

private CrmTask toCrmTask(CrmActivity crmActivity) {
CrmTask crmTask = new CrmTask();
crmTask.id = crmActivity.id;
crmTask.subject = crmActivity.type.name();
if (!Strings.isNullOrEmpty(crmActivity.conversationId)) {
crmTask.subject = crmTask.subject + ":" + crmActivity.conversationId;
}
if (CollectionUtils.isNotEmpty(crmActivity.messageIds)) {
crmTask.description = crmActivity.messageIds.stream()
.collect(Collectors.joining(","));
}

crmTask.assignTo = env.getConfig().salesforce.defaultTaskAssignee;
crmTask.status = CrmTask.Status.TO_DO;
crmTask.priority = CrmTask.Priority.MEDIUM;

return crmTask;
}

private CrmActivity toCrmActivity(CrmTask crmTask) {
CrmActivity crmActivity = new CrmActivity();

crmActivity.id = crmTask.id;
crmActivity.targetId = crmTask.targetId;
crmActivity.assignTo = crmTask.assignTo;

String subject = crmTask.subject;
String[] split = subject.split(":");

crmActivity.type = CrmActivity.Type.valueOf(split[0]);
if (split.length > 1) {
crmActivity.conversationId = split[1];
}
if (!Strings.isNullOrEmpty(crmTask.description)) {
crmActivity.messageIds = Splitter.on(",")
.trimResults()
.splitToList(crmTask.description);
}

return crmActivity;
}

@Override
public List<CrmCustomField> insertCustomFields(String layoutName, List<CrmCustomField> crmCustomFields) {
try {
Expand Down Expand Up @@ -269,6 +355,9 @@ public EnvironmentConfig.CRMFieldDefinitions getFieldDefinitions() {
}

protected void setTaskFields(SObject task, CrmTask crmTask) {
if (crmTask != null) {
task.setField("Id", crmTask.id);
}
task.setField("WhoId", crmTask.targetId);
task.setField("OwnerId", crmTask.assignTo);
task.setField("Subject", crmTask.subject);
Expand Down
Loading