You need to sign in to do that
Don't have an account?
Stumped on building wrapper class
I'm building a custom Visualforce PDF report that shows all the Opportunity Chatter that happened in the past week. I'd like to have the report broken out something similar to:
- Account 1
- Oppty 1
- Oppty Chatter Post 1a
- Oppty Chatter Post 1b
- Oppty 2
- Oppty Chatter Post 2a
- Oppty Chatter Post 2b
- Oppty Chatter Post 2c
- Oppty 1
- Account 2
- Oppty 3
- Oppty Chatter Post 3a
- Oppty Chatter post 3b
- Oppty 3
My current code is able to retrieve the Opportunity Chatter Posts easily enough -- but I'm stumped on figuring out how to modify it so that the chatter posts are grouped by Account, as in the example above.
Here's my current VF page:
<apex:page controller="ReportOpptyChatter" renderAs="PDF" showHeader="true" sidebar="false"> <!-- Summary List of all accounts that had Opportunity Chatter this Week --> <table> <tr><td>Opportunity Chatter found for the following accounts:</td></tr> <tr><td> <apex:repeat value="{!Accounts}" var="a" > <li><apex:outputText value=" {!a.Name}" /> </li> </apex:repeat> </td></tr> </table> <p></p> <!-- Opportunity Chatter --> <table> <apex:repeat value="{!ChatterUpdate}" var="update" > <tr valign="top"><td><b>Project:</b></td><td><apex:outputField value="{!update.ParentId}" /></td><td align="right"><i>{!update.CreatedBy.Firstname} {!update.CreatedBy.Lastname}</i></td></tr> <tr valign="top"><td></td><td colspan="2"><apex:outputText value="{!update.Body}" escape="false" /></td></tr> <tr><td></td></tr> </apex:repeat> </table> </apex:page>
Here's my current controller:
public class ReportOpptyChatter { // List of Opportunity Chatter Posts from Last 7 Days List<OpportunityFeed> opptyChatter= [SELECT Id, Body, ParentId, CreatedDate, CreatedBy.FirstName, CreatedBy.LastName FROM OpportunityFeed WHERE CreatedDate = LAST_N_DAYS:7 ORDER BY CreatedDate]; // Parent accounts of Oppty Chatter public List<Account> getAccounts() { Set<Id> opptyIdSet = new Set<Id>(); // Which Opportunities had Chatter this past week? Set<Id> acctIdSet = new Set<Id>(); // Which accounts are those opptys related to? // Interate through the Oppty Chatter to find a list of unique Opptys for (OpportunityFeed i : opptyChatter) { opptyIdSet.add(i.ParentId); } List<Opportunity> opptyList = [SELECT Id, Name, AccountId FROM Opportunity WHERE Id IN :opptyIdSet]; // Itegrate through the Opptys to get a list of unique Accounts for (Opportunity o : opptyList) { acctIdSet.add(o.AccountId); } List<Account> accountList = [SELECT Id, Name FROM Account WHERE Id IN :acctIdSet ORDER BY Name]; return accountList; } public List<OpportunityFeed> getChatterUpdate() { return opptyChatter; } }
I suspect I probably need a wrapper class, so my VF page and modify the VF page to use nested <apex:repeats> but am unsure how to tackle that.
All Answers
The Apex works brilliantly. I return a Map of AccountWrapper objects back to the Visualforce page. How do I "unwind" that to display the values of each map entry? In this VF page, I'm just going for the Account Names in the outer map (start small, right?), but I'll eventually want to iterate through the inner map.
To give an idea of what the output (and the values of the map), this is the current output:
001P000001ThJxAIAV
AccountWrapper:[accRecord=Account:{Id=001P000001ThJxAIAV, Name=Stark Enterprises}, oppWraps=(OpportunityWrapper:[chatPosts=(OpportunityFeed:{Id=0D5P000000L4sxxKAB, Body=<p>This is a test Chatter Post for Acct: Stark Enterprises, Oppty: Ironman Prototype</p>, ParentId=006P0000009gJTtIAM, CreatedDate=2019-11-14 19:41:43, CreatedById=005f2000008ucvaAAA, IsRichText=true}), oppRecord=Opportunity:{Id=006P0000009gJTtIAM, Name=Ironman Prototype, AccountId=001P000001ThJxAIAV, RecordTypeId=012f20000006h63AAA}])]
001P000001ThLFUIA3
AccountWrapper:[accRecord=Account:{Id=001P000001ThLFUIA3, Name=Eagles}, oppWraps=(OpportunityWrapper:[chatPosts=(OpportunityFeed:{Id=0D5P000000L4t6uKAB, Body=<p>On a dark desert highway</p>, ParentId=006P0000009gKxGIAU, CreatedDate=2019-11-14 20:08:13, CreatedById=005f2000008ucvaAAA, IsRichText=true}), oppRecord=Opportunity:{Id=006P0000009gKxGIAU, Name=Hotel California, AccountId=001P000001ThLFUIA3, RecordTypeId=012f20000006h63AAA}], OpportunityWrapper:[chatPosts=(OpportunityFeed:{Id=0D5P000000L4t7iKAB, Body=<p>Well I'm runnin' down the road tryin' to loosen my load</p>, ParentId=006P0000009gL59IAE, CreatedDate=2019-11-14 20:10:06, CreatedById=005f2000008ucvaAAA, IsRichText=true}), oppRecord=Opportunity:{Id=006P0000009gL59IAE, Name=Take It Easy, AccountId=001P000001ThLFUIA3, RecordTypeId=012f20000006h63AAA}], OpportunityWrapper:[chatPosts=(OpportunityFeed:{Id=0D5P000000L4tA3KAJ, Body=<p>Look at us baby, up all night</p>, ParentId=006P0000009gLVwIAM, CreatedDate=2019-11-14 20:15:44, CreatedById=005f2000008ucvaAAA, IsRichText=true}), oppRecord=Opportunity:{Id=006P0000009gLVwIAM, Name=I Cant Tell You Why, AccountId=001P000001ThLFUIA3, RecordTypeId=012f20000006h63AAA}])]
Then the VFP will be something like this.