salesforce-appraiser-review.../force-app/main/default/classes/AppraiserCasePayloadBuilder...

172 lines
7.0 KiB
OpenEdge ABL

/**
* @description Builds CLM-ready JSON payload for Appraiser Case with related Deficiencies.
* Used to transform Salesforce data into DocuSign CLM merge field structure.
*/
public class AppraiserCasePayloadBuilder {
/**
* @description Generates CLM merge payload for a given Appraiser Case.
* @param caseId Appraiser_Case__c record Id
* @return Map<String, Object> CLM merge data ready for template rendering
*/
public static Map<String, Object> buildPayload(String caseId) {
// Query parent case with all child deficiencies
Appraiser_Case__c appraiserCase = queryAppraiserCase(caseId);
if (appraiserCase == null) {
throw new IllegalArgumentException('Appraiser Case not found: ' + caseId);
}
// Build CLM payload structure
Map<String, Object> payload = new Map<String, Object>();
payload.put('AppraiserCaseNumber', appraiserCase.Name);
payload.put('AppraiserFieldReviewDate', formatDate(appraiserCase.Appraiser_Field_Review_Date__c));
payload.put('LetterSentDate', formatDate(appraiserCase.Letter_Sent_Date__c));
payload.put('FHACaseNumber', appraiserCase.FHA_Case_Number__c);
payload.put('AppraiserName', appraiserCase.Appraiser_Name__c);
payload.put('AppraiserSalutation', appraiserCase.Appraiser_Salutation__c);
payload.put('AppraiserLastName', appraiserCase.Appraiser_Last_Name__c);
payload.put('AppraiserEmail', appraiserCase.Appraiser_Email__c);
payload.put('AppraiserStreet', appraiserCase.Appraiser_Street__c);
payload.put('AppraiserCity', appraiserCase.Appraiser_City__c);
payload.put('AppraiserStateProvince', appraiserCase.Appraiser_State_Province__c);
payload.put('AppraiserPostalCode', appraiserCase.Appraiser_Postal_Code__c);
payload.put('AppraiserCountry', appraiserCase.Appraiser_Country__c);
payload.put('AppraiserAddress', formatMailingAddress(
appraiserCase.Appraiser_Street__c,
appraiserCase.Appraiser_City__c,
appraiserCase.Appraiser_State_Province__c,
appraiserCase.Appraiser_Postal_Code__c,
appraiserCase.Appraiser_Country__c
));
payload.put('PropertyStreet', appraiserCase.Property_Street__c);
payload.put('PropertyCity', appraiserCase.Property_City__c);
payload.put('PropertyStateProvince', appraiserCase.Property_State_Province__c);
payload.put('PropertyPostalCode', appraiserCase.Property_Postal_Code__c);
payload.put('PropertyCountry', appraiserCase.Property_Country__c);
payload.put('PropertyAddress', formatAddress(appraiserCase));
// Transform child deficiencies into DeficiencyList array
List<Map<String, Object>> deficiencyList = new List<Map<String, Object>>();
if (appraiserCase.Deficiencies__r != null && !appraiserCase.Deficiencies__r.isEmpty()) {
for (Appraiser_Case_Deficiency__c deficiency : appraiserCase.Deficiencies__r) {
Map<String, Object> defMap = new Map<String, Object>();
defMap.put('deficiencyNumber', deficiency.Deficiency_Number__c);
defMap.put('description', deficiency.Description__c);
defMap.put('resolution', deficiency.Resolution__c);
defMap.put('reference', deficiency.Reference__c);
deficiencyList.add(defMap);
}
}
payload.put('DeficiencyList', deficiencyList);
return payload;
}
/**
* @description Returns CLM payload as JSON string for API transmission.
* @param caseId Appraiser_Case__c record Id
* @return String JSON representation of payload
*/
public static String buildPayloadJson(String caseId) {
Map<String, Object> payload = buildPayload(caseId);
return JSON.serialize(payload);
}
/**
* @description Query Appraiser Case with related Deficiencies ordered by number.
* @param caseId Appraiser_Case__c record Id
* @return Appraiser_Case__c Record with Deficiencies__r populated
*/
private static Appraiser_Case__c queryAppraiserCase(String caseId) {
List<Appraiser_Case__c> results = [
SELECT
Id,
Name,
Appraiser_Field_Review_Date__c,
Letter_Sent_Date__c,
FHA_Case_Number__c,
Appraiser_Name__c,
Appraiser_Salutation__c,
Appraiser_Last_Name__c,
Appraiser_Email__c,
Appraiser_Street__c,
Appraiser_City__c,
Appraiser_State_Province__c,
Appraiser_Postal_Code__c,
Appraiser_Country__c,
Property_Street__c,
Property_City__c,
Property_State_Province__c,
Property_Postal_Code__c,
Property_Country__c,
(SELECT Id, Deficiency_Number__c, Description__c, Resolution__c, Reference__c
FROM Deficiencies__r
ORDER BY Deficiency_Number__c ASC)
FROM Appraiser_Case__c
WHERE Id = :caseId
LIMIT 1
];
return results.isEmpty() ? null : results.get(0);
}
/**
* @description Format date for CLM merge (for example Apr 09, 2026) or null.
* @param dt Date field value
* @return String Formatted date or null
*/
private static String formatDate(Date dt) {
return dt != null
? DateTime.newInstance(dt, Time.newInstance(0, 0, 0, 0)).format('MMM dd, yyyy')
: null;
}
private static String formatAddress(Appraiser_Case__c appraiserCase) {
return formatMailingAddress(
appraiserCase.Property_Street__c,
appraiserCase.Property_City__c,
appraiserCase.Property_State_Province__c,
appraiserCase.Property_Postal_Code__c,
appraiserCase.Property_Country__c
);
}
public static String formatMailingAddress(
String street,
String city,
String stateProvince,
String postalCode,
String country
) {
List<String> lines = new List<String>();
if (String.isNotBlank(street)) {
lines.add(street.trim());
}
List<String> localityParts = new List<String>();
if (String.isNotBlank(city)) {
localityParts.add(city.trim());
}
if (String.isNotBlank(stateProvince)) {
localityParts.add(stateProvince.trim());
}
String locality = String.join(localityParts, ', ');
if (String.isNotBlank(postalCode)) {
locality = String.isNotBlank(locality)
? locality + ' ' + postalCode.trim()
: postalCode.trim();
}
if (String.isNotBlank(locality)) {
lines.add(locality);
}
if (String.isNotBlank(country)) {
lines.add(country.trim());
}
return lines.isEmpty() ? null : String.join(lines, ', ');
}
}