So, a month or two ago, our implementation partner wrote a trigger to keep a field on the Opportunity called "Related Application Record" populated with a Lookup to the Admission Application record it most closely corresponded to.
Those Admission-Application "rake tines" are actually miniature rakes in and of themselves. They have "Checklist Records" hanging off of them, indicating what documents a Contact has turned in along with their application form.
We wanted to put a Related List at the bottom of the Opportunity page layout to show any "Checklist Records" from the Admission Application record indicated in "Related Application Record."
Only SalesForce wouldn't let us.
So I wrote my first VisualForce page, which allowed me to put a component into the Opportunity page layout that looks close enough to a Related List.
So here's the code
(Please let me know if you have any ideas for making "chkls" in my wrapper class private - it seems like bad design to leave it public. Please also let me know if you see any design or security flaws in this code. I'm still a beginner and appreciate pro tips.)
(Note: Please let me know if my code doesn't seem to flow. I did some manual Find&Replace to obfuscate my org's internal structure just a wee bit, and I might have missed something.)
The VisualForce Page
<apex:page standardController="Opportunity" extensions="OppApplicationChecklistClass"> <apex:pageBlock > <apex:pageBlockTable value="{!app_chkl}" var="a" id="table"> <apex:column value="{!a.chkls.Requirement__c}"></apex:column> <apex:column value="{!a.chkls.Received_Date__c}"></apex:column> apex:column value="{!a.chkls.Comment__c}"></apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:page>
The Apex Class (A "Standard Opportunity Controller Extension")
(Ignore the close-tags in line 52 - either Blogger or my new code formatter doesn't seem to like Apex collections and insists on closing them as if they were HTML.
public with sharing class OppApplicationChecklistClass { // Attributes possessed by all objects made out of this class private final Opportunity opp; private ListchklRecords; // Constructor for this class public OppApplicationChecklistClass(ApexPages.StandardController stdController) { this.opp = (Opportunity)stdController.getRecord(); } // Methods possessed by all objects made out of this class public Opportunity getOpportunity() { return opp; } public List getchecklist() { if (chklRecords == null) { chklRecords = new List (); List tempQueryResult = [SELECT (SELECT Id FROM Opportunities__r), (SELECT Applicant_Last_Name__c, Requirement__c, Received_Date__c, Comment__c FROM Checklist__r) FROM ApplicationRecord__c WHERE Id IN (SELECT Related_Application_Record__c FROM Opportunity WHERE Id = :opp.id) AND Id IN (SELECT RelatedApplication__c FROM Checklist__c)]; if(tempQueryResult.size() == 1) { for (Checklist__c a : (tempQueryResult.get(0)).Checklist__r) { chklRecords.add(new wChkl(a)); } } } return chklRecords; } // Another attribute possessed by all objects made out of this class... // ...the wrapper class wChkl surrounding a single Checklist__c object public with sharing class wChkl { public Checklist__c chkls {get; set;} // I don't seem to be able to find a way to privatize this. public wChkl(Checklist__c a) { chkls = a; } } }
My awful test class
(I swear I mean to come back to it and make it meaningful...)
@isTest private class OppApplicationChecklistTest { static testMethod void test() { Opportunity setupOpp = new Opportunity(); ApexPages.StandardController sc = new ApexPages.standardController(setupOpp); // Create an instance of the page controller to test OppApplicationChecklistHandler testPageCon = new OppApplicationChecklistHandler(sc); // Try calling methods/properties of the controller in all possible scenarios to get the best coverage. Opportunity testOpp = testPageCon.getOpportunity(); // OppApplicationChecklistHandler works with a blank Opportunity if it can't find a real one from the page it's on. System.assertEquals(null, testOpp.Id); // Working with a blank Opportunity, the list of Checklist records would also be blank. System.assertEquals(0, (testPageCon.getchecklist()).size()); } }