5

Long time reader first question :)

I have a before insert trigger on EmailMessage, but I also need to update the Parent Case - which works fine. I believe I have to use before insert as I am updating the TextBody/HTMLBody of the EmailMessage and it cannot be updated once saved. However I have not been able to test the Parent Case update, the EmailMessage tests are fine.

Now I read in this situation it's best to use an after insert trigger for the Parent updates but I can't do this completely because of the EmailMessage limitation. So it is possible to cover the Parent Case update in the test methods (currently on 85%), or have I missed something in terms of my trigger/class structure?

Thanks in advance.

Further scenario info: We want to mask/replace certain details on an inbound email, then also mark the Parent Case so we can report on when this has happened and also make it obvious to the user on the Case record itself.

Class below (hope I've used the correct tag for readability). I've added comments for the lines I can't cover in my existing test. When querying the Case these updates are not showing (although they are applied in out of the test method).

public class MaskClass{   

    Public Static EmailMask (List<EmailMessage> newEm){

        Set<String> emPId = new Set<String>();
        String mask = System.Label.Mask;
        String regEx = System.Label.Pattern;
        String MaskedText;
        Boolean EmailIncoming;


        for(EmailMessage emx:newEm){
            If(emx.TextBody !=null){

            pattern p = Pattern.compile(regEx);
            matcher m = p.matcher(emx.TextBody);             

            //If pattern matched replace match with mask
            if(m.find()){
                system.debug('**EmailMask**: Card Details Detected in Email');
                emx.TextBody = m.replaceAll(mask);
        emx.HtmlBody = m.replaceAll(mask);             
                System.debug('**EmailMask ParentId: '+emx.ParentId);
                MaskedText = emx.TextBody;
                EmIncoming = emx.Incoming;
                emPId.add(emx.ParentId);

            }
            else{
                system.debug('**EmailMask**: No Detection');
            }
        System.debug('**EmailMask** Masked Text: '+MaskedText);    
        }
            else{
                system.debug('**EmailMask TextBody is Null** '+emx.Subject);
            }           
        }
        //Flag Parent Case Record
        If(emPid != null && EmIncoming == True){
    List<Case> cx = [SELECT Id, CaseNumber FROM Case WHERE Id IN :emPId];    //Not covered   
        for(Case cxUpdate:cx){ //Not covered
            cxUpdate.Flag__c=True; //Not covered
            system.debug('**EmailMask Debug** CaseNumber: '+cxUpdate.CaseNumber);
            update cxUpdate; //Not covered
          }            
        }
    }
    public static void ParentCaseMask (List<Case> newCase){
        String mask = System.Label.Mask;
        String regEx = System.Label.Pattern;

        for(Case cxUpdate:newCase){
            If(cxUpdate.Description != null){
                pattern pc = pattern.compile(regEx);
                matcher mc = pc.matcher(cxUpdate.Description);
                If(mc.find()){
                    system.debug('**CaseMask**: Detected in Case Description');                            
                    cxUpdate.Description = mc.replaceAll(mask);
                    cxUpdate.Flag__c=True;
                    system.debug('**CaseMask: '+cxUpdate.Flag__c);
                }
                Else{
                    system.debug('**CaseMask*: No match in Case Description');
                }                
            }
            Else{
                    system.debug('**CaseMask**: Case Description is Null');
                }            
          }
    }
}
  • I've added the class to my original post. It's the Case loop where the updates don't get applied within the test method, but do in real use. – Girbot Jun 13 '14 at 11:18
0

If an EmailMessage is inserted, any before insert and after insert trigger on EmailMessage will execute. The after insert trigger can do a SOQL query on the parent Case and then update that Case.

//  after insert trigger snippet; assume variable theMask contains a unique mask string
Set<ID> csIdUpdSet = new Set<ID>();
for (EmailMessage em : Trigger.new) 
  if (em.htmlbody.contains(theMask) || em.textBody.contains(theMask))
     csIdUpdSet.add(em.parentId);

List<Case> csUpdList = [select id, has_mask_event__c from Case where id IN :csIdUpdSet]
for (Case cs : csUpdList)
   cs.has_mask_event__c = true;
update csUpdList;

// end snippet
  • Hi, so are you suggesting changing the trigger to after insert? When I tried this the EmailMessage was read only and I couldn't update the TextBody or EmailBody. – Girbot Jun 13 '14 at 11:19
  • 2
    No - do the masking in the before insert and the Case update in the after insert – cropredy Jun 13 '14 at 18:23
  • Ah OK I think I understand. A new email message comes in (regardless if it creating a new case or associated to an existing case) an email message before insert trigger masks the email message and an email message after insert trigger performs the case update action. Didn't think of splitting it like that, I'll have a go when I'm next in the office. – Girbot Jun 13 '14 at 21:33
  • 1
    I generally follow two simple rules: Validations and updating records inside Trigger.new are always "before event", and any type of DML for related parent or child records, or any other records, in an "after event". There are, however, exceptions to the rule. – sfdcfox Jul 13 '14 at 19:06
  • 1
    N.B. The Force.com Enterprise Architecture domain layer (aka trigger pattern) does Validation in after triggers. The justification tends to be mostly for ISVs protecting data integrity against an environment where others also have triggers on the same object. @sfdcfox – cropredy May 21 '18 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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