244 lines
7.5 KiB
OpenEdge ABL
244 lines
7.5 KiB
OpenEdge ABL
public inherited sharing class CreateEmailToCase {
|
|
public class Request {
|
|
@InvocableVariable(required=true label='Routing Name')
|
|
public String routingName;
|
|
|
|
@InvocableVariable(required=true label='Email Address')
|
|
public String emailAddress;
|
|
|
|
@InvocableVariable(required=true label='Case Owner Queue Id')
|
|
public Id caseOwnerId;
|
|
|
|
@InvocableVariable(required=true label='Case Origin')
|
|
public String caseOrigin;
|
|
}
|
|
|
|
public class Result {
|
|
@InvocableVariable(label='Metadata Full Name')
|
|
public String metadataFullName;
|
|
|
|
@InvocableVariable(label='Routing Name')
|
|
public String routingName;
|
|
|
|
@InvocableVariable(label='Email Address')
|
|
public String emailAddress;
|
|
|
|
@InvocableVariable(label='Email-to-Case Address')
|
|
public String emailToCaseAddress;
|
|
|
|
@InvocableVariable(label='Email Routing Address Id')
|
|
public Id emailRoutingAddressId;
|
|
|
|
@InvocableVariable(label='Created')
|
|
public Boolean created;
|
|
}
|
|
|
|
@InvocableMethod(
|
|
label='Create Email-To-Case'
|
|
description='Adds an on-demand Email-to-Case routing address to Case Settings.'
|
|
category='Queue Configuration'
|
|
callout=true
|
|
)
|
|
public static List<Result> createRoutingAddress(List<Request> requests) {
|
|
MetadataXml.require(
|
|
requests != null && requests.size() == 1,
|
|
'Create Email-To-Case accepts exactly one request per invocation.'
|
|
);
|
|
Request input = requests[0];
|
|
input.routingName = input.routingName == null
|
|
? null
|
|
: input.routingName.trim();
|
|
input.emailAddress = input.emailAddress == null
|
|
? null
|
|
: input.emailAddress.trim();
|
|
input.caseOrigin = input.caseOrigin == null
|
|
? null
|
|
: input.caseOrigin.trim();
|
|
MetadataXml.require(
|
|
!String.isBlank(input.routingName),
|
|
'Routing Name is required.'
|
|
);
|
|
MetadataXml.require(
|
|
!String.isBlank(input.emailAddress),
|
|
'Email Address is required.'
|
|
);
|
|
MetadataXml.require(
|
|
input.caseOwnerId != null,
|
|
'Case Owner Queue Id is required.'
|
|
);
|
|
MetadataXml.require(
|
|
!String.isBlank(input.caseOrigin),
|
|
'Case Origin is required.'
|
|
);
|
|
|
|
List<Group> queues = [
|
|
SELECT Id, DeveloperName
|
|
FROM Group
|
|
WHERE Id = :input.caseOwnerId AND Type = 'Queue'
|
|
WITH USER_MODE
|
|
LIMIT 1
|
|
];
|
|
MetadataXml.require(
|
|
!queues.isEmpty(),
|
|
'Case Owner Id must identify a queue.'
|
|
);
|
|
|
|
Dom.XmlNode caseSettings = MetadataApiClient.readMetadata(
|
|
'CaseSettings',
|
|
'Case'
|
|
);
|
|
MetadataXml.require(
|
|
caseSettings != null,
|
|
'Case Settings metadata was not found.'
|
|
);
|
|
Dom.XmlNode emailToCase = MetadataXml.child(caseSettings, 'emailToCase');
|
|
MetadataXml.require(
|
|
emailToCase != null,
|
|
'Email-to-Case is not configured. Enable Email-to-Case in Setup before creating a routing address.'
|
|
);
|
|
|
|
for (
|
|
Dom.XmlNode route : MetadataXml.children(emailToCase, 'routingAddresses')
|
|
) {
|
|
String existingName = MetadataXml.text(route, 'routingName');
|
|
String existingAddress = MetadataXml.text(route, 'emailAddress');
|
|
Boolean sameName = input.routingName.equalsIgnoreCase(existingName);
|
|
Boolean sameAddress = input.emailAddress.equalsIgnoreCase(
|
|
existingAddress
|
|
);
|
|
if (sameName || sameAddress) {
|
|
MetadataXml.require(
|
|
sameName && sameAddress,
|
|
'An Email-to-Case routing address already uses this routing name or email address with different values.'
|
|
);
|
|
return new List<Result>{ buildResult(input, false) };
|
|
}
|
|
}
|
|
|
|
String routeXml =
|
|
'<routingAddresses>' +
|
|
'<addressType>EmailToCase</addressType>' +
|
|
'<caseOrigin>' +
|
|
MetadataXml.escape(input.caseOrigin) +
|
|
'</caseOrigin>' +
|
|
'<caseOwner>' +
|
|
MetadataXml.escape(queues[0].DeveloperName) +
|
|
'</caseOwner>' +
|
|
'<caseOwnerType>Queue</caseOwnerType>' +
|
|
'<casePriority>Medium</casePriority>' +
|
|
'<emailAddress>' +
|
|
MetadataXml.escape(input.emailAddress) +
|
|
'</emailAddress>' +
|
|
'<routingName>' +
|
|
MetadataXml.escape(input.routingName) +
|
|
'</routingName>' +
|
|
'<saveEmailHeaders>false</saveEmailHeaders>' +
|
|
'</routingAddresses>';
|
|
String emailToCaseXml = '<emailToCase>';
|
|
Boolean inserted = false;
|
|
for (Dom.XmlNode child : emailToCase.getChildElements()) {
|
|
if (!inserted && child.getName().compareTo('routingAddresses') > 0) {
|
|
emailToCaseXml += routeXml;
|
|
inserted = true;
|
|
}
|
|
emailToCaseXml += MetadataXml.serialize(child);
|
|
}
|
|
if (!inserted) {
|
|
emailToCaseXml += routeXml;
|
|
}
|
|
emailToCaseXml += '</emailToCase>';
|
|
|
|
MetadataApiClient.updateMetadata(
|
|
'CaseSettings',
|
|
MetadataXml.replaceOrInsertChild(
|
|
caseSettings,
|
|
'emailToCase',
|
|
emailToCaseXml
|
|
)
|
|
);
|
|
return new List<Result>{ buildResult(input, true) };
|
|
}
|
|
|
|
private static Result buildResult(Request input, Boolean created) {
|
|
Result result = new Result();
|
|
result.metadataFullName = 'Case';
|
|
result.routingName = input.routingName;
|
|
result.emailAddress = input.emailAddress;
|
|
result.created = created;
|
|
|
|
Schema.SObjectType routingType = Schema.getGlobalDescribe()
|
|
.get('EmailRoutingAddress');
|
|
if (routingType == null) {
|
|
return result;
|
|
}
|
|
Map<String, Schema.SObjectField> fields = routingType.getDescribe()
|
|
.fields.getMap();
|
|
String addressField = fields.containsKey('EmailAddress')
|
|
? 'EmailAddress'
|
|
: (fields.containsKey('Address') ? 'Address' : null);
|
|
if (addressField == null) {
|
|
return result;
|
|
}
|
|
|
|
List<String> selectFields = new List<String>{ 'Id', addressField };
|
|
if (fields.containsKey('RoutingAddress')) {
|
|
selectFields.add('RoutingAddress');
|
|
}
|
|
if (fields.containsKey('EmailServicesAddressId')) {
|
|
selectFields.add('EmailServicesAddressId');
|
|
}
|
|
String query =
|
|
'SELECT ' +
|
|
String.join(selectFields, ',') +
|
|
' FROM EmailRoutingAddress WHERE ' +
|
|
addressField +
|
|
' = :emailAddress LIMIT 1';
|
|
List<SObject> matches = Database.queryWithBinds(
|
|
query,
|
|
new Map<String, Object>{ 'emailAddress' => input.emailAddress },
|
|
AccessLevel.USER_MODE
|
|
);
|
|
if (matches.isEmpty()) {
|
|
return result;
|
|
}
|
|
|
|
result.emailRoutingAddressId = (Id) matches[0].get('Id');
|
|
if (fields.containsKey('RoutingAddress')) {
|
|
result.emailToCaseAddress = (String) matches[0].get('RoutingAddress');
|
|
} else if (fields.containsKey('EmailServicesAddressId')) {
|
|
result.emailToCaseAddress = emailServicesAddress(
|
|
(Id) matches[0].get('EmailServicesAddressId')
|
|
);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static String emailServicesAddress(Id serviceAddressId) {
|
|
if (serviceAddressId == null) {
|
|
return null;
|
|
}
|
|
Schema.SObjectType serviceType = Schema.getGlobalDescribe()
|
|
.get('EmailServicesAddress');
|
|
if (serviceType == null) {
|
|
return null;
|
|
}
|
|
Map<String, Schema.SObjectField> fields = serviceType.getDescribe()
|
|
.fields.getMap();
|
|
if (
|
|
!fields.containsKey('LocalPart') || !fields.containsKey('EmailDomainName')
|
|
) {
|
|
return null;
|
|
}
|
|
List<SObject> rows = Database.queryWithBinds(
|
|
'SELECT LocalPart, EmailDomainName FROM EmailServicesAddress WHERE Id = :serviceAddressId LIMIT 1',
|
|
new Map<String, Object>{ 'serviceAddressId' => serviceAddressId },
|
|
AccessLevel.USER_MODE
|
|
);
|
|
return rows.isEmpty()
|
|
? null
|
|
: String.valueOf(rows[0].get('LocalPart')) +
|
|
'@' +
|
|
String.valueOf(rows[0].get('EmailDomainName'));
|
|
}
|
|
}
|