0

I am trying to run an email template from the Contract object, but in the email (or an attached PDF) print a list of related cases and specified fields for the cases. I've managed to do this successfully on a visualforce page, but trying to use the same idea in an email template has not worked out. It's as though the query is not receiving the contract Id but I cannot figure out how to pass it so it works. Maybe I'm barking up the wrong tree though.

Visualforce Email Template:

<messaging:emailTemplate recipientType="User" 
    relatedToType="Contract"
    subject="Test {!relatedTo.ContractNumber}">
    
<messaging:attachment renderAs="PDF" filename="claims-list.pdf">
<html>
    <body>
        <div>
            <h3>CLAIMS</h3>
            
            <c:StatementofClaims Contract="{!relatedTo.Id}" policyref="{!relatedTo.Id}" />
            
            <table>
            
            </table>
        </div>
        <div>
            <p></p>
        </div>
    </body>
</html>
</messaging:attachment>    

<messaging:plainTextEmailBody >
test mail

{!relatedTo.Id}


<c:StatementofClaims policyref="{!relatedTo.Id}" />
</messaging:plainTextEmailBody>
</messaging:emailTemplate>

Visualforce Component:

<apex:component layout="none" access="global" controller="ClaimsListController2">
<apex:attribute name="Contract" description="Statement of Claims" type="Contract" />
<apex:attribute name="policyref" description="" type="id" assignTo="{!policyId}" />
<html>
    <style>
        .claimRecordsTable {
            border: 1px solid black;
        }
        .claimRecordTableCells {
            border-top: 1px solid black;
            border-bottom: 1px solid black;
            border-left: 1px solid black;
        }
    </style>
    <body>
        <div>
            
            {!testReturn2}
            <p><apex:outputText ><apex:param value="{!testReturn2}" /></apex:outputText></p>
            <table id="claimTableInfo" width="100%" rowClasses="odd,even" styleClass="claimRecordsTable" border="solid" cellpadding="5px">
                <thead>
                    <tr>
                        <th style="text-align: left; border-collapse:collapse; width:20%;">Claim No.</th>
                        <th style="text-align: left; border-collapse:collapse; width:20%;">Date Notified</th>
                        <th style="text-align: left; border-collapse:collapse; width:20%;">Repaired or Replaced</th>
                        <th style="text-align: left; border-collapse:collapse; width:20%;">Amount if Replaced</th>
                        <th style="text-align: left; border-collapse:collapse; width:20%;">Claim Status</th>
                    </tr>
                </thead>
                <tbody>
                    <apex:repeat value="{!claims}" var="claim">
                        <tr>
                            <td class="claimRecordsTable" width="170">{!claim.CaseNumber}</td>
                            <td class="claimRecordsTable" width="170"><apex:outputText value="{0,Date,dd/MM/yy}"><apex:param value="{!claim.Claim_Form_Recevied_Date__c}" /></apex:outputText></td>
                            <td class="claimRecordsTable" width="170">{!claim.Reason}</td>
                            <td class="claimRecordsTable" width="170">{!claim.Claim_Cost__c}</td>
                            <td class="claimRecordsTable" width="170">{!claim.status}</td>
                        </tr>
                    </apex:repeat>
                </tbody>
            </table>
            
            <table>
            
            </table>
        </div>
        <div>
            {!policyId}
            {!testReturn}
            <p><apex:outputText ><apex:param value="{!testReturn}" /></apex:outputText></p>
        </div>
    </body>
</html>
</apex:component>

Controller:

public class ClaimsListController2 {
    
    public Id policyId {get;set {loadList();}}
    public List<Case> claims{get;set;}
    public Contract policy {get;set;}
    public String testReturn {get;set;}
    public String testReturn2 {get;set;}
    
    public ClaimsListController2() {
        
        // this.policy = (Contract)stdController.getRecord();
        claims = [SELECT Id, CaseNumber, recordTypeId, Claim_Form_Recevied_Date__c, Policy__c, Reason, Claim_Cost__c, Status FROM Case
                  WHERE RecordTypeId='012b0000000Kr2VAAS' AND Policy__r.Id= :policyId];
        
        
        testReturn2 = 'constructor has run';
    }
    
    public void loadList() {
        claims = [SELECT Id, CaseNumber, recordTypeId, Claim_Form_Recevied_Date__c, Policy__c, Reason, Claim_Cost__c, Status FROM Case
                  WHERE RecordTypeId='012b0000000Kr2VAAS' AND Policy__c= :policyId];
        testReturn = 'loadList has run';

    }
    
}

As you can probably see in the controller, I tried also calling the query separately to the constructor, but neither really worked until I take out the limitation of the policy.

1 Answer 1

1

To start with

<c:StatementofClaims Contract="{!relatedTo.Id}" policyref="{!relatedTo.Id}" />
        

doesn't agree with the attribute definitions in the component:

 <apex:attribute name="Contract" description="Statement of Claims" type="Contract" />
 <apex:attribute name="policyref" description="" type="id" assignTo="{!policyId}" />

You are passing for attribute Contract the value of {!relatedTo.Id} which is of type ID but the component is expecting type Contract

You need to do:

<c:StatementofClaims Contract="{!relatedTo}" policyref="{!relatedTo.Id}" />

But, you've made this harder than it has to be:

The preferred pattern is as follows:

<c:StatementofClaims  policyref="{!relatedTo.Id}" />

The VF component has a single attribute

<apex:component layout="none" access="global" controller="ClaimsListController2">
<apex:attribute name="policyref" description="" type="id" assignTo="{!policyId}" />
<html>
...

And the VF component controller looks like this

public class ClaimsListController2 {
    
    public Id policyId {get;set;}
    public List<Case> claims{

      get {
         if (claims == null) {
            claims = this.policyId == null
               ? new List<Case>()
               : [SELECT Id, CaseNumber, ...
                   FROM Case WHERE
                        RecordtypeId = '012b0000000Kr2VAAS' AND
                        Policy__c = :this.policyId];
         return claims;
      } private set;
    }
    
    public ClaimsListController2() {}

}

Now, you should also avoid hardcoding recordtypeIds in Apex - use the Schema.DescribeSObjectResult.getRecordTypeInfosByDeveloperName(). See example

1
  • Thank you for the help! I am fairly new to Apex and had been racking my brain to figure out why it was not working, trying all sorts (resulting in the spaghetti code above). I had not thought to do the query in the variable for the controller. I am now getting results. Thanks again!
    – Claire
    Mar 23, 2022 at 1:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.