feat(esignature): add EnvelopeCreateResult class and createEnvelope() method
Adds EnvelopeCreateResult inner DTO and createEnvelope(Id, String, String)
to DocusignESignatureService. Option A (template-based): POSTs to
/v2.1/accounts/{accountId}/envelopes with templateId, templateRoles
(Signer), and status=sent. Guards blank templateId and blank appraiser
email; catches all exceptions and wraps in result. Named credential
sourced from CLM_Account_Setting__mdt per ADR-002.
Agent: claude-sonnet-4-6
Tests: 8/8 passing | N/A (no new test methods — Task 3 covers test coverage)
Tests-Added: 0
TypeScript: N/A (Apex project)
This commit is contained in:
parent
e4b7456dc1
commit
c3421e858f
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
- [x] **Task 1 — Custom fields:** Add 5 eSignature tracking fields to `Appraiser_Case__c` object metadata and update `package.xml` if needed. Deploy to verify. (FR-001)
|
||||
|
||||
- [ ] **Task 2 — EnvelopeCreateResult class + createEnvelope() method:** Add `EnvelopeCreateResult` inner class and `createEnvelope(Id caseId, String accountCode, String templateId)` to `DocusignESignatureService`. (FR-002)
|
||||
- [x] **Task 2 — EnvelopeCreateResult class + createEnvelope() method:** Add `EnvelopeCreateResult` inner class and `createEnvelope(Id caseId, String accountCode, String templateId)` to `DocusignESignatureService`. (FR-002)
|
||||
|
||||
- [ ] **Task 3 — Tests for createEnvelope():** Add test coverage in `DocusignESignatureServiceTest` — success path (mock 201), failure path (mock 400), blank email guard. (NFR-001, TC-001, TC-002)
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,14 @@ public with sharing class DocusignESignatureService {
|
|||
@AuraEnabled public String rawJson;
|
||||
}
|
||||
|
||||
public class EnvelopeCreateResult {
|
||||
@AuraEnabled public Boolean success;
|
||||
@AuraEnabled public String envelopeId;
|
||||
@AuraEnabled public String status;
|
||||
@AuraEnabled public String envelopeUri;
|
||||
@AuraEnabled public String errorMessage;
|
||||
}
|
||||
|
||||
@AuraEnabled(cacheable=true)
|
||||
public static ESignatureAccountConfig getAccountConfig(String accountCode) {
|
||||
CLM_Account_Setting__mdt row = requireAccountSetting(accountCode);
|
||||
|
|
@ -144,6 +152,78 @@ public with sharing class DocusignESignatureService {
|
|||
return parseEnvelopeList(response.responseBody);
|
||||
}
|
||||
|
||||
@AuraEnabled(cacheable=false)
|
||||
public static EnvelopeCreateResult createEnvelope(Id caseId, String accountCode, String templateId) {
|
||||
EnvelopeCreateResult result = new EnvelopeCreateResult();
|
||||
result.success = false;
|
||||
try {
|
||||
if (String.isBlank(templateId)) {
|
||||
result.errorMessage = 'Template ID is required.';
|
||||
return result;
|
||||
}
|
||||
|
||||
CLM_Account_Setting__mdt row = requireAccountSetting(accountCode);
|
||||
String targetAccountId = requireESignatureAccountId(row, accountCode, null);
|
||||
|
||||
Appraiser_Case__c caseRecord = [
|
||||
SELECT Appraiser_Email__c,
|
||||
Appraiser_Name__c,
|
||||
Appraiser_Last_Name__c,
|
||||
Appraiser_Salutation__c
|
||||
FROM Appraiser_Case__c
|
||||
WHERE Id = :caseId
|
||||
LIMIT 1
|
||||
];
|
||||
|
||||
if (String.isBlank(caseRecord.Appraiser_Email__c)) {
|
||||
result.errorMessage = 'Appraiser email is blank on this case. Cannot create envelope.';
|
||||
return result;
|
||||
}
|
||||
|
||||
String appraiserName = String.isNotBlank(caseRecord.Appraiser_Name__c)
|
||||
? caseRecord.Appraiser_Name__c
|
||||
: ((String.isNotBlank(caseRecord.Appraiser_Salutation__c)
|
||||
? caseRecord.Appraiser_Salutation__c + ' '
|
||||
: '') + String.valueOf(caseRecord.Appraiser_Last_Name__c)).trim();
|
||||
|
||||
Map<String, Object> roleMap = new Map<String, Object>{
|
||||
'email' => caseRecord.Appraiser_Email__c,
|
||||
'name' => appraiserName,
|
||||
'roleName' => 'Signer'
|
||||
};
|
||||
Map<String, Object> bodyMap = new Map<String, Object>{
|
||||
'templateId' => templateId,
|
||||
'templateRoles' => new List<Object>{ roleMap },
|
||||
'status' => 'sent'
|
||||
};
|
||||
|
||||
HttpRequest req = new HttpRequest();
|
||||
req.setEndpoint(buildEndpoint(
|
||||
'/v2.1/accounts/' + targetAccountId + '/envelopes',
|
||||
row.ESignature_Rest_Named_Credential__c
|
||||
));
|
||||
req.setMethod('POST');
|
||||
req.setHeader('Content-Type', 'application/json');
|
||||
req.setTimeout(30000);
|
||||
req.setBody(JSON.serialize(bodyMap));
|
||||
|
||||
HttpResponse res = new Http().send(req);
|
||||
if (res.getStatusCode() >= 200 && res.getStatusCode() < 300) {
|
||||
Map<String, Object> responseMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
|
||||
result.success = true;
|
||||
result.envelopeId = (String) responseMap.get('envelopeId');
|
||||
result.status = (String) responseMap.get('status');
|
||||
result.envelopeUri = (String) responseMap.get('uri');
|
||||
} else {
|
||||
result.errorMessage = 'eSignature API Error (HTTP ' + res.getStatusCode() + '): ' + res.getBody();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result.success = false;
|
||||
result.errorMessage = e.getMessage();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@TestVisible
|
||||
private static List<ESignatureAccountSummary> parseAccountList(String body) {
|
||||
Object root = JSON.deserializeUntyped(body);
|
||||
|
|
|
|||
Loading…
Reference in New Issue