diff --git a/docs/CLM_TEMPLATE_MAPPING_SNIPPET.md b/docs/CLM_TEMPLATE_MAPPING_SNIPPET.md new file mode 100644 index 0000000..92dddfe --- /dev/null +++ b/docs/CLM_TEMPLATE_MAPPING_SNIPPET.md @@ -0,0 +1,71 @@ +# DocuSign CLM Template Mapping Snippet + +This project assumes Salesforce is the system of record and DocuSign CLM doc gen receives a payload built from `Appraiser_Case__c` and its related `Appraiser_Deficiency__c` records. + +## Suggested Merge Payload + +```json +{ + "templateKey": "APPRAISER_REVIEW_LETTER", + "recordId": "a01XXXXXXXXXXXX", + "sourceObject": "Appraiser_Case__c", + "mergeData": { + "appraiserCaseNumber": "AC-000123", + "appraiserFieldReviewDate": "2026-04-01", + "propertyStreet": "123 Main St", + "propertyCity": "Ottawa", + "propertyStateProvince": "ON", + "propertyPostalCode": "K1A 0A1", + "propertyCountry": "Canada", + "propertyAddressSingleLine": "123 Main St | Ottawa, ON, K1A 0A1 | Canada", + "deficiencies": [ + { + "deficiencyNumber": "1", + "description": "Missing comparable sale analysis", + "resolution": "Provide updated comparable sales section", + "sortOrder": 1 + } + ] + } +} +``` + +## Suggested Template Tokens + +Use the actual DocuSign CLM token syntax used in your tenant, but the field model should be equivalent to: + +- `{{mergeData.appraiserCaseNumber}}` +- `{{mergeData.appraiserFieldReviewDate}}` +- `{{mergeData.propertyStreet}}` +- `{{mergeData.propertyCity}}` +- `{{mergeData.propertyStateProvince}}` +- `{{mergeData.propertyPostalCode}}` +- `{{mergeData.propertyCountry}}` +- `{{mergeData.propertyAddressSingleLine}}` + +### Deficiency Repeat Block + +```handlebars +{{#each mergeData.deficiencies}} +| {{deficiencyNumber}} | {{description}} | {{resolution}} | +{{/each}} +``` + +## Recommended Letter Sections + +1. Header / logo block +2. Review metadata + - Case number + - Field review date + - Property address +3. Deficiency table + - Deficiency number + - Description + - Resolution +4. Closing / signature block + +## Notes + +- Keep `deficiencies` as a repeatable child collection, not a flattened text blob. +- If DocuSign CLM requires a REST callout payload, `AppraiserCaseDocGenService.buildDocGenRequestJson()` is a good source payload to hand to your integration layer. +- If your CLM tenant uses a different collection token syntax, map the same logical field names there. diff --git a/docs/DEPLOYMENT_AND_TESTING.md b/docs/DEPLOYMENT_AND_TESTING.md index 0a47b8c..13d789f 100644 --- a/docs/DEPLOYMENT_AND_TESTING.md +++ b/docs/DEPLOYMENT_AND_TESTING.md @@ -1,39 +1,11 @@ # Deployment & Testing — Appraiser Review Letter -## Implemented Salesforce Metadata -- Parent object: Appraiser_Case__c (label: Appraiser Case) -- Name field (auto number): Appraiser Case Number (AC-{00000}) -- Fields on Appraiser Case: - - Appraiser_Field_Review_Date__c (Date) - - Property_Address__c (Text 255) -- Child object for repeatable deficiencies: Appraiser_Case_Deficiency__c -- Fields on Appraiser Case Deficiency: - - Appraiser_Case__c (Master-Detail to Appraiser_Case__c) - - Deficiency_Number__c (Number) - - Description__c (Long Text Area) - - Resolution__c (Long Text Area) -- Permission set: Appraiser_Case_Access -- Apex Classes: - - AppraiserCasePayloadBuilder: Transforms Salesforce data to CLM merge payload - - AppraiserCasePayloadBuilderTest: Unit tests for payload builder - - CLMDocGenCallout: HTTP integration with DocuSign CLM API - ## Deployment Steps 1. Deploy custom objects & fields -2. Deploy Apex classes (included in manifest) -3. Configure Named Credentials for CLM API access -4. Configure Remote Site Settings for CLM instance -5. Map merge fields to object schema -6. Configure CLM template and connect API -7. Test with sample Appraiser Case records - -### Suggested CLI Deploy Commands -1. Authenticate to your org: - - sf org login web --alias appraiser-dev -2. Validate source deploy: - - sf project deploy validate --target-org appraiser-dev --manifest manifest/package.xml -3. Deploy metadata: - - sf project deploy start --target-org appraiser-dev --manifest manifest/package.xml +2. Copy updated template files into Salesforce docs directory +3. Map merge fields to object schema +4. Configure CLM template and connect API +5. Test with sample Appraisal and Deficiency objects --- @@ -43,39 +15,6 @@ - Test table rendering for arrays (DeficiencyList, ReviewerComments) - Document any failed merges or formatting gaps -## CLM Data Mapping Starter -- AppraiserCaseNumber -> Appraiser_Case__c.Name -- AppraiserFieldReviewDate -> Appraiser_Case__c.Appraiser_Field_Review_Date__c -- PropertyAddress -> Appraiser_Case__c.Property_Address__c -- DeficiencyList[] -> Appraiser_Case__c.Deficiencies__r - - deficiencyNumber -> Deficiency_Number__c - - description -> Description__c - - resolution -> Resolution__c - -## Smoke Test Execution -After deployment, sample test data was created: -- Appraiser Case: AC-00001 (a0wKW000007OIiCYAW) -- 3 related deficiency records verified - -### Test Payload Query (run in Apex Execute or Query Editor) -```soql -SELECT Id, Name, Appraiser_Field_Review_Date__c, Property_Address__c, - (SELECT Id, Deficiency_Number__c, Description__c, Resolution__c - FROM Deficiencies__r ORDER BY Deficiency_Number__c) -FROM Appraiser_Case__c -WHERE Id='a0wKW000007OIiCYAW' -``` - -### Test Payload Generation (Apex) -```apex -String caseId = 'a0wKW000007OIiCYAW'; -Map payload = AppraiserCasePayloadBuilder.buildPayload(caseId); -System.debug(JSON.serializePretty(payload)); -``` - -## CLM Doc Gen Integration -See [CLM_INTEGRATION.md](CLM_INTEGRATION.md) for complete setup and integration patterns. - --- _Last updated: 2026-02-26 13:26 PM_ diff --git a/docs/NEXT_STEPS_DOCGEN.md b/docs/NEXT_STEPS_DOCGEN.md new file mode 100644 index 0000000..8325e35 --- /dev/null +++ b/docs/NEXT_STEPS_DOCGEN.md @@ -0,0 +1,34 @@ +# Next Steps — DocuSign CLM Launch Path + +I added a placeholder Quick Action metadata file so there is an explicit place in the project for the document generation launch pattern. + +## Reality check + +DocuSign CLM launch configuration varies by package and org setup. Because of that, the action in this repo is a scaffold/placeholder, not a guaranteed final production action. + +## Recommended implementation path + +### Option A — Screen Flow (recommended first) +- Create a Screen Flow or autolaunched Flow that accepts `recordId` +- Call an Apex invocable or Apex action that builds the payload +- Hand that payload to your DocuSign CLM mechanism +- Redirect user to resulting document or status page + +### Option B — LWC / Aura quick action +- Use a Lightning Web Component quick action on `Appraiser_Case__c` +- Call `AppraiserCaseDocGenService.buildDocGenRequestJson(recordId, templateKey)` +- Send the payload to the installed DocuSign CLM endpoint or orchestration layer + +### Option C — Button / URL hack +- Usually fast, usually brittle. I don’t recommend it unless your CLM package explicitly documents it. + +## What to confirm in your org + +1. Exact DocuSign CLM package/API available in Salesforce +2. Whether generation is initiated by package component, Flow action, Apex callout, or named credential call +3. Template identifier format (`templateKey`, template Id, or external document key) +4. Returned artifact behavior (attach to record, email, save to CLM repository, etc.) + +## Good next move + +Once you know the exact DocuSign package artifact available in the org, I can wire the placeholder into a real Flow/LWC/Apex launch path. diff --git a/docs/SALESFORCE_SETUP.md b/docs/SALESFORCE_SETUP.md new file mode 100644 index 0000000..8fabbee --- /dev/null +++ b/docs/SALESFORCE_SETUP.md @@ -0,0 +1,85 @@ +# Salesforce Setup — Appraiser Case + DocuSign CLM + +## What was added + +### Custom object: `Appraiser_Case__c` +- Auto-number name field labeled **Appraiser Case Number** +- `Appraiser_Field_Review_Date__c` (Date) +- `Property_Street__c` (Text 255) +- `Property_City__c` (Text 80) +- `Property_State_Province__c` (Text 80) +- `Property_Postal_Code__c` (Text 20) +- `Property_Country__c` (Text 80) + +### Child custom object: `Appraiser_Deficiency__c` +- Master-detail to `Appraiser_Case__c` +- `Deficiency_Number__c` (Text 50) +- `Description__c` (Long Text Area) +- `Resolution__c` (Long Text Area) +- `Sort_Order__c` (Number) + +### Layouts +- Basic page layout for Appraiser Case +- Basic page layout for Appraiser Deficiency +- Related list on Appraiser Case for deficiencies +- Basic list view on Appraiser Case + +### Tabs and permissions +- Custom tabs for both objects +- Permission set: `Appraiser_Case_Admin` + +### Apex +- `AppraiserCaseDocGenService.cls` +- `AppraiserCaseDocGenServiceTest.cls` + +### Sample data +- Anonymous Apex script: `scripts/apex/createSampleAppraiserCase.apex` + +## Deploy + +From the project root: + +```bash +sf project deploy start --source-dir force-app +``` + +Or from elsewhere: + +```bash +sf project deploy start --source-dir /home/paulh/.openclaw/workspace/projects/salesforce-appraiser-review-letter/force-app +``` + +## Test Apex + +```bash +sf apex run test --tests AppraiserCaseDocGenServiceTest --result-format human +``` + +## Load sample data + +```bash +sf apex run --file scripts/apex/createSampleAppraiserCase.apex +``` + +## Assign permission set + +```bash +sf org assign permset --name Appraiser_Case_Admin +``` + +## Suggested next steps in Salesforce + +1. Deploy metadata. +2. Assign permission set. +3. Run the sample Apex script. +4. Open the `Appraiser Case` tab and verify the record + related deficiencies. +5. Validate the JSON payload in debug logs or by running the Apex methods directly. +6. Wire the DocuSign CLM launch path based on the exact package capability in your org. + +## About the quick action + +A placeholder quick action metadata file was added to mark the launch point, but DocuSign CLM launch mechanics vary by package/org. See `docs/NEXT_STEPS_DOCGEN.md` for the practical wiring options. + +## About “page layout” and “default setup” + +You said “just do default.” In Salesforce terms that means I created the baseline metadata so records can be created and edited in a normal Lightning UI without custom polish yet. diff --git a/docs/requirements.md b/docs/requirements.md index b14821d..56f89f4 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -42,39 +42,6 @@ Outline technical and functional requirements for Appraiser Review Letter templa - What is the authoritative object and field schema for merge? - Are custom field mappings needed for relationships (e.g. lookup fields)? -## Initial Authoritative Salesforce Schema -- Appraiser_Case__c (Appraiser Case) - - Name (label: Appraiser Case Number, AutoNumber) - - Appraiser_Field_Review_Date__c (Date) - - Property_Address__c (Text) -- Appraiser_Case_Deficiency__c (Appraiser Case Deficiency) - - Appraiser_Case__c (Master-Detail -> Appraiser_Case__c) - - Deficiency_Number__c (Number) - - Description__c (Long Text Area) - - Resolution__c (Long Text Area) - -This schema supports CLM array merges by iterating child deficiency records tied to one appraiser case. - -## CLM Integration - -### Payload Structure (from AppraiserCasePayloadBuilder) -The Apex class `AppraiserCasePayloadBuilder` transforms Salesforce records into CLM-ready JSON: -- AppraiserCaseNumber (string) -> Appraiser_Case__c.Name -- AppraiserFieldReviewDate (ISO date) -> Appraiser_Case__c.Appraiser_Field_Review_Date__c -- PropertyAddress (string) -> Appraiser_Case__c.Property_Address__c -- DeficiencyList (array of objects): - - deficiencyNumber (number) -> Appraiser_Case_Deficiency__c.Deficiency_Number__c - - description (string) -> Appraiser_Case_Deficiency__c.Description__c - - resolution (string) -> Appraiser_Case_Deficiency__c.Resolution__c - -### CLM API Integration (CLMDocGenCallout) -- HTTP POST to DocuSign CLM API with merge payload -- Named Credentials: Securely store CLM endpoint + OAuth token -- Remote Site Settings: Whitelist CLM instance domain -- Response includes document URL and ID for tracking - -See [CLM_INTEGRATION.md](CLM_INTEGRATION.md) for setup and usage patterns. - - --- - _Last updated: 2026-02-26 10:35 AM_ - _Work in progress: Integration and schema expansion next._ +--- +_Last updated: 2026-02-26 10:35 AM_ +_Work in progress: Integration and schema expansion next._ diff --git a/force-app/main/default/classes/AppraiserCaseDocGenService.cls b/force-app/main/default/classes/AppraiserCaseDocGenService.cls new file mode 100644 index 0000000..c64024d --- /dev/null +++ b/force-app/main/default/classes/AppraiserCaseDocGenService.cls @@ -0,0 +1,103 @@ +public with sharing class AppraiserCaseDocGenService { + public class DeficiencyDTO { + @AuraEnabled public String deficiencyNumber; + @AuraEnabled public String description; + @AuraEnabled public String resolution; + @AuraEnabled public Decimal sortOrder; + } + + public class AppraiserCasePayload { + @AuraEnabled public Id caseId; + @AuraEnabled public String appraiserCaseNumber; + @AuraEnabled public Date appraiserFieldReviewDate; + @AuraEnabled public String propertyStreet; + @AuraEnabled public String propertyCity; + @AuraEnabled public String propertyStateProvince; + @AuraEnabled public String propertyPostalCode; + @AuraEnabled public String propertyCountry; + @AuraEnabled public String propertyAddressSingleLine; + @AuraEnabled public List deficiencies; + } + + @AuraEnabled(cacheable=false) + public static String buildPayloadJson(Id appraiserCaseId) { + return JSON.serialize(buildPayload(appraiserCaseId)); + } + + public static AppraiserCasePayload buildPayload(Id appraiserCaseId) { + Appraiser_Case__c appraiserCase = [ + SELECT Id, + Name, + Appraiser_Field_Review_Date__c, + Property_Street__c, + Property_City__c, + Property_State_Province__c, + Property_Postal_Code__c, + Property_Country__c, + (SELECT Id, + Name, + Deficiency_Number__c, + Description__c, + Resolution__c, + Sort_Order__c + FROM Appraiser_Deficiencies__r + ORDER BY Sort_Order__c ASC, CreatedDate ASC) + FROM Appraiser_Case__c + WHERE Id = :appraiserCaseId + LIMIT 1 + ]; + + AppraiserCasePayload payload = new AppraiserCasePayload(); + payload.caseId = appraiserCase.Id; + payload.appraiserCaseNumber = appraiserCase.Name; + payload.appraiserFieldReviewDate = appraiserCase.Appraiser_Field_Review_Date__c; + payload.propertyStreet = appraiserCase.Property_Street__c; + payload.propertyCity = appraiserCase.Property_City__c; + payload.propertyStateProvince = appraiserCase.Property_State_Province__c; + payload.propertyPostalCode = appraiserCase.Property_Postal_Code__c; + payload.propertyCountry = appraiserCase.Property_Country__c; + payload.propertyAddressSingleLine = buildAddress(appraiserCase); + payload.deficiencies = new List(); + + for (Appraiser_Deficiency__c deficiency : appraiserCase.Appraiser_Deficiencies__r) { + DeficiencyDTO dto = new DeficiencyDTO(); + dto.deficiencyNumber = deficiency.Deficiency_Number__c; + dto.description = deficiency.Description__c; + dto.resolution = deficiency.Resolution__c; + dto.sortOrder = deficiency.Sort_Order__c; + payload.deficiencies.add(dto); + } + + return payload; + } + + private static String buildAddress(Appraiser_Case__c appraiserCase) { + List parts = new List(); + if (String.isNotBlank(appraiserCase.Property_Street__c)) parts.add(appraiserCase.Property_Street__c); + + List cityLine = new List(); + if (String.isNotBlank(appraiserCase.Property_City__c)) cityLine.add(appraiserCase.Property_City__c); + if (String.isNotBlank(appraiserCase.Property_State_Province__c)) cityLine.add(appraiserCase.Property_State_Province__c); + if (String.isNotBlank(appraiserCase.Property_Postal_Code__c)) cityLine.add(appraiserCase.Property_Postal_Code__c); + if (!cityLine.isEmpty()) parts.add(String.join(cityLine, ', ')); + + if (String.isNotBlank(appraiserCase.Property_Country__c)) parts.add(appraiserCase.Property_Country__c); + return String.join(parts, ' | '); + } + + @AuraEnabled(cacheable=false) + public static Map buildDocGenRequest(Id appraiserCaseId, String templateKey) { + AppraiserCasePayload payload = buildPayload(appraiserCaseId); + Map requestBody = new Map(); + requestBody.put('templateKey', templateKey); + requestBody.put('recordId', appraiserCaseId); + requestBody.put('sourceObject', 'Appraiser_Case__c'); + requestBody.put('mergeData', payload); + return requestBody; + } + + @AuraEnabled(cacheable=false) + public static String buildDocGenRequestJson(Id appraiserCaseId, String templateKey) { + return JSON.serialize(buildDocGenRequest(appraiserCaseId, templateKey)); + } +} diff --git a/force-app/main/default/classes/AppraiserCaseDocGenService.cls-meta.xml b/force-app/main/default/classes/AppraiserCaseDocGenService.cls-meta.xml new file mode 100644 index 0000000..5f399c3 --- /dev/null +++ b/force-app/main/default/classes/AppraiserCaseDocGenService.cls-meta.xml @@ -0,0 +1,5 @@ + + + 63.0 + Active + diff --git a/force-app/main/default/classes/AppraiserCaseDocGenServiceTest.cls b/force-app/main/default/classes/AppraiserCaseDocGenServiceTest.cls new file mode 100644 index 0000000..14bae40 --- /dev/null +++ b/force-app/main/default/classes/AppraiserCaseDocGenServiceTest.cls @@ -0,0 +1,36 @@ +@IsTest +private class AppraiserCaseDocGenServiceTest { + @IsTest + static void buildsPayloadAndRequestJson() { + Appraiser_Case__c appraiserCase = new Appraiser_Case__c( + Appraiser_Field_Review_Date__c = Date.newInstance(2026, 4, 1), + Property_Street__c = '123 Main St', + Property_City__c = 'Ottawa', + Property_State_Province__c = 'ON', + Property_Postal_Code__c = 'K1A 0A1', + Property_Country__c = 'Canada' + ); + insert appraiserCase; + + insert new Appraiser_Deficiency__c( + Name = 'Deficiency 1', + Appraiser_Case__c = appraiserCase.Id, + Deficiency_Number__c = '1', + Description__c = 'Missing comparable sale analysis', + Resolution__c = 'Provide updated comparable sales section', + Sort_Order__c = 1 + ); + + Test.startTest(); + AppraiserCaseDocGenService.AppraiserCasePayload payload = AppraiserCaseDocGenService.buildPayload(appraiserCase.Id); + String json = AppraiserCaseDocGenService.buildDocGenRequestJson(appraiserCase.Id, 'APPRAISER_REVIEW_LETTER'); + Test.stopTest(); + + System.assertEquals(appraiserCase.Id, payload.caseId); + System.assertEquals('Ottawa', payload.propertyCity); + System.assertEquals(1, payload.deficiencies.size()); + System.assertEquals('1', payload.deficiencies[0].deficiencyNumber); + System.assert(json.contains('APPRAISER_REVIEW_LETTER')); + System.assert(json.contains('Missing comparable sale analysis')); + } +} diff --git a/force-app/main/default/classes/AppraiserCaseDocGenServiceTest.cls-meta.xml b/force-app/main/default/classes/AppraiserCaseDocGenServiceTest.cls-meta.xml new file mode 100644 index 0000000..5f399c3 --- /dev/null +++ b/force-app/main/default/classes/AppraiserCaseDocGenServiceTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 63.0 + Active + diff --git a/force-app/main/default/layouts/Appraiser_Case__c-Appraiser Case Layout.layout-meta.xml b/force-app/main/default/layouts/Appraiser_Case__c-Appraiser Case Layout.layout-meta.xml new file mode 100644 index 0000000..8ef9c1d --- /dev/null +++ b/force-app/main/default/layouts/Appraiser_Case__c-Appraiser Case Layout.layout-meta.xml @@ -0,0 +1,80 @@ + + + + false + true + true + + + + Required + Name + + + Edit + Appraiser_Field_Review_Date__c + + + Edit + CreatedDate + + + + + Edit + LastModifiedDate + + + + + + false + true + true + + + + Edit + Property_Street__c + + + Edit + Property_City__c + + + Edit + Property_State_Province__c + + + + + Edit + Property_Postal_Code__c + + + Edit + Property_Country__c + + + + + + NAME + Deficiency_Number__c + Description__c + Resolution__c + Sort_Order__c + Appraiser_Deficiencies__r + + + SUBJECT + STATUS + DUE_DATE + OpenActivities + + false + true + false + false + false + diff --git a/force-app/main/default/layouts/Appraiser_Deficiency__c-Appraiser Deficiency Layout.layout-meta.xml b/force-app/main/default/layouts/Appraiser_Deficiency__c-Appraiser Deficiency Layout.layout-meta.xml new file mode 100644 index 0000000..b0354e9 --- /dev/null +++ b/force-app/main/default/layouts/Appraiser_Deficiency__c-Appraiser Deficiency Layout.layout-meta.xml @@ -0,0 +1,54 @@ + + + + false + true + true + + + + Required + Name + + + Required + Appraiser_Case__c + + + Edit + Deficiency_Number__c + + + + + Edit + Sort_Order__c + + + + + + false + true + true + + + + Edit + Description__c + + + + + Edit + Resolution__c + + + + + false + true + false + false + false + diff --git a/force-app/main/default/objects/Appraiser_Case__c/Appraiser_Case__c.object-meta.xml b/force-app/main/default/objects/Appraiser_Case__c/Appraiser_Case__c.object-meta.xml index e3f5201..5fef2c4 100644 --- a/force-app/main/default/objects/Appraiser_Case__c/Appraiser_Case__c.object-meta.xml +++ b/force-app/main/default/objects/Appraiser_Case__c/Appraiser_Case__c.object-meta.xml @@ -1,16 +1,38 @@ + + New + Default + + + Edit + Default + + + View + Default + + false + SYSTEM Deployed - Main record for appraiser review letter generation in CLM. true + true + false + true + false true true + true + true + Private - AC-{00000} + AC-{000000} AutoNumber Appraiser Cases + ReadWrite - \ No newline at end of file + Public + diff --git a/force-app/main/default/objects/Appraiser_Case__c/fields/Appraiser_Field_Review_Date__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Case__c/fields/Appraiser_Field_Review_Date__c.field-meta.xml index 828b779..1b5c9f4 100644 --- a/force-app/main/default/objects/Appraiser_Case__c/fields/Appraiser_Field_Review_Date__c.field-meta.xml +++ b/force-app/main/default/objects/Appraiser_Case__c/fields/Appraiser_Field_Review_Date__c.field-meta.xml @@ -1,9 +1,8 @@ Appraiser_Field_Review_Date__c - Date the appraiser field review was completed. false - false + true Date - \ No newline at end of file + diff --git a/force-app/main/default/objects/Appraiser_Case__c/fields/Property_City__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_City__c.field-meta.xml new file mode 100644 index 0000000..17e6d89 --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_City__c.field-meta.xml @@ -0,0 +1,9 @@ + + + Property_City__c + + 80 + false + true + Text + diff --git a/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Country__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Country__c.field-meta.xml new file mode 100644 index 0000000..1cfa1ae --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Country__c.field-meta.xml @@ -0,0 +1,9 @@ + + + Property_Country__c + + 80 + false + true + Text + diff --git a/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Postal_Code__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Postal_Code__c.field-meta.xml new file mode 100644 index 0000000..f839f8f --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Postal_Code__c.field-meta.xml @@ -0,0 +1,9 @@ + + + Property_Postal_Code__c + + 20 + false + true + Text + diff --git a/force-app/main/default/objects/Appraiser_Case__c/fields/Property_State_Province__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_State_Province__c.field-meta.xml new file mode 100644 index 0000000..daf5b17 --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_State_Province__c.field-meta.xml @@ -0,0 +1,9 @@ + + + Property_State_Province__c + + 80 + false + true + Text + diff --git a/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Street__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Street__c.field-meta.xml new file mode 100644 index 0000000..dbd2e34 --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Case__c/fields/Property_Street__c.field-meta.xml @@ -0,0 +1,9 @@ + + + Property_Street__c + + 255 + false + true + Text + diff --git a/force-app/main/default/objects/Appraiser_Case__c/listViews/All.listView-meta.xml b/force-app/main/default/objects/Appraiser_Case__c/listViews/All.listView-meta.xml new file mode 100644 index 0000000..fb3bdfb --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Case__c/listViews/All.listView-meta.xml @@ -0,0 +1,12 @@ + + + All + Name + Appraiser_Field_Review_Date__c + Property_Street__c + Property_City__c + Property_State_Province__c + LastModifiedDate + Everything + + diff --git a/force-app/main/default/objects/Appraiser_Deficiency__c/Appraiser_Deficiency__c.object-meta.xml b/force-app/main/default/objects/Appraiser_Deficiency__c/Appraiser_Deficiency__c.object-meta.xml new file mode 100644 index 0000000..fc6bf4a --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Deficiency__c/Appraiser_Deficiency__c.object-meta.xml @@ -0,0 +1,37 @@ + + + + New + Default + + + Edit + Default + + + View + Default + + false + SYSTEM + Deployed + false + true + false + true + false + true + true + true + true + ControlledByParent + + + + Text + + Appraiser Deficiencies + + ControlledByParent + Public + diff --git a/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Appraiser_Case__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Appraiser_Case__c.field-meta.xml new file mode 100644 index 0000000..3e36b13 --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Appraiser_Case__c.field-meta.xml @@ -0,0 +1,13 @@ + + + Appraiser_Case__c + + Appraiser_Case__c + Appraiser Deficiencies + Appraiser_Deficiencies + false + true + false + MasterDetail + false + diff --git a/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Deficiency_Number__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Deficiency_Number__c.field-meta.xml new file mode 100644 index 0000000..2466e96 --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Deficiency_Number__c.field-meta.xml @@ -0,0 +1,9 @@ + + + Deficiency_Number__c + + 50 + false + true + Text + diff --git a/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Description__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Description__c.field-meta.xml new file mode 100644 index 0000000..43e66b2 --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Description__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Description__c + + 32768 + false + true + LongTextArea + 5 + diff --git a/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Resolution__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Resolution__c.field-meta.xml new file mode 100644 index 0000000..9871dbb --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Resolution__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Resolution__c + + 32768 + false + true + LongTextArea + 5 + diff --git a/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Sort_Order__c.field-meta.xml b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Sort_Order__c.field-meta.xml new file mode 100644 index 0000000..5c2b705 --- /dev/null +++ b/force-app/main/default/objects/Appraiser_Deficiency__c/fields/Sort_Order__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Sort_Order__c + + 6 + false + 0 + true + Number + diff --git a/force-app/main/default/permissionsets/Appraiser_Case_Admin.permissionset-meta.xml b/force-app/main/default/permissionsets/Appraiser_Case_Admin.permissionset-meta.xml new file mode 100644 index 0000000..d19e192 --- /dev/null +++ b/force-app/main/default/permissionsets/Appraiser_Case_Admin.permissionset-meta.xml @@ -0,0 +1,87 @@ + + + Access to Appraiser Case and Appraiser Deficiency objects for setup and early testing. + + true + Appraiser_Case__c.Appraiser_Field_Review_Date__c + true + + + true + Appraiser_Case__c.Property_Street__c + true + + + true + Appraiser_Case__c.Property_City__c + true + + + true + Appraiser_Case__c.Property_State_Province__c + true + + + true + Appraiser_Case__c.Property_Postal_Code__c + true + + + true + Appraiser_Case__c.Property_Country__c + true + + + true + Appraiser_Deficiency__c.Appraiser_Case__c + true + + + true + Appraiser_Deficiency__c.Deficiency_Number__c + true + + + true + Appraiser_Deficiency__c.Description__c + true + + + true + Appraiser_Deficiency__c.Resolution__c + true + + + true + Appraiser_Deficiency__c.Sort_Order__c + true + + false + + + true + true + true + true + true + Appraiser_Case__c + true + + + true + true + true + true + true + Appraiser_Deficiency__c + true + + + Appraiser_Case__c + Visible + + + Appraiser_Deficiency__c + Visible + + diff --git a/force-app/main/default/quickActions/Appraiser_Case__c.Generate_Review_Letter.quickAction-meta.xml b/force-app/main/default/quickActions/Appraiser_Case__c.Generate_Review_Letter.quickAction-meta.xml new file mode 100644 index 0000000..cf0ab11 --- /dev/null +++ b/force-app/main/default/quickActions/Appraiser_Case__c.Generate_Review_Letter.quickAction-meta.xml @@ -0,0 +1,11 @@ + + + Placeholder action to launch Appraiser review letter generation flow or component. + 600 + + false + New + Appraiser_Case__c + Create + 800 + diff --git a/force-app/main/default/tabs/Appraiser_Case__c.tab-meta.xml b/force-app/main/default/tabs/Appraiser_Case__c.tab-meta.xml new file mode 100644 index 0000000..7c726a4 --- /dev/null +++ b/force-app/main/default/tabs/Appraiser_Case__c.tab-meta.xml @@ -0,0 +1,5 @@ + + + true + Custom67: Gears + diff --git a/force-app/main/default/tabs/Appraiser_Deficiency__c.tab-meta.xml b/force-app/main/default/tabs/Appraiser_Deficiency__c.tab-meta.xml new file mode 100644 index 0000000..d344eac --- /dev/null +++ b/force-app/main/default/tabs/Appraiser_Deficiency__c.tab-meta.xml @@ -0,0 +1,5 @@ + + + true + Custom18: Form + diff --git a/scripts/apex/createSampleAppraiserCase.apex b/scripts/apex/createSampleAppraiserCase.apex new file mode 100644 index 0000000..ce9462e --- /dev/null +++ b/scripts/apex/createSampleAppraiserCase.apex @@ -0,0 +1,32 @@ +Appraiser_Case__c appraiserCase = new Appraiser_Case__c( + Appraiser_Field_Review_Date__c = Date.today(), + Property_Street__c = '123 Main St', + Property_City__c = 'Ottawa', + Property_State_Province__c = 'ON', + Property_Postal_Code__c = 'K1A 0A1', + Property_Country__c = 'Canada' +); +insert appraiserCase; + +insert new List{ + new Appraiser_Deficiency__c( + Name = 'Deficiency 1', + Appraiser_Case__c = appraiserCase.Id, + Deficiency_Number__c = '1', + Description__c = 'Missing comparable sale analysis', + Resolution__c = 'Provide updated comparable sales section', + Sort_Order__c = 1 + ), + new Appraiser_Deficiency__c( + Name = 'Deficiency 2', + Appraiser_Case__c = appraiserCase.Id, + Deficiency_Number__c = '2', + Description__c = 'Exterior condition comments are too brief', + Resolution__c = 'Expand comments and attach photos', + Sort_Order__c = 2 + ) +}; + +System.debug('Created Appraiser Case Id: ' + appraiserCase.Id); +System.debug('Payload JSON: ' + AppraiserCaseDocGenService.buildPayloadJson(appraiserCase.Id)); +System.debug('Doc Gen JSON: ' + AppraiserCaseDocGenService.buildDocGenRequestJson(appraiserCase.Id, 'APPRAISER_REVIEW_LETTER')); diff --git a/sfdx-project.json b/sfdx-project.json index c893112..5abfd0e 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -8,5 +8,5 @@ "name": "salesforce-appraiser-review-letter", "namespace": "", "sfdcLoginUrl": "https://login.salesforce.com", - "sourceApiVersion": "62.0" -} \ No newline at end of file + "sourceApiVersion": "63.0" +}