I have WorkOrder, WorkOrderLineItem and Product2 object. In trigger when WorkOrder Status will become completed, i am checking if tht WorkOrder contains specific 2 type of products. If it is present i am trying to send email with vf template as pdf attachment.
The issue here is
- I am receiving 2 emails with both the templates as attached. Is there any way where i can get both the templates in one email.
- The templates don't have any data into them. Basically blank fields.
I tried diplaying those in vf page render as pdf, both are working fine. But when i am using it in trigger i am not getting any values.
VF Template
<messaging:emailTemplate subject="Test Subject" recipientType="Contact" relatedToType="WorkOrderLineItem">
<messaging:htmlEmailBody >
</messaging:htmlEmailBody>
<messaging:attachment renderAs="pdf">
<c:test1 wId="{!relatedTo.WorkOrderId}"/>
</messaging:attachment>
<messaging:attachment renderAs="pdf">
<c:test2 wId="{!relatedTo.WorkOrderId}"/>
</messaging:attachment>
</messaging:emailTemplate>
Trigger (after Update)
private void sendCertificate() {
Set<Id> wkId = new Set<Id>();
Set<String> pCode = new Set<String>{'A','B'};
EmailTemplate et=[SELECT Id, DeveloperName , body,IsActive FROM EmailTemplate WHERE DeveloperName = 'Test_Template'];
for (WorkOrder wo : lstNewWorkOrders) {
WorkOrder oldRec = mapOldWorkOrders.get(wo.Id);
if(oldRec.Status != wo.Status && (wo.Status == 'Completed')) {
wkId.add(wo.Id);
}
}
List<Messaging.SingleEmailMessage> lstsemail = new List<Messaging.SingleEmailMessage>();
for(WorkOrderLineItem wli : [SELECT Id, WorkOrderLineItem.WorkOrder.ContactId FROM WorkOrderLineItem WHERE WorkOrderId IN :wkId AND Product2.ProductCode IN :pCode]) {
Messaging.SingleEmailMessage semail = new Messaging.SingleEmailMessage();
semail.setTemplateId(et.Id);
semail.setTargetObjectId(wli.WorkOrder.ContactId);
semail.setWhatId(wli.WorkOrderId);
semail.setSenderDisplayName('Test Email');
semail.setUseSignature(false);
semail.setBccSender(false);
semail.setSaveAsActivity(false);
lstsemail.add(semail);
}
if (!lstsemail.isEmpty()) {
Messaging.SendEmailResult[] r = Messaging.sendEmail(lstsemail);
}
}
VF Component
<apex:component layout="none" access="global" controller="sanicerticontroller">
<apex:attribute name="wId" description="Record Id" type="id" assignTo="{!record_Id}"/>
<body>
<p style="font-size:20px;">{!accName}</p>
<p style="font-size:20px;">{!address}</p>
</body>
</apex:component>
VF COmponent Controller
public class sanicerticontroller {
public Integer day{get;set;}
public String month{get;set;}
public String address{get;set;}
public Integer year{get;set;}
public String accName{get;set;}
public List<WorkOrderLineItem> woOLI{get;set;}
public List<String> datewrap{get;set;}
public Id record_Id;
public Id getrecord_Id() {
return this.record_Id;
}
public void setrecord_Id(String argId){
woOLI = new List<WorkOrderLineItem>();
if(this.record_Id == null) {
record_Id = argId;
woOLI = [SELECT Id, Product2.ProductCode, WorkOrderId, WorkOrder.AccountId, WorkOrder.Account.Name, WorkOrder.Account.ShippingCountry, WorkOrder.Account.ShippingState,
WorkOrder.Account.ShippingStreet, WorkOrder.Account.ShippingPostalCode, WorkOrder.LastModifiedDate
FROM WorkOrderLineItem WHERE WorkOrderId =:record_Id];
system.debug('@@@@woOLI' + woOLI);
if(!woOLI.isEmpty() && woOLI !=null) {
for(WorkOrderLineItem jj: woOLI) {
accName = jj.WorkOrder.Account.Name;
address = jj.WorkOrder.Account.ShippingStreet + ' ' + jj.WorkOrder.Account.ShippingPostalCode;
datewrap.add(String.valueof(jj.WorkOrder.LastModifiedDate.Day()));
datewrap.add(String.valueof(jj.WorkOrder.LastModifiedDate.format('MMMM')));
datewrap.add(String.valueof( jj.WorkOrder.LastModifiedDate.Year()));
}
}
}else{
}
}
public sanicerticontroller() {
datewrap = new List<String>{'','',''};
}
}
if(!woOLI.isEmpty() && woOLI !=null) {
is the incorrect way to check for potentially empty list (null first, empty second). Queries always return a list, never a null list, and it is always okay to iterate over an empty list, so you don't need this if statement at all.