745 lines
32 KiB
OpenEdge ABL
745 lines
32 KiB
OpenEdge ABL
public with sharing class CLMAdminService {
|
|
public class CaseDeficiencyItem {
|
|
@AuraEnabled public Id recordId;
|
|
@AuraEnabled public Decimal deficiencyNumber;
|
|
@AuraEnabled public String description;
|
|
@AuraEnabled public String resolution;
|
|
@AuraEnabled public String reference;
|
|
}
|
|
|
|
public class CaseContext {
|
|
@AuraEnabled public Id caseId;
|
|
@AuraEnabled public String caseNumber;
|
|
@AuraEnabled public String propertyAddress;
|
|
@AuraEnabled public String lastDocGenStatus;
|
|
@AuraEnabled public String lastDocGenMessage;
|
|
@AuraEnabled public String lastClmAccountCode;
|
|
@AuraEnabled public String lastDocGenTaskId;
|
|
@AuraEnabled public String lastDocGenTaskUrl;
|
|
@AuraEnabled public String generatedDocumentUrl;
|
|
@AuraEnabled public String generatedDocumentId;
|
|
@AuraEnabled public String attachedFileContentDocumentId;
|
|
@AuraEnabled public String attachedFileUrl;
|
|
@AuraEnabled public Datetime lastDocGenRequestedAt;
|
|
@AuraEnabled public Datetime lastDocGenCompletedAt;
|
|
@AuraEnabled public List<CaseDeficiencyItem> deficiencies;
|
|
}
|
|
|
|
public class FileAttachmentResult {
|
|
@AuraEnabled public Boolean success;
|
|
@AuraEnabled public String message;
|
|
@AuraEnabled public String contentDocumentId;
|
|
@AuraEnabled public String fileUrl;
|
|
@AuraEnabled public String fileTitle;
|
|
}
|
|
|
|
public class AccountSettings {
|
|
@AuraEnabled public String accountCode;
|
|
@AuraEnabled public String accountDisplayName;
|
|
@AuraEnabled public String environment;
|
|
@AuraEnabled public String clmAccountId;
|
|
@AuraEnabled public String clmApiNamedCredential;
|
|
@AuraEnabled public String clmDownloadNamedCredential;
|
|
@AuraEnabled public String eSignatureRestNamedCredential;
|
|
@AuraEnabled public String templateRootFolderHref;
|
|
@AuraEnabled public String destinationRootFolderHref;
|
|
@AuraEnabled public String defaultTemplateDocumentHref;
|
|
@AuraEnabled public String defaultDocumentNamePrefix;
|
|
@AuraEnabled public Boolean active;
|
|
}
|
|
|
|
public class LetterSettings {
|
|
@AuraEnabled public String accountCode;
|
|
@AuraEnabled public String letterCode;
|
|
@AuraEnabled public String letterDisplayName;
|
|
@AuraEnabled public String description;
|
|
@AuraEnabled public Boolean isDefault;
|
|
@AuraEnabled public Decimal sortOrder;
|
|
@AuraEnabled public String templateRootFolderHref;
|
|
@AuraEnabled public String destinationRootFolderHref;
|
|
@AuraEnabled public String defaultTemplateDocumentHref;
|
|
@AuraEnabled public String defaultDocumentNamePrefix;
|
|
@AuraEnabled public Boolean active;
|
|
}
|
|
|
|
public class ResourceItem {
|
|
@AuraEnabled public String name;
|
|
@AuraEnabled public String href;
|
|
@AuraEnabled public String type;
|
|
@AuraEnabled public String parentHref;
|
|
@AuraEnabled public String rawJson;
|
|
}
|
|
|
|
public class FolderContents {
|
|
@AuraEnabled public ResourceItem folder;
|
|
@AuraEnabled public List<ResourceItem> folders;
|
|
@AuraEnabled public List<ResourceItem> documents;
|
|
}
|
|
|
|
public class DocGenPreview {
|
|
@AuraEnabled public String accountCode;
|
|
@AuraEnabled public String accountDisplayName;
|
|
@AuraEnabled public String letterCode;
|
|
@AuraEnabled public String letterDisplayName;
|
|
@AuraEnabled public String mergeTaskEndpointUrl;
|
|
@AuraEnabled public String templateDocHref;
|
|
@AuraEnabled public String destinationFolderHref;
|
|
@AuraEnabled public String destinationDocName;
|
|
@AuraEnabled public String payloadJson;
|
|
@AuraEnabled public String dataXml;
|
|
@AuraEnabled public String requestBodyJson;
|
|
}
|
|
|
|
@AuraEnabled(cacheable=true)
|
|
public static List<AccountSettings> listAccountSettings() {
|
|
List<AccountSettings> settings = new List<AccountSettings>();
|
|
for (CLM_Account_Setting__mdt row : [
|
|
SELECT DeveloperName,
|
|
Account_Code__c,
|
|
Account_Display_Name__c,
|
|
Environment_Code__c,
|
|
CLM_Account_Id__c,
|
|
CLM_Api_Named_Credential__c,
|
|
CLM_Download_Named_Credential__c,
|
|
ESignature_Rest_Named_Credential__c,
|
|
Template_Root_Folder_Href__c,
|
|
Destination_Root_Folder_Href__c,
|
|
Default_Template_Document_Href__c,
|
|
Default_Destination_Document_Name_Prefix__c,
|
|
Active__c
|
|
FROM CLM_Account_Setting__mdt
|
|
WHERE Active__c = true
|
|
ORDER BY Account_Display_Name__c ASC, DeveloperName ASC
|
|
]) {
|
|
settings.add(toAccountSettings(row));
|
|
}
|
|
return settings;
|
|
}
|
|
|
|
@AuraEnabled(cacheable=true)
|
|
public static AccountSettings getAccountSettings(String accountCode) {
|
|
CLM_Account_Setting__mdt row = resolveAccountSetting(accountCode);
|
|
return row == null ? null : toAccountSettings(row);
|
|
}
|
|
|
|
@AuraEnabled(cacheable=true)
|
|
public static List<LetterSettings> listLetterSettings(String accountCode) {
|
|
AccountSettings account = getAccountSettings(accountCode);
|
|
List<LetterSettings> letters = new List<LetterSettings>();
|
|
if (account == null) {
|
|
return letters;
|
|
}
|
|
|
|
for (CLM_Letter_Definition__mdt row : [
|
|
SELECT DeveloperName,
|
|
Account_Code__c,
|
|
Letter_Code__c,
|
|
Letter_Display_Name__c,
|
|
Description__c,
|
|
Active__c,
|
|
Is_Default__c,
|
|
Sort_Order__c,
|
|
Template_Root_Folder_Href__c,
|
|
Destination_Root_Folder_Href__c,
|
|
Default_Template_Document_Href__c,
|
|
Default_Destination_Document_Name_Prefix__c
|
|
FROM CLM_Letter_Definition__mdt
|
|
WHERE Active__c = true
|
|
AND Account_Code__c = :account.accountCode
|
|
ORDER BY Is_Default__c DESC, Sort_Order__c ASC, Letter_Display_Name__c ASC, DeveloperName ASC
|
|
]) {
|
|
letters.add(toLetterSettings(row, account));
|
|
}
|
|
|
|
if (letters.isEmpty()) {
|
|
letters.add(buildFallbackLetterSettings(account));
|
|
}
|
|
return letters;
|
|
}
|
|
|
|
@AuraEnabled(cacheable=true)
|
|
public static LetterSettings getLetterSettings(String accountCode, String letterCode) {
|
|
AccountSettings account = getAccountSettings(accountCode);
|
|
if (account == null) {
|
|
return null;
|
|
}
|
|
|
|
String normalizedLetterCode = String.isBlank(letterCode) ? null : letterCode.trim();
|
|
if (String.isNotBlank(normalizedLetterCode)) {
|
|
List<CLM_Letter_Definition__mdt> rows = [
|
|
SELECT DeveloperName,
|
|
Account_Code__c,
|
|
Letter_Code__c,
|
|
Letter_Display_Name__c,
|
|
Description__c,
|
|
Active__c,
|
|
Is_Default__c,
|
|
Sort_Order__c,
|
|
Template_Root_Folder_Href__c,
|
|
Destination_Root_Folder_Href__c,
|
|
Default_Template_Document_Href__c,
|
|
Default_Destination_Document_Name_Prefix__c
|
|
FROM CLM_Letter_Definition__mdt
|
|
WHERE Active__c = true
|
|
AND Account_Code__c = :account.accountCode
|
|
AND Letter_Code__c = :normalizedLetterCode
|
|
LIMIT 1
|
|
];
|
|
if (!rows.isEmpty()) {
|
|
return toLetterSettings(rows[0], account);
|
|
}
|
|
}
|
|
|
|
List<LetterSettings> letters = listLetterSettings(account.accountCode);
|
|
for (LetterSettings letter : letters) {
|
|
if (letter.isDefault) {
|
|
return letter;
|
|
}
|
|
}
|
|
return letters.isEmpty() ? buildFallbackLetterSettings(account) : letters[0];
|
|
}
|
|
|
|
@AuraEnabled(cacheable=false)
|
|
public static CLMDocGenCallout.CLMDocGenResponse generateDocument(
|
|
Id appraiserCaseId,
|
|
String templateDocHref,
|
|
String destinationFolderHref,
|
|
String destinationDocName,
|
|
String accountCode
|
|
) {
|
|
CLM_Account_Setting__mdt account = requireAccountSetting(accountCode);
|
|
CLMDocGenCallout.CLMDocGenResponse response = CLMDocGenCallout.generateDocument(
|
|
(String) appraiserCaseId,
|
|
templateDocHref,
|
|
destinationFolderHref,
|
|
destinationDocName,
|
|
account.Environment_Code__c,
|
|
account.CLM_Account_Id__c,
|
|
account.CLM_Api_Named_Credential__c
|
|
);
|
|
persistDocGenResult(appraiserCaseId, templateDocHref, destinationFolderHref, response, false, accountCode);
|
|
return response;
|
|
}
|
|
|
|
@AuraEnabled(cacheable=false)
|
|
public static CLMDocGenCallout.CLMDocGenResponse getTaskStatus(Id appraiserCaseId, String taskId, String accountCode) {
|
|
CLM_Account_Setting__mdt account = requireAccountSetting(accountCode);
|
|
CLMDocGenCallout.CLMDocGenResponse response = CLMDocGenCallout.getTaskStatus(
|
|
taskId,
|
|
account.Environment_Code__c,
|
|
account.CLM_Account_Id__c,
|
|
account.CLM_Api_Named_Credential__c
|
|
);
|
|
persistDocGenResult(appraiserCaseId, null, null, response, true, accountCode);
|
|
return response;
|
|
}
|
|
|
|
@AuraEnabled(cacheable=false)
|
|
public static String probeResource(String resourceOrHref, String accountCode) {
|
|
CLM_Account_Setting__mdt account = requireAccountSetting(accountCode);
|
|
return performGet(resourceOrHref, account).getBody();
|
|
}
|
|
|
|
@AuraEnabled(cacheable=false)
|
|
public static DocGenPreview getDocGenPreview(Id appraiserCaseId, String accountCode, String letterCode) {
|
|
if (appraiserCaseId == null) {
|
|
throw new AuraHandledException('appraiserCaseId is required');
|
|
}
|
|
|
|
AccountSettings account = getAccountSettings(accountCode);
|
|
if (account == null) {
|
|
throw new AuraHandledException('No active CLM account setting was found for ' + accountCode + '.');
|
|
}
|
|
|
|
LetterSettings letter = getLetterSettings(account.accountCode, letterCode);
|
|
List<Appraiser_Case__c> previewRows = [
|
|
SELECT Id, Name
|
|
FROM Appraiser_Case__c
|
|
WHERE Id = :appraiserCaseId
|
|
LIMIT 1
|
|
];
|
|
if (previewRows.isEmpty()) {
|
|
throw new AuraHandledException('Appraiser Case not found: ' + appraiserCaseId);
|
|
}
|
|
Appraiser_Case__c appraiserCase = previewRows[0];
|
|
|
|
String prefix = letter != null && String.isNotBlank(letter.defaultDocumentNamePrefix)
|
|
? letter.defaultDocumentNamePrefix
|
|
: account.defaultDocumentNamePrefix;
|
|
|
|
DocGenPreview preview = new DocGenPreview();
|
|
preview.accountCode = account.accountCode;
|
|
preview.accountDisplayName = account.accountDisplayName;
|
|
preview.letterCode = letter != null ? letter.letterCode : 'APPRAISER_REVIEW';
|
|
preview.letterDisplayName = letter != null ? letter.letterDisplayName : 'Appraiser Review Letter';
|
|
preview.templateDocHref = letter != null ? letter.defaultTemplateDocumentHref : account.defaultTemplateDocumentHref;
|
|
preview.destinationFolderHref = letter != null ? letter.destinationRootFolderHref : account.destinationRootFolderHref;
|
|
preview.destinationDocName = buildDefaultDocumentName(prefix, appraiserCase.Name);
|
|
preview.mergeTaskEndpointUrl = CLMDocGenCallout.buildDocumentXmlMergeTasksUrl(
|
|
preview.templateDocHref,
|
|
preview.destinationFolderHref,
|
|
account.environment,
|
|
account.clmAccountId
|
|
);
|
|
preview.payloadJson = JSON.serializePretty(AppraiserCasePayloadBuilder.buildPayload((String) appraiserCaseId));
|
|
preview.dataXml = CLMDocGenCallout.prettyPrintXml(CLMDocGenCallout.buildDataXmlForCase((String) appraiserCaseId));
|
|
preview.requestBodyJson = CLMDocGenCallout.buildRequestBodyJson(
|
|
(String) appraiserCaseId,
|
|
preview.templateDocHref,
|
|
preview.destinationFolderHref,
|
|
preview.destinationDocName
|
|
);
|
|
return preview;
|
|
}
|
|
|
|
@AuraEnabled(cacheable=false)
|
|
public static CaseContext getCaseContext(Id appraiserCaseId) {
|
|
List<Appraiser_Case__c> contextRows = [
|
|
SELECT Id,
|
|
Name,
|
|
Property_Street__c,
|
|
Property_City__c,
|
|
Property_State_Province__c,
|
|
Property_Postal_Code__c,
|
|
Property_Country__c,
|
|
Last_DocGen_Status__c,
|
|
Last_DocGen_Message__c,
|
|
Last_CLM_Account_Code__c,
|
|
Last_DocGen_Task_Id__c,
|
|
Last_DocGen_Task_Url__c,
|
|
Generated_Document_Url__c,
|
|
Generated_Document_Id__c,
|
|
Attached_File_Content_Document_Id__c,
|
|
Attached_File_Url__c,
|
|
Last_DocGen_Requested_At__c,
|
|
Last_DocGen_Completed_At__c,
|
|
(SELECT Id,
|
|
Deficiency_Number__c,
|
|
Description__c,
|
|
Resolution__c,
|
|
Reference__c
|
|
FROM Deficiencies__r
|
|
ORDER BY Deficiency_Number__c ASC, CreatedDate ASC)
|
|
FROM Appraiser_Case__c
|
|
WHERE Id = :appraiserCaseId
|
|
LIMIT 1
|
|
];
|
|
if (contextRows.isEmpty()) {
|
|
throw new AuraHandledException('Appraiser Case not found: ' + appraiserCaseId);
|
|
}
|
|
Appraiser_Case__c appraiserCase = contextRows[0];
|
|
|
|
CaseContext context = new CaseContext();
|
|
context.caseId = appraiserCase.Id;
|
|
context.caseNumber = appraiserCase.Name;
|
|
context.propertyAddress = formatAddress(appraiserCase);
|
|
context.lastDocGenStatus = appraiserCase.Last_DocGen_Status__c;
|
|
context.lastDocGenMessage = appraiserCase.Last_DocGen_Message__c;
|
|
context.lastClmAccountCode = appraiserCase.Last_CLM_Account_Code__c;
|
|
context.lastDocGenTaskId = appraiserCase.Last_DocGen_Task_Id__c;
|
|
context.lastDocGenTaskUrl = appraiserCase.Last_DocGen_Task_Url__c;
|
|
context.generatedDocumentUrl = appraiserCase.Generated_Document_Url__c;
|
|
context.generatedDocumentId = appraiserCase.Generated_Document_Id__c;
|
|
context.attachedFileContentDocumentId = appraiserCase.Attached_File_Content_Document_Id__c;
|
|
context.attachedFileUrl = appraiserCase.Attached_File_Url__c;
|
|
context.lastDocGenRequestedAt = appraiserCase.Last_DocGen_Requested_At__c;
|
|
context.lastDocGenCompletedAt = appraiserCase.Last_DocGen_Completed_At__c;
|
|
context.deficiencies = new List<CaseDeficiencyItem>();
|
|
|
|
if (appraiserCase.Deficiencies__r != null) {
|
|
for (Appraiser_Case_Deficiency__c deficiency : appraiserCase.Deficiencies__r) {
|
|
CaseDeficiencyItem item = new CaseDeficiencyItem();
|
|
item.recordId = deficiency.Id;
|
|
item.deficiencyNumber = deficiency.Deficiency_Number__c;
|
|
item.description = deficiency.Description__c;
|
|
item.resolution = deficiency.Resolution__c;
|
|
item.reference = deficiency.Reference__c;
|
|
context.deficiencies.add(item);
|
|
}
|
|
}
|
|
|
|
return context;
|
|
}
|
|
|
|
@AuraEnabled(cacheable=false)
|
|
public static FileAttachmentResult attachGeneratedDocumentToCase(Id appraiserCaseId, String accountCode) {
|
|
if (appraiserCaseId == null) {
|
|
throw new AuraHandledException('appraiserCaseId is required');
|
|
}
|
|
CLM_Account_Setting__mdt account = requireAccountSetting(accountCode);
|
|
|
|
Appraiser_Case__c appraiserCase = [
|
|
SELECT Id,
|
|
Name,
|
|
Generated_Document_Url__c,
|
|
Generated_Document_Id__c
|
|
FROM Appraiser_Case__c
|
|
WHERE Id = :appraiserCaseId
|
|
LIMIT 1
|
|
];
|
|
|
|
if (String.isBlank(appraiserCase.Generated_Document_Url__c)) {
|
|
throw new AuraHandledException('No generated document is available to attach yet.');
|
|
}
|
|
|
|
CLMDocGenCallout.DownloadedDocument downloaded = CLMDocGenCallout.downloadDocument(
|
|
appraiserCase.Generated_Document_Url__c,
|
|
account.Environment_Code__c,
|
|
account.CLM_Account_Id__c,
|
|
account.CLM_Download_Named_Credential__c
|
|
);
|
|
String fileName = String.isNotBlank(downloaded.fileName)
|
|
? downloaded.fileName
|
|
: 'Generated_' + appraiserCase.Name + '.docx';
|
|
String title = fileName.contains('.')
|
|
? fileName.substringBeforeLast('.')
|
|
: fileName;
|
|
|
|
ContentVersion version = new ContentVersion(
|
|
Title = title,
|
|
PathOnClient = '/' + fileName,
|
|
VersionData = downloaded.body
|
|
);
|
|
insert version;
|
|
|
|
version = [
|
|
SELECT Id, ContentDocumentId
|
|
FROM ContentVersion
|
|
WHERE Id = :version.Id
|
|
LIMIT 1
|
|
];
|
|
|
|
insert new ContentDocumentLink(
|
|
ContentDocumentId = version.ContentDocumentId,
|
|
LinkedEntityId = appraiserCase.Id,
|
|
ShareType = 'V',
|
|
Visibility = 'AllUsers'
|
|
);
|
|
|
|
String fileUrl = '/lightning/r/ContentDocument/' + version.ContentDocumentId + '/view';
|
|
update new Appraiser_Case__c(
|
|
Id = appraiserCase.Id,
|
|
Last_CLM_Account_Code__c = accountCode,
|
|
Attached_File_Content_Document_Id__c = version.ContentDocumentId,
|
|
Attached_File_Url__c = fileUrl
|
|
);
|
|
|
|
FileAttachmentResult result = new FileAttachmentResult();
|
|
result.success = true;
|
|
result.message = 'Generated document attached to the case.';
|
|
result.contentDocumentId = version.ContentDocumentId;
|
|
result.fileUrl = fileUrl;
|
|
result.fileTitle = title;
|
|
return result;
|
|
}
|
|
|
|
private static String formatAddress(Appraiser_Case__c appraiserCase) {
|
|
return AppraiserCasePayloadBuilder.formatMailingAddress(
|
|
appraiserCase.Property_Street__c,
|
|
appraiserCase.Property_City__c,
|
|
appraiserCase.Property_State_Province__c,
|
|
appraiserCase.Property_Postal_Code__c,
|
|
appraiserCase.Property_Country__c
|
|
);
|
|
}
|
|
|
|
@AuraEnabled(cacheable=false)
|
|
public static FolderContents getFolderContents(String folderHref, String accountCode) {
|
|
if (String.isBlank(folderHref)) {
|
|
throw new IllegalArgumentException('folderHref is required');
|
|
}
|
|
CLM_Account_Setting__mdt account = requireAccountSetting(accountCode);
|
|
|
|
FolderContents contents = new FolderContents();
|
|
contents.folder = parseSingleResource(performGet(folderHref, account).getBody(), 'Folder');
|
|
contents.folders = parseResourceList(performGet(folderHref + '/folders', account).getBody(), 'Folder', folderHref);
|
|
contents.documents = parseResourceList(performGet(folderHref + '/documents', account).getBody(), 'Document', folderHref);
|
|
return contents;
|
|
}
|
|
|
|
private static HttpResponse performGet(String resourceOrHref, CLM_Account_Setting__mdt account) {
|
|
HttpRequest req = new HttpRequest();
|
|
req.setEndpoint(CLMDocGenCallout.buildEndpointForResource(
|
|
resourceOrHref,
|
|
account.CLM_Account_Id__c,
|
|
account.CLM_Api_Named_Credential__c
|
|
));
|
|
req.setMethod('GET');
|
|
req.setTimeout(CLMDocGenCallout.HTTP_TIMEOUT);
|
|
|
|
HttpResponse res = new Http().send(req);
|
|
Integer statusCode = res.getStatusCode();
|
|
if (statusCode < 200 || statusCode >= 300) {
|
|
throw new AuraHandledException('CLM API Error (HTTP ' + statusCode + '): ' + res.getBody());
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
@TestVisible
|
|
private static ResourceItem parseSingleResource(String body, String defaultType) {
|
|
Object root = JSON.deserializeUntyped(body);
|
|
if (!(root instanceof Map<String, Object>)) {
|
|
return null;
|
|
}
|
|
return parseResource((Map<String, Object>) root, defaultType, null);
|
|
}
|
|
|
|
@TestVisible
|
|
private static List<ResourceItem> parseResourceList(String body, String defaultType, String parentHref) {
|
|
Object root = JSON.deserializeUntyped(body);
|
|
List<Object> records = unwrapList(root);
|
|
List<ResourceItem> items = new List<ResourceItem>();
|
|
|
|
for (Object record : records) {
|
|
if (record instanceof Map<String, Object>) {
|
|
items.add(parseResource((Map<String, Object>) record, defaultType, parentHref));
|
|
}
|
|
}
|
|
|
|
return items;
|
|
}
|
|
|
|
private static List<Object> unwrapList(Object root) {
|
|
if (root instanceof List<Object>) {
|
|
return (List<Object>) root;
|
|
}
|
|
|
|
if (root instanceof Map<String, Object>) {
|
|
Map<String, Object> payload = (Map<String, Object>) root;
|
|
for (String key : new List<String>{ 'Results', 'Items', 'Documents', 'Folders' }) {
|
|
Object value = payload.get(key);
|
|
if (value instanceof List<Object>) {
|
|
return (List<Object>) value;
|
|
}
|
|
}
|
|
|
|
if (payload.size() == 1) {
|
|
for (Object value : payload.values()) {
|
|
if (value instanceof List<Object>) {
|
|
return (List<Object>) value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return new List<Object>();
|
|
}
|
|
|
|
private static ResourceItem parseResource(Map<String, Object> source, String defaultType, String parentHref) {
|
|
ResourceItem item = new ResourceItem();
|
|
item.name = firstString(source, new List<String>{ 'Name', 'DisplayName', 'Title', 'Label' });
|
|
item.href = firstString(source, new List<String>{ 'Href', 'Uri', 'Location' });
|
|
item.type = firstString(source, new List<String>{ 'Type', 'ObjectType', 'ItemType' });
|
|
item.parentHref = extractParentHref(source, parentHref);
|
|
item.rawJson = JSON.serialize(source);
|
|
|
|
if (String.isBlank(item.type)) {
|
|
item.type = defaultType;
|
|
}
|
|
|
|
if (String.isBlank(item.name) && String.isNotBlank(item.href)) {
|
|
item.name = item.href.substringAfterLast('/');
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
private static String extractParentHref(Map<String, Object> source, String fallbackValue) {
|
|
Object parentValue = source.get('Parent');
|
|
if (parentValue instanceof Map<String, Object>) {
|
|
String href = firstString((Map<String, Object>) parentValue, new List<String>{ 'Href', 'Uri', 'Location' });
|
|
if (String.isNotBlank(href)) {
|
|
return href;
|
|
}
|
|
}
|
|
return fallbackValue;
|
|
}
|
|
|
|
private static String firstString(Map<String, Object> source, List<String> keys) {
|
|
for (String key : keys) {
|
|
Object value = source.get(key);
|
|
if (value != null) {
|
|
String textValue = String.valueOf(value);
|
|
if (String.isNotBlank(textValue)) {
|
|
return textValue;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static void persistDocGenResult(
|
|
Id appraiserCaseId,
|
|
String templateDocHref,
|
|
String destinationFolderHref,
|
|
CLMDocGenCallout.CLMDocGenResponse response,
|
|
Boolean isStatusRefresh,
|
|
String accountCode
|
|
) {
|
|
if (appraiserCaseId == null || response == null) {
|
|
return;
|
|
}
|
|
|
|
Appraiser_Case__c updateCase = new Appraiser_Case__c(Id = appraiserCaseId);
|
|
updateCase.Last_CLM_Account_Code__c = accountCode;
|
|
updateCase.Last_DocGen_Status__c = String.isNotBlank(response.taskStatus) ? response.taskStatus : (response.success ? 'Submitted' : 'Failed');
|
|
updateCase.Last_DocGen_Message__c = response.message;
|
|
updateCase.Last_DocGen_Task_Id__c = response.documentId;
|
|
updateCase.Last_DocGen_Task_Url__c = response.documentUrl;
|
|
|
|
if (!isStatusRefresh) {
|
|
updateCase.Last_DocGen_Requested_At__c = System.now();
|
|
updateCase.Last_Template_Document_Href__c = templateDocHref;
|
|
updateCase.Last_Destination_Folder_Href__c = destinationFolderHref;
|
|
}
|
|
|
|
if (String.isNotBlank(response.generatedDocumentUrl)) {
|
|
updateCase.Generated_Document_Url__c = response.generatedDocumentUrl;
|
|
updateCase.Generated_Document_Id__c = response.generatedDocumentId;
|
|
}
|
|
|
|
if (response.success && String.valueOf(response.taskStatus).toLowerCase() == 'completed') {
|
|
updateCase.Last_DocGen_Completed_At__c = System.now();
|
|
}
|
|
|
|
update updateCase;
|
|
}
|
|
|
|
private static CLM_Account_Setting__mdt requireAccountSetting(String accountCode) {
|
|
CLM_Account_Setting__mdt row = resolveAccountSetting(accountCode);
|
|
if (row == null) {
|
|
throw new AuraHandledException('No active CLM account setting was found for ' + accountCode + '.');
|
|
}
|
|
return row;
|
|
}
|
|
|
|
private static CLM_Account_Setting__mdt resolveAccountSetting(String accountCode) {
|
|
String normalizedCode = String.isBlank(accountCode) ? null : accountCode.trim();
|
|
List<CLM_Account_Setting__mdt> rows;
|
|
if (String.isNotBlank(normalizedCode)) {
|
|
rows = [
|
|
SELECT DeveloperName,
|
|
Account_Code__c,
|
|
Account_Display_Name__c,
|
|
Environment_Code__c,
|
|
CLM_Account_Id__c,
|
|
CLM_Api_Named_Credential__c,
|
|
CLM_Download_Named_Credential__c,
|
|
ESignature_Rest_Named_Credential__c,
|
|
Template_Root_Folder_Href__c,
|
|
Destination_Root_Folder_Href__c,
|
|
Default_Template_Document_Href__c,
|
|
Default_Destination_Document_Name_Prefix__c,
|
|
Active__c
|
|
FROM CLM_Account_Setting__mdt
|
|
WHERE Active__c = true
|
|
AND DeveloperName = :normalizedCode
|
|
LIMIT 1
|
|
];
|
|
if (rows.isEmpty()) {
|
|
rows = [
|
|
SELECT DeveloperName,
|
|
Account_Code__c,
|
|
Account_Display_Name__c,
|
|
Environment_Code__c,
|
|
CLM_Account_Id__c,
|
|
CLM_Api_Named_Credential__c,
|
|
CLM_Download_Named_Credential__c,
|
|
ESignature_Rest_Named_Credential__c,
|
|
Template_Root_Folder_Href__c,
|
|
Destination_Root_Folder_Href__c,
|
|
Default_Template_Document_Href__c,
|
|
Default_Destination_Document_Name_Prefix__c,
|
|
Active__c
|
|
FROM CLM_Account_Setting__mdt
|
|
WHERE Active__c = true
|
|
AND Account_Code__c = :normalizedCode
|
|
LIMIT 1
|
|
];
|
|
}
|
|
} else {
|
|
rows = [
|
|
SELECT DeveloperName,
|
|
Account_Code__c,
|
|
Account_Display_Name__c,
|
|
Environment_Code__c,
|
|
CLM_Account_Id__c,
|
|
CLM_Api_Named_Credential__c,
|
|
CLM_Download_Named_Credential__c,
|
|
ESignature_Rest_Named_Credential__c,
|
|
Template_Root_Folder_Href__c,
|
|
Destination_Root_Folder_Href__c,
|
|
Default_Template_Document_Href__c,
|
|
Default_Destination_Document_Name_Prefix__c,
|
|
Active__c
|
|
FROM CLM_Account_Setting__mdt
|
|
WHERE Active__c = true
|
|
ORDER BY Account_Display_Name__c ASC, DeveloperName ASC
|
|
LIMIT 1
|
|
];
|
|
}
|
|
return rows.isEmpty() ? null : rows[0];
|
|
}
|
|
|
|
private static AccountSettings toAccountSettings(CLM_Account_Setting__mdt row) {
|
|
AccountSettings settings = new AccountSettings();
|
|
settings.accountCode = String.isNotBlank(row.Account_Code__c) ? row.Account_Code__c : row.DeveloperName;
|
|
settings.accountDisplayName = String.isNotBlank(row.Account_Display_Name__c) ? row.Account_Display_Name__c : row.DeveloperName;
|
|
settings.environment = row.Environment_Code__c;
|
|
settings.clmAccountId = row.CLM_Account_Id__c;
|
|
settings.clmApiNamedCredential = row.CLM_Api_Named_Credential__c;
|
|
settings.clmDownloadNamedCredential = row.CLM_Download_Named_Credential__c;
|
|
settings.eSignatureRestNamedCredential = row.ESignature_Rest_Named_Credential__c;
|
|
settings.templateRootFolderHref = row.Template_Root_Folder_Href__c;
|
|
settings.destinationRootFolderHref = row.Destination_Root_Folder_Href__c;
|
|
settings.defaultTemplateDocumentHref = row.Default_Template_Document_Href__c;
|
|
settings.defaultDocumentNamePrefix = row.Default_Destination_Document_Name_Prefix__c;
|
|
settings.active = row.Active__c;
|
|
return settings;
|
|
}
|
|
|
|
private static LetterSettings toLetterSettings(CLM_Letter_Definition__mdt row, AccountSettings account) {
|
|
LetterSettings settings = new LetterSettings();
|
|
settings.accountCode = String.isNotBlank(row.Account_Code__c) ? row.Account_Code__c : account.accountCode;
|
|
settings.letterCode = String.isNotBlank(row.Letter_Code__c) ? row.Letter_Code__c : 'APPRAISER_REVIEW';
|
|
settings.letterDisplayName = String.isNotBlank(row.Letter_Display_Name__c) ? row.Letter_Display_Name__c : row.DeveloperName;
|
|
settings.description = row.Description__c;
|
|
settings.isDefault = row.Is_Default__c;
|
|
settings.sortOrder = row.Sort_Order__c;
|
|
settings.templateRootFolderHref = firstNonBlankValue(row.Template_Root_Folder_Href__c, account.templateRootFolderHref);
|
|
settings.destinationRootFolderHref = firstNonBlankValue(row.Destination_Root_Folder_Href__c, account.destinationRootFolderHref);
|
|
settings.defaultTemplateDocumentHref = firstNonBlankValue(row.Default_Template_Document_Href__c, account.defaultTemplateDocumentHref);
|
|
settings.defaultDocumentNamePrefix = firstNonBlankValue(row.Default_Destination_Document_Name_Prefix__c, account.defaultDocumentNamePrefix);
|
|
settings.active = row.Active__c;
|
|
return settings;
|
|
}
|
|
|
|
private static LetterSettings buildFallbackLetterSettings(AccountSettings account) {
|
|
LetterSettings settings = new LetterSettings();
|
|
settings.accountCode = account.accountCode;
|
|
settings.letterCode = 'APPRAISER_REVIEW';
|
|
settings.letterDisplayName = 'Appraiser Review Letter';
|
|
settings.description = 'Fallback current appraiser letter flow.';
|
|
settings.isDefault = true;
|
|
settings.sortOrder = 10;
|
|
settings.templateRootFolderHref = account.templateRootFolderHref;
|
|
settings.destinationRootFolderHref = account.destinationRootFolderHref;
|
|
settings.defaultTemplateDocumentHref = account.defaultTemplateDocumentHref;
|
|
settings.defaultDocumentNamePrefix = account.defaultDocumentNamePrefix;
|
|
settings.active = true;
|
|
return settings;
|
|
}
|
|
|
|
private static String firstNonBlankValue(String preferredValue, String fallbackValue) {
|
|
return String.isNotBlank(preferredValue) ? preferredValue : fallbackValue;
|
|
}
|
|
|
|
private static String buildDefaultDocumentName(String prefix, String caseNumber) {
|
|
String normalizedPrefix = String.isNotBlank(prefix) ? prefix : 'Review';
|
|
return String.isNotBlank(caseNumber)
|
|
? normalizedPrefix + '_' + caseNumber + '.docx'
|
|
: normalizedPrefix + '.docx';
|
|
}
|
|
}
|