What this layer does
A signer is awaiting signature on a workflow. Either manually (quick action on workflow item) or automatically (nightly batch), the system sends a reminder email to prompt the signer to sign. The reminder fetches the signing link and optional custom email template from the workflow configuration, substitutes signer name and URL tokens, renders dynamic content (merge fields), and sends via org-wide email address. Every reminder sent is logged for audit trails. Two paths exist: manual (quick action) and automated (batch scheduler).
Three records (plus configuration) hold the state:
|
Object |
Holds |
|---|---|
|
|
Signer queue item (Envelope Link created) — contains Signer_Email__c, Signer_Name__c, Signer_URL_New__c, Signer_Sequence__c, linked to workflow |
|
|
Workflow header — contains Reminder_Email_Template__c (EmailTemplate ID), Sender_s_Email_Address__c (OrgWideEmailAddress), Email_Body__c, Email_Subject__c, Current_Signing_Count__c (which signer is up) |
|
|
Email template — subject and HTML body for reminder message. Contains {url} and {signer} tokens for substitution |
Architecture
┌─────────────────────────────────────────────────────┐
│ Two Reminder Paths │
└──────────────┬──────────────────────────────────────┘
│
┌──────────┴──────────┐
│ │
▼ ▼
MANUAL REMINDER AUTOMATED REMINDER
(Quick Action) (Scheduled Batch)
│ │
└──────────┬──────────┘
│
reminderEmailPopup (LWC) OR BatchSendReminderEmail (Batch)
│ │
└──────────┬──────────┘
│
┌───────────────────┬─┴──────────────────┐
│ │ │
▼ ▼ ▼
InvocableSendReminder │ DocumentSigningUtility
Email (Invocable) │ .sendEmail()
│ │ │
└─────────────┬─────┴────────────────────┘
│
Query EmailTemplate
Query OrgWideEmailAddress
Substitute {url}, {signer}, merge fields
│
Messaging.sendEmail()
│
Log result via UtilityClass.createReminderLog()
Key mechanism — two-path invocation + deferred scheduling.
Manual path: User clicks "Send Reminder" quick action on a workflow item (documentWorkFlowIndividual LWC). reminderEmailPopup LWC opens confirmation dialog. On confirm, calls GenerationScreenController.sendReminderEmail() → queries workflow item + workflow + email template → calls InvocableSendReminderEmail.sendReminder() → sends email immediately → logs result.
Automated path: BatchSendReminderEmail runs on schedule (via finish() reschedule or external org-wide schedule). Queries workflows in Awaiting Signature status (created in last N days per config). For each workflow, finds current signer (matching Current_Signing_Count__c). Fetches email template + org-wide address. Constructs and sends bulk emails. Logs each result. On finish(), reschedules itself for next run time (read from DocGen_eSign_Configuration__c).
LWC — reminderEmailPopup
Quick action quick-open component. Triggered by documentWorkFlowIndividual "Send Reminder" badge or flow button.
Tracked state
|
Property |
Purpose |
|---|---|
|
|
Injected: Document_Workflow_Item__c ID |
|
|
Toggles spinner during send |
Key functions
|
Function |
Behavior |
|---|---|
|
|
None (component stateless) |
|
|
Calls GenerationScreenController.sendReminderEmail({ recordId }). Sets isLoading = true. On success: shows toast, closes modal. On error: shows error toast, closes modal. |
|
|
Dispatches CloseActionScreenEvent. |
|
|
Displays ShowToastEvent. |
HTML Template
Info banner: "Are you sure you want to send a reminder email to notify the signer of the pending document?" Cancel/Send buttons in footer.
Apex — GenerationScreenController.sendReminderEmail()
@AuraEnabled method. Receives Document_Workflow_Item__c ID. Queries workflow item + linked workflow. Calls InvocableSendReminderEmail.sendReminder() passing item ID.
|
Method |
Returns |
What it does |
|---|---|---|
|
|
void |
Queries Document_Workflow_Item__c by recordId. Calls InvocableSendReminderEmail.sendReminder({ itemId }). Used by reminderEmailPopup LWC and documentWorkFlowIndividual LWC. |
Apex — InvocableSendReminderEmail
global with sharing. Invocable method (callable from Flow, Apex, or direct method calls).
|
Method |
Invocation |
What it does |
|---|---|---|
|
|
Flow, Apex, quick action → GenerationScreenController |
Takes Document_Workflow_Item__c ID(s). Queries item + workflow (including Reminder_Email_Template__c, Sender_s_Email_Address__c, Email_Body__c, Email_Subject__c). Queries same signer's Envelop Link Created event to fetch Signer_URL_New__c. Validates: URL, org-wide address, email, signer name present. Queries EmailTemplate by ID. If template exists: uses Subject + HTMLValue. Else: uses Email_Subject__c + Email_Body__c from workflow. Substitutes {url} → Signer_URL_New__c, {signer} → Signer_Name__c. Calls UtilityClass.renderDynamicContent() to replace merge fields (e.g., {Account.Name}). Calls DocumentSigningUtility.sendEmail() to construct email. Sends via Messaging.sendEmail(). On success: calls UtilityClass.createReminderLog('Reminder Email Delivered', workflowId, 'Success', null, 'Manual Reminder Email Sent'). On fail: logs error message. |
Validation gate: If Test.isRunningTest() = false, requires: sSignerURL not blank, orgWideEmailAddress not null, sSignerEmail not null, reminderTemplateId not null OR emailContent not blank.
Apex — BatchSendReminderEmail
global with sharing, implements Database.Batchable<sObject>, Schedulable, Database.Stateful. Queries workflows in Awaiting Signature state (created in last N days). For each workflow, identifies current signer (matching Current_Signing_Count__c to Signer_Sequence__c). Sends bulk reminder emails. Reschedules itself on finish().
|
Method |
Context |
What it does |
|---|---|---|
|
|
Batch init |
Queries DocGen_eSign_Configuration__c for 'Reminder_Batch_WhereClause'. If not set: defaults to WHERE Status = 'Awaiting Signature'. Appends CreatedDate = LAST_N_DAYS:{iLastDays} (read from 'Reminder_Batch_LastNDays' config, default N). Returns QueryLocator. |
|
|
Batch row processing |
Takes workflow batch. Extracts workflow IDs and current signer counts into map. Queries Workflow_Items WHERE Event_Type = 'Envelop Link Created' AND Workflow ID IN set (all signers' envelope links). Filters items: only process if Current_Signing_Count matches Signer_Sequence AND all required fields present (email, URL, body/template, org-wide, parent ID). Builds set of email template IDs + org-wide addresses. Queries EmailTemplates and OrgWideEmailAddresses. Builds map of address→ID and templateId→EmailTemplate. For each item to process: constructs EmailWrapper using DocumentSigningUtility. Uses template.Subject/HTMLValue if available, else workflow Email_Subject__c/Email_Body__c. Substitutes {url}, {signer}. Calls renderDynamicContent(). Adds to batch email list. Sends all emails via Messaging.sendEmail(lstMails, false). For each result, logs success/failure via UtilityClass.createReminderLog(). |
|
|
Scheduler invocation |
Creates new BatchSendReminderEmail() and calls database.executebatch(oBatch, iBatchSize). Decouples scheduler from batch. |
|
|
Batch completion |
Queries 'Reminder_Email_Next_Run_Time' config (hours from now). If set: calculates next scheduled time. Generates CRON expression. Generates unique job name. Calls System.schedule() to reschedule next batch run. This creates a self-rescheduling batch job. |
Configuration reads: Reminder_Batch_LastNDays (default N), Reminder_Batch_WhereClause (default "Status = 'Awaiting Signature'"), Reminder_Email_Next_Run_Time (hours to next run), Reminder_Batch_Batch_Size (batch size for execute).
Utility — DocumentSigningUtility.sendEmail()
Helper method. Constructs Messaging.SingleEmailMessage from EmailWrapper.
|
Wrapper Property |
Apex Property |
|---|---|
|
toAddress |
setToAddresses(new List<String>{ toAddress }) |
|
fromAddress |
setOrgWideEmailAddressId(fromAddress) [OrgWideEmailAddress ID] |
|
emailSubject |
setSubject(emailSubject) |
|
emailBody |
setHtmlBody(emailBody) |
Returns fully-built Messaging.SingleEmailMessage ready for sendEmail().
Utility — UtilityClass.createReminderLog()
Audit log. Creates platform event or log record. Takes event name, workflow ID, status, error message, description. Logs all manual and automated reminder attempts (success and failure).
Email template tokens
Standard substitutions (literal, no field lookup):
|
Token |
Replaced with |
|---|---|
|
|
Document_Workflow_Item__c.Signer_URL_New__c (signing link) |
|
|
Document_Workflow_Item__c.Signer_Name__c (signer name) |
|
|
Merge field lookup via UtilityClass.renderDynamicContent() — depends on parent record type |