/** * @description Main invocable class for combining multiple Docusign templates into a single envelope * @author Paul Huliganga * @date 2026-02-23 */ global with sharing class DocusignCompositeEnvelopeBuilder { /** * @description Invocable method called from Salesforce Screen Flow * @param requests List of request objects containing template IDs and metadata * @return List of result objects with envelope ID and status */ @InvocableMethod( label='Send Composite Docusign Envelope' description='Combines multiple Docusign templates into a single envelope' category='Docusign' ) public static List sendCompositeEnvelope(List requests) { List results = new List(); // 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(); try { // Validate request using handler DocusignEnvelopeRequestHandler.validateRequest(req); // Build envelope JSON using handler String envelopeJSON = DocusignEnvelopeRequestHandler.buildEnvelopeJSON(req); // Get Docusign credentials DocusignCredentials creds = DocusignCredentials.getInstance(); // Call Docusign API String envelopeId = DocusignAPIService.createCompositeEnvelope( envelopeJSON, creds ); // Success result.envelopeId = envelopeId; result.success = true; result.errorMessage = null; // Log success logAPICall(req.templateIds.size(), envelopeId, 'Success', null); } catch (Exception e) { // Error handling result.success = false; result.errorMessage = e.getMessage(); result.envelopeId = null; // Log error logAPICall( req.templateIds != null ? req.templateIds.size() : 0, null, 'Error', e.getMessage() + '\n' + e.getStackTraceString() ); // Re-throw if critical (governor limits) if (e instanceof System.LimitException) { throw e; } } results.add(result); return results; } /** * @description Logs API call to debug log (future: custom object) * @param templateCount Number of templates in envelope * @param envelopeId Docusign envelope ID * @param status Success or Error * @param errorMessage Error message if applicable */ private static void logAPICall( Integer templateCount, String envelopeId, String status, String errorMessage ) { System.debug(LoggingLevel.INFO, '=== Docusign Composite Envelope API Call ==='); System.debug(LoggingLevel.INFO, 'Timestamp: ' + System.now()); System.debug(LoggingLevel.INFO, 'Template Count: ' + templateCount); System.debug(LoggingLevel.INFO, 'Envelope ID: ' + envelopeId); System.debug(LoggingLevel.INFO, 'Status: ' + status); if (String.isNotBlank(errorMessage)) { System.debug(LoggingLevel.ERROR, 'Error: ' + errorMessage); } // Future enhancement: Insert into Docusign_API_Log__c custom object } /** * @description Helper to build error result * @param errorMessage Error message * @return List containing single error result */ private static List buildErrorResult(String errorMessage) { Result result = new Result(); result.success = false; result.errorMessage = errorMessage; result.envelopeId = null; return new List{ 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 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; } }