DocGen & eSign

Docgen & eSign Send Document For eSignature (Without Document Template) — Technical Architecture & Reference

Overview

A user selects an existing document (linked to a record) or uploads a new document, manually adds signers with their emails, configures signing settings (eOriginal vaulting, digital signature), and sends the document for eSignature without requiring a pre-created Document_Template__c. This is an ad-hoc signing flow — document + signers selected at runtime, Document_Workflow__c created on-the-fly with signer configuration embedded as JSON. No template mappings, no field merging — pure document transmission and signature collection. Useful for one-off signing requests, dynamic signer lists, or processes where template pre-configuration is not practical.


Component

Purpose

Context

sendDocumentForEsignature (LWC)

Document selection + signer management + settings configuration. Multi-step wizard.

Record action quick action

SendDocumentForEsigningController (Apex)

Retrieves linked files, creates workflow on-the-fly, manages signer queries, checks service entitlements.

Backend logic

PSPDFKit_InitPSPDFKit.page (VF)

Document preview/rendering via Nutrient Web SDK (no signing in this page — preview only).

Iframe modal for file preview


Architecture.

SQL
┌──────────────────────────────────────────────┐
│   User clicks "Send For eSignature"          │
│   (quick action on record)                   │
└────────────────────┬─────────────────────────┘
                     │
           ┌─────────▼──────────┐
           │ sendDocumentFor    │
           │ Esignature LWC     │
           │ (multi-step wizard)│
           └─────────┬──────────┘
                     │
        ┌────────────▼──────────────┐
        │  Step 1: Select Document  │
        │                           │
        │ • Query linked files      │
        │ • Display as table        │
        │ • Allow upload new file   │
        │ • User selects file       │
        └────────────┬──────────────┘
                     │
        ┌────────────▼──────────────┐
        │  Step 2: Add Recipients   │
        │                           │
        │ • User enters signer name │
        │ • User enters email       │
        │ • User clicks Add         │
        │ • System sets sequence    │
        │ • Optional: Query signers │
        │   from SOQL config        │
        └────────────┬──────────────┘
                     │
        ┌────────────▼──────────────┐
        │  Step 3: Signing Settings │
        │                           │
        │ • Select eOriginal?       │
        │ • Select Digital Sig?     │
        │ • Review signers (table)  │
        │ • Confirm send            │
        └────────────┬──────────────┘
                     │
        ┌────────────▼──────────────────────┐
        │ SendDocumentForEsigning           │
        │ Controller.createWorkFlow()       │
        │                                   │
        │ 1. Deserialize signers JSON       │
        │ 2. Create Document_Workflow__c    │
        │    (status: Workflow Initiated)   │
        │ 3. Store signer config as JSON    │
        │    in Signer_Configuration__c     │
        │ 4. Create ContentVersion (doc)    │
        │ 5. Update workflow with CV ID     │
        │ 6. Status: Document Generated     │
        └────────────┬─────────────────────┘
                     │
        ┌────────────▼──────────────┐
        │ Workflow Created          │
        │ Ready for Signing         │
        │                           │
        │ Send confirmation email   │
        │ to first signer           │
        └───────────────────────────┘


Key mechanism — ad-hoc document signing without template.

Unlike the Template Module (which pre-defines field mappings, signer lists via metadata), this flow is runtime-configured. User selects document, enters signers manually (or queries from SOQL config), sets signing method (eOriginal/Digital Signature), clicks Send. The LWC calls SendDocumentForEsigningController.createWorkFlow(), which:

  1. Deserializes signer list from LWC-submitted JSON

  2. Creates Document_Workflow__c record (no template link, no field mappings)

  3. Stores signer config as JSON in Signer_Configuration__c field (later used by signing flow)

  4. Creates ContentVersion record with document blob

  5. Sets workflow status → "Document Generated"

  6. Returns workflow ID for next steps (sending signing links)

Advantages:

  • No pre-template setup required

  • Dynamic signer lists

  • One-off ad-hoc signing

  • Flexible document selection

Tradeoff:

  • No field auto-population (all fields must be pre-filled in document)

  • No template validation

  • Signer SOQL queries optional (manual entry is primary path)


LWC — sendDocumentForEsignature

Multi-step wizard component. Triggered as quick action on record.

Tracked state

Property

Purpose

@track recordId

Injected by quick action framework

@track relatedFiles

Array of ContentVersion records linked to record (PDF, DOCX, DOC)

@track selectedRowFile

Selected file from table (ContentVersion ID)

@track signers

Array of signer objects: {name, email, sequence}

@track signer

Current signer being added (temp object)

@track screenConfig

Multi-step wizard config (step 1, 2, 3 details)

isStep1, isStep2, isStep3

Toggles which step displays

digitalSignatureEnabledForDocument

Boolean: user selected Digital Signature?

eOriginalEnabledForDocument

Boolean: user selected eOriginal vaulting?

digitalSignEnabled, eOriginalEnabled

Feature flags from org entitlements

showConfirmationModal

Confirmation dialog before sending

bUserAssignedLicense

Licensing gate

isLoading

Spinner during file fetch/creation

Key functions

Function

Behavior

connectedCallback()

Calls getRelatedFiles(recordId). Checks user license. Calls enabledServices() to populate digitalSignEnabled + eOriginalEnabled.

getRelatedFiles()

Apex call: queries ContentDocumentLink + ContentVersion WHERE AccountId = recordId. Filters PDF/DOCX/DOC, < 2.5MB, isLatest=true. Returns list for table display.

handleRowAction(event)

User clicks Preview button on file row. Opens PSPDFKit_InitPSPDFKit.page in modal with document. OR clicks Delete to remove file.

handleFileUpload(event)

User uploads new file. Saves to Files section of record. Refreshes relatedFiles list.

handleAddSigner()

User enters name + email, clicks Add. Validates email format. Increments sequence. Adds to signers array. Clears input fields.

handleDeleteSigner(event)

User clicks Delete on signer row. Removes from signers array. Re-sequences remaining signers.

handleProceedStep1()

Validates file selected. If yes: isStep1=false, isStep2=true (show step 2). If no: shows error toast.

handleProceedStep2()

Validates at least 1 signer added. If yes: isStep2=false, isStep3=true. If no: shows error.

handleSendDocument()

User clicks Send (step 3). Checks digitalSignature + eOriginal toggles. Calls createWorkFlow(base64 of file, signers JSON, recordId, fileName, documentAction).

createWorkFlow(blobBase64, signersJSON, recordId, fileName, documentAction)

Apex call. Receives response { isSuccess, workflowId, errorMessage }. On success: shows confirmation modal + redirect option. On error: shows error toast.

handleExecuteSignerQuery()

Optional: User clicks "Load from SOQL". Calls executeSignerQuery(recordId) → queries custom SOQL (from metadata) to fetch signers from record. Auto-populates signer table.

toggleDigitalSignature(), toggleEOriginal()

User clicks toggle for signing method. Updates digitalSignatureEnabledForDocument / eOriginalEnabledForDocument.

handleRowSelection(event)

User selects row in file table (radio button). Sets selectedRowFile = ContentVersion ID.

showPreviewModal(event)

Opens PSPDFKit VF page in modal iframe to preview selected document.

closePreviewModal()

Closes preview modal.

Child Components

Component

Usage

lightning-datatable

Step 2: Display signers table (name, email, sequence, delete action)

lightning-datatable

Step 1: Display related files (title, created date, preview button)

lightning-input

Signer name/email input fields

lightning-toggle-button

eOriginal + Digital Signature toggles (step 3)

lightning-modal

Preview modal (PSPDFKit VF page iframe)

lightning-modal

Confirmation modal (before send)


Apex — SendDocumentForEsigningController

public with sharing. Backend logic for ad-hoc signing.

Method

Returns

What it does

getRelatedFiles(Id parentId) @AuraEnabled(cacheable)

List<ContentVersion>

Queries ContentDocumentLink WHERE LinkedEntityId = parentId. Extracts ContentDocumentIds. Queries ContentVersion WHERE ContentDocumentId IN (...) AND FileExtension IN ('pdf','docx','doc') AND ContentSize < 2500000 AND IsLatest=true. Returns sorted by CreatedDate DESC.

createWorkFlow(String base64String, String signerInfo, String recordId, String fileName, String documentAction) @AuraEnabled

Map<String,Object>

Deserializes signerInfo JSON → List<SignerInstance>. Creates Document_Workflow__c: stores signerInfo JSON in Signer_Configuration__c, sets status=Workflow Initiated, sets Current_Signing_Count=1, Maximum_Signer=signerInfo.size(), sets Signing_Link_Expiry_Date=now()+30days. Creates ContentVersion with base64 blob, links to workflow. Updates workflow status → Document Generated. Returns { isSuccess: true, workflowId, errorMessage }.

enabledServices() @AuraEnabled(cacheable)

Map<String,Object>

Queries Features_Entitlement__c. Returns { eOriginal: boolean, digitalSign: boolean }. Used to show/hide toggles in LWC.

getsObjectConfigForSigner(String recordId) @AuraEnabled

Map<String,Object>

Gets record sObject type. Queries Docgen_Signer_Selection_Config__mdt metadata. Returns config JSON (contains SOQL query for fetching signers). Returns { bSuccess, sConfig, sObjectName, errorMessage }.

executeSignerQuery(String sQuery, String recordId) @AuraEnabled

sObject

Takes custom SOQL query (from metadata config). Executes with recordId binding. Returns first result (or null). Used to fetch signer details from parent record.

isSizeWithtinAllowedLimit(String contentDocId) @AuraEnabled

Boolean

Delegates to UtilityClass. Checks if document size < org limit (default 2.5MB).

Key Apex Class Structure

DocumentWrapperClass.SignerInstance

Java
public class SignerInstance {
    public String name;          // Signer name
    public String email;         // Signer email
    public Decimal sequence;     // Signing order (1, 2, 3...)
    public String signer_SOQL;   // Optional: SOQL query for fetching signer
}


VF Page — PSPDFKit_InitPSPDFKit.page

Controller: PSPDFKitController. Preview-only page (no signing, no field editing).

Feature

Implementation

Purpose

Display document via Nutrient Web SDK for preview before sending

Usage

Opened in modal iframe by sendDocumentForEsignature LWC

Toolbar

sidebar-annotations, sidebar-signatures, pager, zoom, text, signature, image, search, export-pdf, etc.

Base64 Input

Receives document blob as base64 via {!base64String} VF property

License Key

PSPDFKit license from org config

Readonly

Document displayed; user cannot save changes (preview mode)

VF Properties:

Property

Purpose

TemplateData

JSON with document metadata

base64String

Base64-encoded document blob

licensekey

PSPDFKit license key

vfURL

VF origin for postMessage validation

isMappingScreen

Boolean: is this a mapping screen or preview? (false for preview)


Data Flow — Send Document For eSignature (No Template)

  1. User on record detail page clicks "Send For eSignature" quick action.

  2. sendDocumentForEsignature LWC opens.

  3. connectedCallback() executes: queries user license, calls getRelatedFiles(), calls enabledServices().

  4. getRelatedFiles() Apex executed. Queries ContentDocumentLink for record. Retrieves linked files (PDF/DOCX/DOC, <2.5MB, latest version).

  5. LWC renders Step 1: Select Document with file table.

  6. User browses files, clicks Preview on one. Preview modal opens with PSPDFKit_InitPSPDFKit.page iframe.

  7. User clicks "Next" button (or closes preview and clicks Next).

  8. LWC validates file selected. If yes: renders Step 2: Add Recipients.

  9. User enters signer name + email. Clicks Add Signer.

  10. LWC validates email format. Adds to signers array. Displays in signer table with sequence.

  11. User repeats steps 9-10 to add more signers (optional).

  12. User clicks "Next" (or "Proceed to Settings").

  13. LWC validates at least 1 signer added. If yes: renders Step 3: Signing Settings.

  14. Step 3 shows: eOriginal toggle, Digital Signature toggle, review signers table, Send button.

  15. User optionally toggles eOriginal/Digital Signature (based on feature entitlements).

  16. User clicks "Send Document".

  17. LWC calls SendDocumentForEsigningController.createWorkFlow():

    • Passes base64 of selected file

    • Passes signers array as JSON

    • Passes recordId

    • Passes fileName

    • Passes documentAction (eOriginal / DigitalSignature / Both)

  18. Apex deserializes signers JSON → List<SignerInstance>.

  19. Apex creates Document_Workflow__c record:

    • Document_Template_Name__c = fileName

    • Signer_Configuration__c = signerInfo JSON (for later signing flow)

    • Status__c = "Workflow Initiated"

    • Current_Signing_Count__c = 1

    • Maximum_Signer__c = signers.size()

    • Signing_Link_Expiry_Date__c = now().addDays(30)

    • Document_Execution_Method__c = documentAction (eOriginal/Digital Signature)

    • Organization_Name__c, Organization_Address__c = from org settings

    • RecordTypeId = "DocGen_eSign"

  20. Apex creates ContentVersion (document blob):

    • Title = fileName

    • VersionData = base64 decoded

    • FirstPublishLocationId = Workflow ID (links file to workflow)

    • IsMajorVersion = true

  21. Apex updates workflow:

    • Content_Version_Id__c = ContentVersion ID

    • Status__c = "Document Generated"

  22. Apex returns { isSuccess: true, workflowId }.

  23. LWC receives response.

  24. LWC shows confirmation modal: "Document sent successfully! Workflow ID: [ID]"

  25. LWC displays next steps (e.g., "First signer will receive email shortly")

  26. User clicks Close/Redirect (if configured).

  27. Confirmation email sent to first signer with signing link (external system/flow handles this).