0

Can any one help me out with this scenario? Any help is very much appreciated. We get cases created VIA Email. When there is a case created with the same subject line, it should be identified as a duplicate case and get closed by adding its case comment to the previous case.

Wrote a trigger which just creates a case, but it does not identifies the duplicate cases.

Here is a code :

trigger CaseTrigger123 on Case (after insert) {     
    Set<String> caseSubs = new Set<String>();       
    Set<Id> caseIds = new Set<Id>();       
    List<Case> listCases = new List<Case>();       
    List<CaseComment> listCaseComm = new List<CaseComment>();        
    List<CaseComment> listInsertCaseComm = new List<CaseComment>();       
    Map<String, Id> mapCasSubId = new Map<String, Id>();        
    Map<Id, CaseComment> mapCaseIdCasComm = new Map<Id, CaseComment>();        
    Map<String,id> caseMap = new Map<String,id>();       
    Map<id,String> caseMap1 = new Map<id,String>();       
    Map<id,String> caseMap2 = new Map<id,String>();      
    Map<id,String> caseMap3 = new Map<id,String>();        
    Set<String> subjSet = new Set<String>();       
    List<CaseComment> updateLstCaseComment = new List<CaseComment>();       
    set<id> updateCasedIDs = new Set<Id>();        
    List<case> closeCasesCases = new List<case>();       
    set<String> subjCaseUpdated = new Set<String>();

    for(Case cas : trigger.new) {            
        //caseMap1.put(id)            
        caseIds.add(cas.id);           
        system.debug('Case ID++'+caseIds);       
    }

    if(!caseIds.IsEmpty()){          
        //for newly added case          
        for(case c : [SELECT  Id,Subject,Description,
            (SELECT Id, CommentBody,parentId from CaseComments) 
            from case where id IN:caseIds] ){               
            for(CaseComment c1 : c.CaseComments){                    
                caseMap.put(c.Subject,c1.CommentBody);                    
                caseMap2.put(c.Subject,c1.id);                    
                caseMap3.put(c.Subject,c1.parentId);                                                        
            }                        
        }

        for(String s : caseMap.Keyset()){               
            subjSet.add(s);            
        }           

        //for already existed cases in the data base           
        for(case ca : [SELECT  Id,Subject,Description,
            (SELECT Id, CommentBody,parentId from CaseComments) 
            from case where Subject IN:subjSet ]){                
                if(!caseIds.contains(ca.id)){                    
                    for(CaseComment cc : ca.CaseComments){                            
                        cc.CommentBody = cc.CommentBody + caseMap.get(ca.Subject);
                    }

                    for(case c:closeCasesCases){                   
                        c.status = 'Closed';                   
                        update c;               
                    }            
                }
            }
        }
}

Editor's note: Removed commented out code which may or may not be needed.

Thanks in Advance.

  • 3
    Hi @nikkey. The first thing you should try do is formatting your code into something that is readable. Its nearly impossible for someone else to understand what the code is doing in its current format. Thanks – BarCotter Sep 24 '14 at 9:53
1

I'm struggling to read the code, but here's a possible solution that would do the dupe check:

trigger Case_AfterInsert (after insert)
{
  Map<String, List<Case>> subjectToCaseList = new Map<String, List<Case>>();
  Map<String, List<CaseComment> subjectToComments = new Map<String, List<CaseComment>>();


  List<Case> toUpdate = new List<Case>();
  List<CaseComment> toReparent = new List<CaseComment>();

  for(Case c : trigger.new)
  {       
    if(subjectToCaseList.get(c.Subject) != null)
    {
      subjectToCaseList.get(c.Subject).add(c);
    }
    else
    {
      subjectToCaseList.put(c.Subject, new List<Case> {c});
      subjectToComments.put(c.Subject, new List<CaseComment>());
    }
  }

  // this will grab all comments, even those that don't need to be reparented.
  // there's definitely room for some optimisation in this code ;)
  for(CaseComment cc : [select Id, Parent.Subject, ParentId from CaseComment
                                      where Parent.Subject in : subjectToCaseList.keySet()])
  {
    subjectToComments.get(cc.Parent.Subject).add(cc);
  }

  // this query will return new and old cases!
  for(Case existingCase : [select Id, Subject from Case where Subject in : subjectToCase.keySet()])
  {
    // old cases should receive the new comments
    if(!trigger.newMap.keySet().contains(existingCase.Id))
    {
      for(CaseComment cc : subjectToComments.get(existingCase.subject))
      {
        cc.ParentId = existingCase.id;
        toReparent.add(cc);
      }
    }

    // only new cases are in this map so close them
    for(Case newCase : subjectToCaseList.get(existingCase.Subject))
    { 
      toUpdate.add(new Case(Id = newCase.Id, Status = 'Closed'));
    }
  }

  update toUpdate;
  update toReparent;
}

As the comment suggests, this only matches on subject. You'd probably want to check a few other things like who the sender is, whether the old case is closed etc.. Hopefully this gives you some ideas about how to structure the code though.

I'm pretty sure the logic is right but this has not been compiled, let alone executed and tested, so there could be a few bugs (big or small).

On a side note, having variables with similar names like caseMap, caseMap1, caseMap2 is always going to be quite confusing and could easily result in the developer making logic errors.

In this code:

caseMap.put(c.Subject,c1.CommentBody);                    
caseMap2.put(c.Subject,c1.id);                    
caseMap3.put(c.Subject,c1.parentId); 

The maps would be better named subjectToComment, subjectToId and subjectToParentId respectively, as then you can easily tell what should go in them; which counts doubly so for anyone else trying to read/maintain the code in the future.

Note I wrote this code straight in the editor here, so it's likely to have a couple of syntax errors ;)

|improve this answer|||||
  • 1
    You are missing the scenario where two duplicate cases are added in a single batch of Cases. You could change Map<String, Case> subjectToCase to be Map<String, List<Case>> subjectToCases so to handle multiple cases with the same subject in the batch. – BarCotter Sep 24 '14 at 10:22
  • 1
    Good call! :) Will add that now! – Matt Lacey Sep 24 '14 at 10:29
  • @BarCotter,@LaceySnr :Thanks for your reply ,But my scenario is the duplicate case should get saved first and once identified it as a duplicate then it should get closed automatically ,by adding its case comments to the previous which is open case(First case).Using AFTER EVENTS and this cases are created via Email. – nikkey Sep 24 '14 at 10:52
  • @nikkey Made some changes so I tihnk it's along the right lines for your use case now. If it's not, I might have to revisit tomorrow, my brain is a tad fried atm. – Matt Lacey Sep 24 '14 at 11:14
  • 1
    I can't do any more work on this @nikkey, hope you understand but SFSE isn't a place to get work done for you, I only did as much as I did as I thought it was the easiest way to show you some ideas. But for me to write things so a spec would be unfair on clients given that we charge for this kind of thing. – Matt Lacey Sep 25 '14 at 9:05

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.