From 12869257650870b99ead7d1622f4e77e65cc428a Mon Sep 17 00:00:00 2001 From: Paul Huliganga Date: Fri, 3 Apr 2026 11:46:24 -0400 Subject: [PATCH] docs: update QUICK_START, deployment, and design documentation --- composite-envelope-builder/QUICK_START.md | 46 +-- .../docs/DEPLOYMENT_AND_TESTING.md | 11 +- .../docs/deployment-guide.md | 14 +- composite-envelope-builder/docs/design.md | 383 ++++++++++-------- 4 files changed, 239 insertions(+), 215 deletions(-) diff --git a/composite-envelope-builder/QUICK_START.md b/composite-envelope-builder/QUICK_START.md index 4a4029f..c9eeac4 100644 --- a/composite-envelope-builder/QUICK_START.md +++ b/composite-envelope-builder/QUICK_START.md @@ -4,23 +4,22 @@ All Apex classes and tests have been created! Here's what you have: -### πŸ“¦ Code Files Created (6 classes) +### πŸ“¦ Code Files Included in This Package **Main Classes:** -1. `DocusignCompositeEnvelopeBuilder.cls` (11.5 KB) - Invocable method for Flow integration -2. `DocusignAPIService.cls` (10.5 KB) - REST API service layer -3. `DocusignCredentials.cls` (5.9 KB) - Credential management +1. `DocusignCompositeEnvelopeBuilder.cls` - Invocable method for Flow integration (uses dfsle toolkit) +2. `DocusignEnvelopeRequest.cls` - Invocable request parameter object +3. `DocusignEnvelopeRequestHandler.cls` - Request validation helper +4. `DocusignEnvelopeResult.cls` - Invocable result object **Test Classes:** -4. `DocusignCompositeEnvelopeBuilderTest.cls` (13.8 KB) - 12 test methods -5. `DocusignAPIServiceTest.cls` (11.7 KB) - 14 test methods -6. `DocusignCredentialsTest.cls` (8.0 KB) - 13 test methods + - `DocusignCompositeEnvelopeBuilderTest.cls` + - `DocusignEnvelopeRequestHandlerTest.cls` -**Total:** 39 test methods for comprehensive coverage! +**Notes on legacy artifacts:** +- The repository contains a legacy `Docusign_Configuration__c` custom object and older REST-helper classes in docs, but the active implementation uses the `dfsle` (DocuSign for Salesforce managed package) toolkit and `dfsle__EnvelopeConfiguration__c` records. The legacy custom setting/object is not required for the current Flow + Apex approach. -**Metadata:** -- Custom Setting: `Docusign_Configuration__c` with `Account_Id__c` and `Base_URL__c` fields -- All `.cls-meta.xml` files (API version 61.0) +**All `.cls-meta.xml` files** use API version 60/61 as shown in each file. --- @@ -99,25 +98,18 @@ Pass Rate: 100% Code Coverage: 85%+ ``` -### Step 7: Configure Docusign Credentials +### Step 7: DocuSign Integration / Credentials (note) -1. **Create Named Credential** (see docs/deployment-guide.md section 3.1) - - Setup β†’ Named Credentials β†’ New Named Credential - - Name: `DocusignAPI` - - URL: `https://na3.docusign.net/restapi/v2.1` (or your data center) +- The current implementation uses the `dfsle` Apex Toolkit from the DocuSign for Salesforce managed package to send composite envelopes. That toolkit stores and references its templates/configuration using managed-package objects such as `dfsle__EnvelopeConfiguration__c`. -2. **Configure Custom Settings** - - Setup β†’ Custom Settings β†’ Docusign Configuration β†’ Manage - - Click "New" (organization-wide default) - - Account Id: `{Your Docusign Account GUID}` - - Base URL: `callout:DocusignAPI` - - Save +- You do NOT need to create the legacy Named Credential / custom setting (`Docusign_Configuration__c`) for the dfsle-based flow. Ensure the `DocuSign for Salesforce (dfsle)` managed package is installed and its envelope configurations/templates exist in Production. -3. **Add Remote Site Settings** - - Setup β†’ Remote Site Settings β†’ New Remote Site - - Name: `Docusign_API` - - URL: `https://na3.docusign.net` - - Active: βœ“ +- If you intentionally plan to use the older REST-based helper classes (legacy), then follow the steps below **only**: + 1. Create a Named Credential (Setup β†’ Named Credentials β†’ New) + - Example name: `DocusignAPI` + - Example URL: `https://na3.docusign.net/restapi/v2.1` + 2. (Optional legacy) Configure `Docusign_Configuration__c` custom setting/object with `Account_Id__c` and `Base_URL__c` if your older REST helpers require it. + 3. Add Remote Site or appropriate callout permissions for external DocuSign endpoints. ### Step 8: Update Screen Flow diff --git a/composite-envelope-builder/docs/DEPLOYMENT_AND_TESTING.md b/composite-envelope-builder/docs/DEPLOYMENT_AND_TESTING.md index feae5c7..f3218b6 100644 --- a/composite-envelope-builder/docs/DEPLOYMENT_AND_TESTING.md +++ b/composite-envelope-builder/docs/DEPLOYMENT_AND_TESTING.md @@ -132,11 +132,12 @@ sf apex run test --class-names DocusignCompositeEnvelopeBuilderTest --wait 10 -- # Test the request handler sf apex run test --class-names DocusignEnvelopeRequestHandlerTest --wait 10 --result-format human --code-coverage --target-org dev-org -# Test the API service -sf apex run test --class-names DocusignAPIServiceTest --wait 10 --result-format human --code-coverage --target-org dev-org - -# Test the credentials helper -sf apex run test --class-names DocusignCredentialsTest --wait 10 --result-format human --code-coverage --target-org dev-org +# Legacy REST-helper tests (optional) +# The REST-based `DocusignAPIService` and `DocusignCredentials` tests are part of a +# legacy implementation and are not required for the current dfsle-based Flow. +# Run these only if you have intentionally included the older REST helper classes in your package: +# sf apex run test --class-names DocusignAPIServiceTest --wait 10 --result-format human --code-coverage --target-org dev-org +# sf apex run test --class-names DocusignCredentialsTest --wait 10 --result-format human --code-coverage --target-org dev-org ``` PowerShell: diff --git a/composite-envelope-builder/docs/deployment-guide.md b/composite-envelope-builder/docs/deployment-guide.md index c1d0235..50b51a7 100644 --- a/composite-envelope-builder/docs/deployment-guide.md +++ b/composite-envelope-builder/docs/deployment-guide.md @@ -211,12 +211,14 @@ sf project deploy start --target-org my-sandbox Deploying v60.0 metadata to my-sandbox using the v60.0 SOAP API Status: Succeeded Component Deployed: - ApexClass DocusignCompositeEnvelopeBuilder - ApexClass DocusignAPIService - ApexClass DocusignCredentials - ApexClass DocusignCompositeEnvelopeBuilderTest - ApexClass DocusignAPIServiceTest - ApexClass DocusignCredentialsTest + ApexClass DocusignCompositeEnvelopeBuilder + ApexClass DocusignEnvelopeRequest + ApexClass DocusignEnvelopeRequestHandler + ApexClass DocusignEnvelopeResult + ApexClass DocusignCompositeEnvelopeBuilderTest + ApexClass DocusignEnvelopeRequestHandlerTest + +Note: The older `DocusignAPIService` / `DocusignCredentials` classes and their tests are part of a legacy REST-based implementation. The active implementation uses the `dfsle` toolkit and does not require those classes; include them only if you intentionally retain the legacy REST helpers. ``` ### 4.4 Run Unit Tests diff --git a/composite-envelope-builder/docs/design.md b/composite-envelope-builder/docs/design.md index b985425..1ed17ee 100644 --- a/composite-envelope-builder/docs/design.md +++ b/composite-envelope-builder/docs/design.md @@ -1,203 +1,232 @@ -# Design Document +# Design β€” Composite Envelope Builder (Updated) -**Project**: Salesforce Composite Envelope Builder -**Version**: 1.2 -**Date**: February 23, 2026 (updated March 15, 2026) -**Author**: Paul Huliganga +**Project**: Salesforce Composite Envelope Builder +**Version**: 2.0 +**Date**: 2026-03-25 +**Author**: (auto-generated; update author/owner as needed) --- -## 1. Architecture Overview +## 1. Summary -### 1.1 System Context +This document describes the current implementation of the Composite Envelope Builder: how Screen Flows, Apex, and the dfsle toolkit collaborate to build and send a single DocuSign envelope composed from multiple DocuSign templates. It reflects the latest code and metadata in the repository (March 2026), including: -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Salesforce User β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Salesforce Platform β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Screen Flow │───▢│ Apex Class β”‚ β”‚ -β”‚ β”‚ (Template β”‚ β”‚ (Composite β”‚ β”‚ -β”‚ β”‚ Selection) β”‚ β”‚ Builder) β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό HTTPS/REST API - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Docusign REST API β”‚ - β”‚ (Composite β”‚ - β”‚ Templates) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` +- Flow V3 (existing, email-only path) and Flow V4 (new, SMS collection path when recipient email is blank) +- Apex invocable: `DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope` and supporting classes +- SMS delivery support for recipients without an email (via `dfsle.Recipient.withSmsDelivery()`) +- Multi-copy support for the "Authorization to Release Information" template (up to 5 copies) +- Email subject & body composition rules: prefix `Docusign: `, truncation, greeting/signoff handling and Spanish detection +- Key constants: `SMS_PLACEHOLDER_EMAIL`, `MULTI_COPY_TEMPLATE_NAME` -### 1.2 Component Architecture +This is the canonical design doc for developers, release engineers, and reviewers. -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Salesforce Org β”‚ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Presentation Layer (Screen Flow) β”‚ β”‚ -β”‚ β”‚ - Language selection β”‚ β”‚ -β”‚ β”‚ - Template display (checkbox collection) β”‚ β”‚ -β”‚ β”‚ - Success/error messaging β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Business Logic Layer (Apex) β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ - β”‚ β”‚ β”‚ DocusignCompositeEnvelopeBuilder β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - @InvocableMethod entry point β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - Input validation β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - Multi-copy template expansion β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - SMS delivery (withSmsDelivery) β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - Composite JSON construction β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - Envelope ID return β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ DocusignAPIService β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - API authentication β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - HTTP callout construction β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - Response parsing β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - Error handling β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ DocusignCredentials β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - Credential retrieval β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ - Token management β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Data Layer β”‚ β”‚ -β”‚ β”‚ - Named Credential (Docusign API creds) β”‚ β”‚ -β”‚ β”‚ - Custom Settings (configuration) β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό HTTPS REST API - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Docusign Platform β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +--- + +## 2. Architecture Overview + +High-level flow: + +- User launches Screen Flow (Flow V3 or V4) +- User selects language (English/Spanish) and templates +- Flow optionally collects SMS phone when recipient email is blank (V4) +- Flow invokes Apex action `Send Composite Docusign Envelope` with inputs +- Apex builds compound envelope JSON using selected templates (expands multi-copy templates as configured) +- Apex uses dfsle toolkit to send envelope; returns envelopeId and success/error + +Components: + +- Screen Flows: `Docusign_Envelope_Templates_V3` (email path), `Docusign_Envelope_Templates_V4` (collect SMS phone when needed) +- Apex: + - `DocusignCompositeEnvelopeBuilder.cls` (invocable entrypoint + implementation) + - `DocusignEnvelopeRequest.cls` (invocable request contract) + - `DocusignEnvelopeResult.cls` (invocable result contract) + - `DocusignAPIService.cls`, `DocusignCredentials.cls` (service & credential management) +- DocuSign: Composite Templates API (via dfsle toolkit integration) + +--- + +## 3. Flow Behavior (V3 and V4) + +### 3.1 Shared behavior (V3 & V4) + +- Language selection screen: user selects `English` or `Spanish`. +- Template selection screen: multi-select list of templates filtered by selected language. +- After selection, a loop scans selected templates to detect the multi-copy template ("Authorization to Release Information"). +- If detected, a copies screen appears (radio 1–5) that sets `authReleaseFormCopies`. +- Flow gathers `compositeTemplateIds` (selected template IDs) and passes them to Apex action. + +### 3.2 Flow V3 + +- Used when standard email delivery is expected. +- No SMS collection screen is present. +- Behavior is unchanged from previous releases except choices include 1–5 copies. + +### 3.3 Flow V4 (SMS-aware) + +- Added pre-send recipient lookup path: + - `Get_Records` (Client_Case__c) β†’ `Get_Recipient_Contact` (Contact lookup) + - `Is_Recipient_Email_Blank` decision checks Contact.Email + - If email is blank β†’ `SMS_Phone_Screen` (field `smsPhoneInput` required, E.164 format recommended) β†’ `Store_SMS_Phone` assignment assigns to `recipientSmsPhone` variable β†’ continue + - If email present β†’ skip SMS_Phone_Screen and continue +- The `recipientSmsPhone` variable is passed into the Apex action; when non-blank the Apex sets up SMS delivery for Docusign Recipient #1. +- Flow element names to reference in code and docs: `SMS_Phone_Screen`, `smsPhoneInput`, `Store_SMS_Phone`, `recipientSmsPhone`. + +Note: Flow metadata must keep element blocks contiguous (assignments, decisions, screens, etc.) to avoid deployment errors. The committed `Docusign_Envelope_Templates_V4.flow-meta.xml` already follows these rules. + +--- + +## 4. Apex Implementation Details + +### 4.1 Invocable contract (`DocusignEnvelopeRequest`) + +Key input fields (invocable variables): +- `List templateIds` (required) β€” list of selected DocuSign template IDs +- `String recordId` (required) β€” Salesforce Client Case Id +- `String language` (optional) β€” e.g., `en`, `es`, `Spanish`, `EspaΓ±ol` (language detection is normalized in Apex) +- `String emailSubject` (optional) β€” optional override; Apex still prefixes with `Docusign: ` and truncates to 100 chars +- `Integer authReleaseFormCopies` (optional) β€” 1–5; counts for Authorization template +- `String recipientSmsPhone` (optional) β€” when provided, Apex will enable SMS delivery for Docusign Recipient #1 + +Outputs: +- `String envelopeId` +- `Boolean success` +- `String errorMessage` + +### 4.2 Main behavior (`DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope`) + +1. Validate inputs; throw friendly errors if invalid. +2. Expand multi-copy templates: + - Find template IDs whose `Name` contains the constant `MULTI_COPY_TEMPLATE_NAME`. + - If `authReleaseFormCopies` > 1, append (copies - 1) additional entries for each matched template ID. + - Cap copies to 5 (Math.min(..., 5)). +3. Build document list (documents = fromTemplate(templateId, label)) and label duplicates as ` (Copy N)` to preserve uniqueness. +4. Build deduplicated display names for subject/body (merge repeated templates into count markers like `X (3)`). +5. Compose envelope subject & body (see section 5 for rules). +6. Resolve recipients via `resolveRecipients(recordId, recipientSmsPhone)`: + - Query Client_Case__c for lookup fields + - For Docusign Recipient #1: if linked Contact has no Email and `recipientSmsPhone` is provided, set recipientEmail to `SMS_PLACEHOLDER_EMAIL` and call `recipient.withSmsDelivery(smsPhone)`. +7. Use dfsle toolkit to build envelope with documents and recipients and call send. +8. Return `envelopeId` and `success`. + +### 4.3 Important constants + +- `SMS_PLACEHOLDER_EMAIL` (defined in `DocusignCompositeEnvelopeBuilder.cls`): placeholder email used when recipient has no email; required by DocuSign API even for SMS deliveries. +- `MULTI_COPY_TEMPLATE_NAME` (defined in same class): base name used to identify the Authorization to Release Information template (covers English + Spanish variations via LIKE). + +### 4.4 i18n detection + +- The code normalizes `req.language` to lowercase and treats as Spanish if any of the following are true: + - `lang.startsWith('es')` (e.g. `es`, `es-CO`) + - `lang.contains('spanish')` + - `lang.contains('espa')` (to capture `espaΓ±ol` / `espanol`) +- On Spanish detection, Apex uses Spanish greeting/signoff; otherwise English is used. + +--- + +## 5. Email Subject & Body Composition Rules + +- Subject: + - Prefix: `Docusign: ` is prepended to the subject to make the source explicit. + - Truncation: After prefixing, subject is truncated to a maximum of 100 characters (Docusign requirement). The code uses `left(97) + '...'` if longer. + - If user supplies `emailSubject`, prefix and truncation still apply. + +- Body: + - Built as: GREETING + (template bodies joined by DIVIDER) + SIGNOFF + - DIVIDER: `"\n\n" + '─'.repeat(40) + "\n\n"` (visual separator) + - Greeting/Sign-off: English default; Spanish strings used when language detection matches Spanish variants. Examples: + - English greeting: `Hello,\n\nPlease complete the DocuSign signature request from Early Intervention Colorado.\n\n` + - Spanish greeting: `Hola,\n\nPor favor, firme la solicitud de DocuSign de parte de IntervenciΓ³n Temprana Colorado.\n\n` + +--- + +## 6. Multi-copy Behavior + +- Single constant drives detection: `MULTI_COPY_TEMPLATE_NAME = 'Authorization to Release Information'`. +- Flow shows a copies screen when the template is present; operator selects 1–5 copies. +- Apex expands the templateId list before building documents to include multiple entries; duplicates are intentionally kept so each copy becomes a separate document in the envelope. +- Document labels: duplicates are labeled with ` (Copy N)` so they appear distinct in DocuSign Status. + +--- + +## 7. SMS Delivery Details + +- Trigger: Flow V4 routes to `SMS_Phone_Screen` if the Contact linked by `Docusign_Recipient_1__c` has empty `Email`. +- The screen collects `smsPhoneInput` which is assigned to `recipientSmsPhone` variable and passed to Apex. +- In Apex, when `recipientSmsPhone` is non-blank for Docusign Recipient #1: + - If recipient record has no email, set `recipientEmail = SMS_PLACEHOLDER_EMAIL`. + - Call `recipient = recipient.withSmsDelivery(smsPhone)` to enable SMS delivery via dfsle toolkit. +- Service Coordinator recipient always uses email delivery (unchanged). +- Important setup requirement (documented): `Docusign_Recipient_1__c` on the Client Case must be populated with a Contact. The Contact must have `Name` and (for SMS flow) may have blank `Email`. If the Contact is null, the recipient will be omitted and envelope will be missing that signer. + +--- + +## 8. Flows & Metadata Notes + +- Flow element naming conventions are important (screen fields bind by their `name`). For the SMS flow, the screen field is `smsPhoneInput` and the assignment must use `smsPhoneInput` (not `ScreenName.smsPhoneInput`). +- Flow metadata must keep element blocks contiguous (screens, assignments, recordLookups, decisions, loops, choices) to avoid Salesforce Flow XML validation failures. The repo's V4 flow file was normalized accordingly. + +--- + +## 9. Tests, Validation & CI + +- Unit tests: ensure `DocusignCompositeEnvelopeBuilderTest` covers: + - English and Spanish subject/body composition + - Multi-copy expansion with 1–5 copies + - SMS flow path: when Contact.Email blank + recipientSmsPhone provided, mailbox placeholder used and `withSmsDelivery` applied + - Error branches and API failures +- CI: add a PR validation job that does: + - sfdx auth to a validation org + - For changed flow or Apex files, run `sfdx force:source:deploy --checkonly` for those components + - Fail PR if check-only returns errors +- Pre-deploy: run check-only deploy to target org before actual deploy. Example local command: + +```bash +sfdx force:source:deploy -p force-app/main/default/flows/Docusign_Envelope_Templates_V4.flow-meta.xml,force-app/main/default/classes/DocusignCompositeEnvelopeBuilder.cls -u dev-org --checkonly --testlevel NoTestRun ``` --- -## 2. Detailed Component Design +## 10. Edge Cases and Known Gotchas -### 2.1 DocusignCompositeEnvelopeBuilder (Main Class) - -**Purpose**: Invocable Apex class that combines multiple Docusign templates into a single envelope - -**Responsibilities**: -- Receive template IDs from Screen Flow -- Validate inputs -- Expand multi-copy templates (e.g. Authorization to Release Information) -- Construct composite template JSON -- Delegate API call to service class -- Return envelope ID to Flow - -**Methods**: - -```apex -// Flow-invocable entry point -@InvocableMethod( - label='Send Composite Docusign Envelope' - description='Combines multiple templates into one envelope' -) -public static List sendCompositeEnvelope(List requests) - -// Private helper methods -private static String buildCompositeEnvelopeJSON( - List templateIds, - String recordId, - String language, - Map customFields -) - -private static void validateInputs(Request req) - -private static List sortTemplatesAlphabetically(List templateIds) -``` - -**Inner Classes**: - -```apex -public class Request { - @InvocableVariable(required=true label='Template IDs') - public List templateIds; - - @InvocableVariable(required=true label='Salesforce Record ID') - public String recordId; - - @InvocableVariable(required=false label='Language') - public String language; // 'en' or 'es' - - @InvocableVariable(required=false label='Email Subject') - public String emailSubject; - - @InvocableVariable(required=false label='Authorization to Release Form Copies') - public Integer authReleaseFormCopies; // 1–5; only used when that template is selected - - @InvocableVariable(required=false label='Recipient SMS Phone') - public String recipientSmsPhone; // E.164 preferred (+15551234567); triggers SMS delivery for Docusign Recipient #1 - - @InvocableVariable(required=false label='Custom Fields') - public Map customFields; // For merge fields -} - -public class Result { - @InvocableVariable(label='Envelope ID') - public String envelopeId; - - @InvocableVariable(label='Success') - public Boolean success; - - @InvocableVariable(label='Error Message') - public String errorMessage; -} -``` +- If operator edits a flow in the org and does not retrieve+commit the changes, repo and org diverge. Use mdapi `retrieve` or `sf project retrieve` to pull the authoritative version and commit immediately. +- Flow Builder sometimes reorders or normalizes XML: prefer re-checking contiguity of element blocks after Flow Builder saves. +- Ensure the Flow variable `recipientSmsPhone` is passed to Apex action and that the assignment uses `smsPhoneInput` as elementReference. +- The DocuSign API requires an email field on every recipient even when SMS is used; `SMS_PLACEHOLDER_EMAIL` is central and must be kept updated in Apex if changed. --- -### 2.2 DocusignAPIService (Service Class) +## 11. Deployment Checklist -**Purpose**: Handles all Docusign REST API interactions +1. Confirm `force-app/main/default/flows/Docusign_Envelope_Templates_V4.flow-meta.xml` matches the active version in org (if you intend to deploy active draft) +2. Confirm `force-app/main/default/classes/DocusignCompositeEnvelopeBuilder.cls` and related classes/tests are committed +3. Run `sfdx force:source:deploy --checkonly` for affected components against a validation org +4. Run Apex tests (or allow CI to run tests during deploy) +5. Deploy to sandbox, perform a manual Flow Builder inspection of V4 +6. Activate the desired Flow version if runtime activation is needed -**Responsibilities**: -- Construct HTTP requests -- Make callouts to Docusign API -- Parse responses -- Handle errors and retries -- Log API interactions +--- -**Methods**: +## 12. Change Log (high level) -```apex -public static String createCompositeEnvelope( - String envelopeJSON, - DocusignCredentials creds -) +- 2.0 (2026-03-25): Updated design to reflect: + - Flow V4 (SMS path) retrieval & Active flow committed + - Spanish greeting/signoff and broadened language detection + - Envelope subject prefix `Docusign: ` and truncation to 100 chars + - Increased Authorization multi-copy support to 5 copies + - Flow element and metadata normalization -public static HttpResponse callDocusignAPI( - String endpoint, - String method, - String body, - Map headers -) +--- -public static String parseEnvelopeId(HttpResponse response) +## 13. Contact & Ownership + +- Primary developer: Paul Huliganga (update as appropriate) +- Repo: `composite-envelope-builder` +- For deployment questions: refer to `docs/DEPLOYMENT_AND_TESTING.md` + +--- + +*This document was generated to represent the repository state as of March 25, 2026. Update the change log and ownership fields when you make future changes.* -private static void logAPICall( - HttpRequest req, HttpResponse res, Long durationMs )