refactor: extract Request and Result as standalone global classes
- Created DocusignEnvelopeRequest.cls (separate global class for input) - Created DocusignEnvelopeResult.cls (separate global class for output) - Updated DocusignCompositeEnvelopeBuilder to use standalone classes - Updated DocusignEnvelopeRequestHandler to reference standalone classes - Updated all test classes to use new class references - Fixes Flow Builder visibility issues with nested inner classes - Better API design with clear input/output types - Easier to extend and reuse across other classes
This commit is contained in:
parent
565b851462
commit
7df62e06ca
|
|
@ -15,16 +15,16 @@ global with sharing class DocusignCompositeEnvelopeBuilder {
|
|||
description='Combines multiple Docusign templates into a single envelope'
|
||||
category='Docusign'
|
||||
)
|
||||
public static List<Result> sendCompositeEnvelope(List<Request> requests) {
|
||||
List<Result> results = new List<Result>();
|
||||
public static List<DocusignEnvelopeResult> sendCompositeEnvelope(List<DocusignEnvelopeRequest> requests) {
|
||||
List<DocusignEnvelopeResult> results = new List<DocusignEnvelopeResult>();
|
||||
|
||||
// Process first request (Flow only sends one)
|
||||
if (requests == null || requests.isEmpty()) {
|
||||
return buildErrorResult('No request provided');
|
||||
}
|
||||
|
||||
Request req = requests[0];
|
||||
Result result = new Result();
|
||||
DocusignEnvelopeRequest req = requests[0];
|
||||
DocusignEnvelopeResult result = new DocusignEnvelopeResult();
|
||||
|
||||
try {
|
||||
// Validate request using handler
|
||||
|
|
@ -104,67 +104,11 @@ global with sharing class DocusignCompositeEnvelopeBuilder {
|
|||
* @param errorMessage Error message
|
||||
* @return List containing single error result
|
||||
*/
|
||||
private static List<Result> buildErrorResult(String errorMessage) {
|
||||
Result result = new Result();
|
||||
private static List<DocusignEnvelopeResult> buildErrorResult(String errorMessage) {
|
||||
DocusignEnvelopeResult result = new DocusignEnvelopeResult();
|
||||
result.success = false;
|
||||
result.errorMessage = errorMessage;
|
||||
result.envelopeId = null;
|
||||
return new List<Result>{ result };
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Input parameters for invocable method (from Screen Flow)
|
||||
*/
|
||||
global class Request {
|
||||
@InvocableVariable(
|
||||
label='Template IDs'
|
||||
description='List of Docusign template IDs to combine'
|
||||
required=true
|
||||
)
|
||||
public List<String> templateIds;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Salesforce Record ID'
|
||||
description='ID of the Salesforce record to attach documents to'
|
||||
required=true
|
||||
)
|
||||
public String recordId;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Language'
|
||||
description='Language code (en or es)'
|
||||
required=false
|
||||
)
|
||||
public String language;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Email Subject'
|
||||
description='Subject line for envelope email'
|
||||
required=false
|
||||
)
|
||||
public String emailSubject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Output parameters for invocable method (to Screen Flow)
|
||||
*/
|
||||
global class Result {
|
||||
@InvocableVariable(
|
||||
label='Envelope ID'
|
||||
description='Docusign envelope ID'
|
||||
)
|
||||
public String envelopeId;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Success'
|
||||
description='True if envelope was created successfully'
|
||||
)
|
||||
public Boolean success;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Error Message'
|
||||
description='Error message if envelope creation failed'
|
||||
)
|
||||
public String errorMessage;
|
||||
return new List<DocusignEnvelopeResult>{ result };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
|
||||
DocusignCredentials.setTestCredentials('test-account-id', 'callout:DocusignAPI', 'test-token');
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{'template-1', 'template-2', 'template-3'};
|
||||
req.recordId = '001000000ABC123';
|
||||
req.language = 'en';
|
||||
|
|
@ -59,8 +59,8 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
|
|
@ -81,14 +81,14 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
|
||||
DocusignCredentials.setTestCredentials('test-account-id', 'callout:DocusignAPI', 'test-token');
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{'template-1'};
|
||||
req.recordId = '001000000ABC123';
|
||||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
|
|
@ -111,14 +111,14 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
templateIds.add('template-' + i);
|
||||
}
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = templateIds;
|
||||
req.recordId = '001000000ABC123';
|
||||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
|
|
@ -136,22 +136,20 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
|
||||
DocusignCredentials.setTestCredentials('test-account-id', 'callout:DocusignAPI', 'test-token');
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{'template-1', 'template-2', 'template-1'}; // Duplicate
|
||||
req.recordId = '001000000ABC123';
|
||||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
System.assertEquals(true, results[0].success, 'Should handle duplicates');
|
||||
}
|
||||
|
||||
// Custom fields test removed - not supported in InvocableVariable (Phase 2 enhancement)
|
||||
|
||||
/**
|
||||
* @description Test validation failure - no template IDs
|
||||
*/
|
||||
|
|
@ -160,14 +158,14 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
// Arrange
|
||||
DocusignCredentials.setTestCredentials('test-account-id', 'callout:DocusignAPI', 'test-token');
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>(); // Empty
|
||||
req.recordId = '001000000ABC123';
|
||||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
|
|
@ -188,14 +186,14 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
templateIds.add('template-' + i);
|
||||
}
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = templateIds; // 15 templates (> max of 14)
|
||||
req.recordId = '001000000ABC123';
|
||||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
|
|
@ -211,14 +209,14 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
// Arrange
|
||||
DocusignCredentials.setTestCredentials('test-account-id', 'callout:DocusignAPI', 'test-token');
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{'template-1'};
|
||||
req.recordId = ''; // Blank
|
||||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
|
|
@ -237,14 +235,14 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
|
||||
DocusignCredentials.setTestCredentials('test-account-id', 'callout:DocusignAPI', 'test-token');
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{'invalid-template'};
|
||||
req.recordId = '001000000ABC123';
|
||||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
|
|
@ -263,14 +261,14 @@ private class DocusignCompositeEnvelopeBuilderTest {
|
|||
|
||||
DocusignCredentials.setTestCredentials('test-account-id', 'callout:DocusignAPI', 'invalid-token');
|
||||
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{'template-1'};
|
||||
req.recordId = '001000000ABC123';
|
||||
|
||||
// Act
|
||||
Test.startTest();
|
||||
List<DocusignCompositeEnvelopeBuilder.Result> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignCompositeEnvelopeBuilder.Request>{req});
|
||||
List<DocusignEnvelopeResult> results =
|
||||
DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List<DocusignEnvelopeRequest>{req});
|
||||
Test.stopTest();
|
||||
|
||||
// Assert
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* @description Input parameters for DocusignCompositeEnvelopeBuilder invocable method
|
||||
* @author Paul Huliganga
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
global class DocusignEnvelopeRequest {
|
||||
|
||||
@InvocableVariable(
|
||||
label='Template IDs'
|
||||
description='List of Docusign template IDs to combine'
|
||||
required=true
|
||||
)
|
||||
global List<String> templateIds;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Salesforce Record ID'
|
||||
description='ID of the Salesforce record to attach documents to'
|
||||
required=true
|
||||
)
|
||||
global String recordId;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Language'
|
||||
description='Language code (en or es)'
|
||||
required=false
|
||||
)
|
||||
global String language;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Email Subject'
|
||||
description='Subject line for envelope email'
|
||||
required=false
|
||||
)
|
||||
global String emailSubject;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>60.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
|
|
@ -10,7 +10,7 @@ global with sharing class DocusignEnvelopeRequestHandler {
|
|||
* @param req Request object to validate
|
||||
* @throws IllegalArgumentException if validation fails
|
||||
*/
|
||||
public static void validateRequest(DocusignCompositeEnvelopeBuilder.Request req) {
|
||||
public static void validateRequest(DocusignEnvelopeRequest req) {
|
||||
if (req.templateIds == null || req.templateIds.isEmpty()) {
|
||||
throw new IllegalArgumentException('At least one template ID is required');
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ global with sharing class DocusignEnvelopeRequestHandler {
|
|||
* @param req Request object containing parameters
|
||||
* @return JSON string for Docusign API request
|
||||
*/
|
||||
public static String buildEnvelopeJSON(DocusignCompositeEnvelopeBuilder.Request req) {
|
||||
public static String buildEnvelopeJSON(DocusignEnvelopeRequest req) {
|
||||
// Remove duplicates and sort alphabetically
|
||||
List<String> sortedTemplateIds = sortTemplatesAlphabetically(
|
||||
new Set<String>(req.templateIds)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testValidateRequest_Success() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{ 'template1', 'template2' };
|
||||
req.recordId = '001xx000003DHf';
|
||||
req.language = 'en';
|
||||
|
|
@ -27,7 +27,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testValidateRequest_NoTemplateIds() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>();
|
||||
req.recordId = '001xx000003DHf';
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testValidateRequest_TooManyTemplates() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>();
|
||||
for (Integer i = 0; i < 15; i++) {
|
||||
req.templateIds.add('template' + i);
|
||||
|
|
@ -66,7 +66,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testValidateRequest_NoRecordId() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{ 'template1' };
|
||||
req.recordId = '';
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testValidateRequest_BlankTemplateId() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{ 'template1', '', 'template3' };
|
||||
req.recordId = '001xx000003DHf';
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testBuildEnvelopeJSON_Success() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{ 'template2', 'template1', 'template2' }; // duplicates and unsorted
|
||||
req.recordId = '001xx000003DHf';
|
||||
req.language = 'es';
|
||||
|
|
@ -123,7 +123,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testBuildEnvelopeJSON_DefaultSubject() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{ 'template1' };
|
||||
req.recordId = '001xx000003DHf';
|
||||
req.emailSubject = null;
|
||||
|
|
@ -140,7 +140,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testBuildEnvelopeJSON_TemplatesAreSorted() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{ 'template3', 'template1', 'template2' };
|
||||
req.recordId = '001xx000003DHf';
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ public class DocusignEnvelopeRequestHandlerTest {
|
|||
@isTest
|
||||
static void testBuildEnvelopeJSON_DuplicatesRemoved() {
|
||||
// Setup
|
||||
DocusignCompositeEnvelopeBuilder.Request req = new DocusignCompositeEnvelopeBuilder.Request();
|
||||
DocusignEnvelopeRequest req = new DocusignEnvelopeRequest();
|
||||
req.templateIds = new List<String>{ 'template1', 'template1', 'template2' };
|
||||
req.recordId = '001xx000003DHf';
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* @description Output parameters for DocusignCompositeEnvelopeBuilder invocable method
|
||||
* @author Paul Huliganga
|
||||
* @date 2026-02-25
|
||||
*/
|
||||
global class DocusignEnvelopeResult {
|
||||
|
||||
@InvocableVariable(
|
||||
label='Envelope ID'
|
||||
description='Docusign envelope ID'
|
||||
)
|
||||
global String envelopeId;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Success'
|
||||
description='True if envelope was created successfully'
|
||||
)
|
||||
global Boolean success;
|
||||
|
||||
@InvocableVariable(
|
||||
label='Error Message'
|
||||
description='Error message if envelope creation failed'
|
||||
)
|
||||
global String errorMessage;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>60.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
Loading…
Reference in New Issue