feat: add recipient resolution from Client_Case__c lookup fields
- Queries Client_Case__c for Service_Coordinator__c and Docusign_Recipient_1__c - Resolves Contact/User name and email from lookup targets - Maps recipients to Docusign template roles: 'Service Coordinator' and 'Docusign Recipient #1' - Validates recipients exist and have email addresses - Supports both Contact and User lookup types - Role names and field names are configurable constants at top of class - Clear error messages if recipients are missing or have no email
This commit is contained in:
parent
4b1edd4d27
commit
4211648e2a
|
|
@ -1,11 +1,25 @@
|
|||
/**
|
||||
* @description Combines multiple Docusign templates into a single composite envelope
|
||||
* using the dfsle Apex Toolkit (Docusign for Salesforce managed package)
|
||||
* using the dfsle Apex Toolkit (Docusign for Salesforce managed package).
|
||||
* Recipients are resolved from Client_Case__c lookup fields.
|
||||
* @author Paul Huliganga
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
global with sharing class DocusignCompositeEnvelopeBuilder {
|
||||
|
||||
// ============================================================
|
||||
// CONFIGURATION: Update these constants if field/role names change
|
||||
// ============================================================
|
||||
|
||||
// API names of the lookup fields on Client_Case__c that point to recipient records
|
||||
// These are the "Select Lookup Field" values from the Docusign template recipient config
|
||||
private static final String FIELD_SERVICE_COORDINATOR = 'Service_Coordinator__c';
|
||||
private static final String FIELD_DOCUSIGN_RECIPIENT = 'Docusign_Recipient_1__c';
|
||||
|
||||
// Role names must match EXACTLY what's configured in the Docusign templates
|
||||
private static final String ROLE_SERVICE_COORDINATOR = 'Service Coordinator';
|
||||
private static final String ROLE_DOCUSIGN_RECIPIENT = 'Docusign Recipient #1';
|
||||
|
||||
@InvocableMethod(
|
||||
label='Send Composite Docusign Envelope'
|
||||
description='Combines multiple Docusign templates into a single envelope using dfsle Apex Toolkit'
|
||||
|
|
@ -25,7 +39,7 @@ global with sharing class DocusignCompositeEnvelopeBuilder {
|
|||
// Validate request
|
||||
DocusignEnvelopeRequestHandler.validateRequest(req);
|
||||
|
||||
// Create empty envelope linked to the source Salesforce record
|
||||
// Create empty envelope linked to the source record
|
||||
dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope(
|
||||
new dfsle.Entity(req.recordId)
|
||||
);
|
||||
|
|
@ -43,16 +57,18 @@ global with sharing class DocusignCompositeEnvelopeBuilder {
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Add all templates as documents to the envelope
|
||||
myEnvelope = myEnvelope.withDocuments(documents);
|
||||
|
||||
// Resolve recipients from Client_Case__c lookup fields
|
||||
List<dfsle.Recipient> recipients = resolveRecipients(req.recordId);
|
||||
myEnvelope = myEnvelope.withRecipients(recipients);
|
||||
|
||||
// Set email subject if provided
|
||||
if (String.isNotBlank(req.emailSubject)) {
|
||||
myEnvelope = myEnvelope.withEmail(req.emailSubject, '');
|
||||
}
|
||||
|
||||
// Send the envelope (true = send immediately)
|
||||
// Send the envelope
|
||||
myEnvelope = dfsle.EnvelopeService.sendEnvelope(myEnvelope, true);
|
||||
|
||||
// Success
|
||||
|
|
@ -82,6 +98,87 @@ global with sharing class DocusignCompositeEnvelopeBuilder {
|
|||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Resolves recipients from Client_Case__c lookup fields.
|
||||
* Queries the case record and related contacts to get name/email.
|
||||
* @param recordId The Client_Case__c record ID
|
||||
* @return List of dfsle.Recipient objects with role mappings
|
||||
*/
|
||||
private static List<dfsle.Recipient> resolveRecipients(String recordId) {
|
||||
// Query the Client_Case__c record with recipient lookup fields
|
||||
// NOTE: Adjust field API names if they differ in your org
|
||||
String query = 'SELECT Id, '
|
||||
+ FIELD_SERVICE_COORDINATOR + ', '
|
||||
+ FIELD_DOCUSIGN_RECIPIENT
|
||||
+ ' FROM Client_Case__c WHERE Id = :recordId LIMIT 1';
|
||||
|
||||
Client_Case__c caseRecord = Database.query(query);
|
||||
|
||||
List<dfsle.Recipient> recipients = new List<dfsle.Recipient>();
|
||||
Integer routingOrder = 1;
|
||||
|
||||
// Recipient 1: Service Coordinator
|
||||
Id serviceCoordinatorId = (Id) caseRecord.get(FIELD_SERVICE_COORDINATOR);
|
||||
if (serviceCoordinatorId != null) {
|
||||
recipients.add(buildRecipient(serviceCoordinatorId, ROLE_SERVICE_COORDINATOR, routingOrder++, recordId));
|
||||
}
|
||||
|
||||
// Recipient 2: Docusign Recipient #1
|
||||
Id docusignRecipientId = (Id) caseRecord.get(FIELD_DOCUSIGN_RECIPIENT);
|
||||
if (docusignRecipientId != null) {
|
||||
recipients.add(buildRecipient(docusignRecipientId, ROLE_DOCUSIGN_RECIPIENT, routingOrder++, recordId));
|
||||
}
|
||||
|
||||
if (recipients.isEmpty()) {
|
||||
throw new IllegalArgumentException('No recipients found on the Client Case record. '
|
||||
+ 'Please ensure Service Coordinator and Docusign Recipient #1 are populated.');
|
||||
}
|
||||
|
||||
return recipients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Builds a dfsle.Recipient from a Contact/User lookup ID
|
||||
* @param recipientId The Contact or User record ID
|
||||
* @param roleName The Docusign template role name
|
||||
* @param routingOrder Signing order
|
||||
* @param sourceRecordId The source Client_Case__c record ID
|
||||
* @return dfsle.Recipient configured for the role
|
||||
*/
|
||||
private static dfsle.Recipient buildRecipient(Id recipientId, String roleName, Integer routingOrder, String sourceRecordId) {
|
||||
// Determine if this is a Contact or User
|
||||
String objectType = recipientId.getSObjectType().getDescribe().getName();
|
||||
|
||||
String recipientName;
|
||||
String recipientEmail;
|
||||
|
||||
if (objectType == 'Contact') {
|
||||
Contact c = [SELECT Id, Name, Email FROM Contact WHERE Id = :recipientId LIMIT 1];
|
||||
recipientName = c.Name;
|
||||
recipientEmail = c.Email;
|
||||
} else if (objectType == 'User') {
|
||||
User u = [SELECT Id, Name, Email FROM User WHERE Id = :recipientId LIMIT 1];
|
||||
recipientName = u.Name;
|
||||
recipientEmail = u.Email;
|
||||
} else {
|
||||
throw new IllegalArgumentException('Unsupported recipient type: ' + objectType
|
||||
+ '. Expected Contact or User.');
|
||||
}
|
||||
|
||||
if (String.isBlank(recipientEmail)) {
|
||||
throw new IllegalArgumentException('No email found for ' + roleName + ' (' + recipientName + '). '
|
||||
+ 'Please ensure the recipient has a valid email address.');
|
||||
}
|
||||
|
||||
return dfsle.Recipient.fromSource(
|
||||
recipientName,
|
||||
recipientEmail,
|
||||
null, // phone (optional)
|
||||
roleName, // must match template role exactly
|
||||
new dfsle.Entity(sourceRecordId) // source record for merge fields
|
||||
);
|
||||
}
|
||||
|
||||
private static void logResult(Integer templateCount, String envelopeId, String status, String errorMessage) {
|
||||
System.debug(LoggingLevel.INFO, '=== Docusign Composite Envelope ===');
|
||||
System.debug(LoggingLevel.INFO, 'Templates: ' + templateCount);
|
||||
|
|
|
|||
Loading…
Reference in New Issue