function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
DekorDekor 

Need a trigger to clear completed closed milestone

So after discovering that I needed to develop apex classes/triggers to mark my "completed" milestone as complete when a case is closed I've noticed an issue.  Basically if a previously closed case is reopened the "completed" milestone needs to be marked as active again as the SLA is technically live again. 

Can't think of a way to code a trigger to do this.  So basically it needs to clear the completed date/time field when cased close was previously true but now isn't.

Here is my apex class:
 
public class milestoneUtils {
    
    public static void completeMilestone(List<Id> caseIds, String milestoneName, DateTime complDate) {
      
    List<CaseMilestone> cmsToUpdate = [select Id, completionDate
                       from CaseMilestone cm
                       where caseId in :caseIds and cm.MilestoneType.Name=:milestoneName and completionDate = null limit 1];
    if (cmsToUpdate.isEmpty() == false){
      for (CaseMilestone cm : cmsToUpdate){
        cm.completionDate = complDate;
      }
      update cmsToUpdate;
    } // end if
  }
  }

Here is the trigger that marks the "closed" milestone as complete once case closed is true:
 
trigger completeResolutionTimeMilestone on Case (after update) {

    // Cannot be a portal user
    if (UserInfo.getUserType() == 'Standard'){
        DateTime completionDate = System.now();
            List<Id> updateCases = new List<Id>();
            for (Case c : Trigger.new){
                if (((c.isClosed == true))&&((c.SlaStartDate <= completionDate)&&(c.SlaExitDate == null)))
            updateCases.add(c.Id);
        }
    if (updateCases.isEmpty() == false)
        milestoneUtils.completeMilestone(updateCases, 'Closed Milestone', completionDate);
    }
}

Any thoughts on the best way to achieve this?
 
Best Answer chosen by Dekor
DekorDekor
Solved it myself.  Created a new apex class for handling the reset and also a trigger.

Here is the class:
 
public class milestoneUtils2 {
    
    public static void completeMilestone(List<Id> caseIds, String milestoneName, DateTime complDate) {
      
    List<CaseMilestone> cmsToUpdate = [select Id, completionDate
                       from CaseMilestone cm
                       where caseId in :caseIds and cm.MilestoneType.Name=:milestoneName and completionDate != null];
    if (cmsToUpdate.isEmpty() == false){
      for (CaseMilestone cm : cmsToUpdate){
        cm.completionDate = complDate;
      }
      update cmsToUpdate;
    } // end if
  }
  }

Here is my trigger:
 
trigger ResetClosedMilestone on Case (after update) {

    // Cannot be a portal user
    if (UserInfo.getUserType() == 'Standard'){
        DateTime completionDate = null;
            List<Id> updateCases = new List<Id>();
            for (Case c : Trigger.new){
                if ((c.isClosed != true))
            updateCases.add(c.Id);
        }
    if (updateCases.isEmpty() == false)
        milestoneUtils2.completeMilestone(updateCases, 'Closed Milestone', completionDate);
    }
}

 

All Answers

DekorDekor
Solved it myself.  Created a new apex class for handling the reset and also a trigger.

Here is the class:
 
public class milestoneUtils2 {
    
    public static void completeMilestone(List<Id> caseIds, String milestoneName, DateTime complDate) {
      
    List<CaseMilestone> cmsToUpdate = [select Id, completionDate
                       from CaseMilestone cm
                       where caseId in :caseIds and cm.MilestoneType.Name=:milestoneName and completionDate != null];
    if (cmsToUpdate.isEmpty() == false){
      for (CaseMilestone cm : cmsToUpdate){
        cm.completionDate = complDate;
      }
      update cmsToUpdate;
    } // end if
  }
  }

Here is my trigger:
 
trigger ResetClosedMilestone on Case (after update) {

    // Cannot be a portal user
    if (UserInfo.getUserType() == 'Standard'){
        DateTime completionDate = null;
            List<Id> updateCases = new List<Id>();
            for (Case c : Trigger.new){
                if ((c.isClosed != true))
            updateCases.add(c.Id);
        }
    if (updateCases.isEmpty() == false)
        milestoneUtils2.completeMilestone(updateCases, 'Closed Milestone', completionDate);
    }
}

 
This was selected as the best answer
Gabe Sanchez 7Gabe Sanchez 7
@Dekor Any ideas on how I could use this if I just want to close a milestone when a field is checked on the case? I assume I can use most of this, but don't really need to reset it.