Last active
April 1, 2019 00:14
-
-
Save douglascayers/f72962c84314f78fac989a3abc8d77b9 to your computer and use it in GitHub Desktop.
Simple batchable to compute the number of hours a case was open, taking into consideration BusinessHours. Can be scheduled to run hourly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CaseOpenBizHoursBatchable implements Database.Batchable<SObject>, Database.Stateful { | |
private ID businessHoursId { get; set; } | |
public CaseOpenBizHoursBatchable( ID businessHoursId ) { | |
this.businessHoursId = businessHoursId; | |
} | |
public Database.QueryLocator start( Database.BatchableContext context ) { | |
// Idea behind this query is to get all open cases or | |
// cases that were closed yesterday or today. We consider records closed | |
// yesterday or today to ensure the scheduled job doesn't miss updating a case | |
// that may have closed in between job runs, particularly between job runs that | |
// span 11pm yesterday through midnight into next day. | |
// Understandably, this precaution also means any cases closed yesterday or today | |
// continously get queried until we move beyond that window. | |
return Database.getQueryLocator([ | |
SELECT | |
id, createdDate, closedDate, Case_Open_Hours__c | |
FROM | |
Case | |
WHERE | |
isClosed = false | |
OR | |
closedDate = LAST_N_DAYS:1 | |
ORDER BY | |
accountId | |
]); | |
} | |
public void execute( Database.BatchableContext context, List<Case> cases ) { | |
List<Case> casesToUpdate = new List<Case>(); | |
for ( Case cs : cases ) { | |
DateTime now = DateTime.now(); | |
DateTime startDate = cs.createdDate; | |
DateTime endDate = ( cs.closedDate == null ? now : cs.closedDate ); | |
// compute difference between the two dates taking into consideration | |
// working hours, weekends, holidays, etc. of the BusinessHours record | |
Long milliseconds = BusinessHours.diff( this.businessHoursId, startDate, endDate ); | |
// convert milliseconds into hours | |
Long hours = ( milliseconds / 1000 / 60 / 60 ); | |
// don't unecessarily update a case if no new information here | |
if ( cs.Case_Open_Hours__c != hours ) { | |
// use a new case sobject variable so that precisely only | |
// the fields we want to set are populated | |
casesToUpdate.add( new Case( | |
id = cs.id, | |
Case_Open_Hours__c = hours | |
)); | |
} | |
} | |
if ( casesToUpdate.size() > 0 ) { | |
// optimistically update as many of the cases as possible | |
// by not rolling back all cases if one fails to update | |
Database.DMLOptions dmo = new Database.DMLOptions(); | |
dmo.OptAllOrNone = false; | |
// consider iterating save results to identify failed records | |
// and notifying someone | |
List<Database.SaveResult> saveResults = Database.update( casesToUpdate, dmo ); | |
} | |
} | |
public void finish( Database.BatchableContext context ) { | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment