001/** 002 * Copyright 2004-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.hr.time.shiftdiff.rule; 017 018import com.google.common.collect.ImmutableMap; 019import org.joda.time.DateTime; 020import org.joda.time.DateTimeZone; 021import org.joda.time.LocalTime; 022import org.junit.Assert; 023import org.junit.Ignore; 024import org.junit.Test; 025import org.kuali.hr.KPMEWebTestCase; 026import org.kuali.kpme.core.FunctionalTest; 027import org.kuali.kpme.core.api.assignment.Assignment; 028import org.kuali.kpme.core.api.assignment.AssignmentDescriptionKey; 029import org.kuali.kpme.core.api.calendar.entry.CalendarEntry; 030import org.kuali.kpme.core.calendar.CalendarBo; 031import org.kuali.kpme.core.service.HrServiceLocator; 032import org.kuali.kpme.core.util.HrContext; 033import org.kuali.kpme.core.util.TKUtils; 034import org.kuali.kpme.tklm.api.leave.block.LeaveBlock; 035import org.kuali.kpme.tklm.api.time.timeblock.TimeBlock; 036import org.kuali.kpme.tklm.time.rules.shiftdifferential.ShiftDifferentialRule; 037import org.kuali.kpme.tklm.time.rules.shiftdifferential.service.ShiftDifferentialRuleService; 038import org.kuali.kpme.tklm.time.service.TkServiceLocator; 039import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument; 040import org.kuali.kpme.tklm.time.timesheet.TimesheetUtils; 041import org.kuali.kpme.tklm.time.util.TkTimeBlockAggregate; 042import org.kuali.kpme.tklm.utils.TkTestUtils; 043 044import java.math.BigDecimal; 045import java.sql.Time; 046import java.util.ArrayList; 047import java.util.HashMap; 048import java.util.List; 049 050/** 051 * 052 * @author djunk 053 * 054 */ 055@FunctionalTest 056public class ShiftDifferentialRuleServiceProcessTest extends KPMEWebTestCase { 057 058 059 public static final String USER_PRINCIPAL_ID = "admin"; 060 private DateTime JAN_AS_OF_DATE = new DateTime(2010, 1, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 061 062 063 /** 064 * Test with boundary carryover and overlapping rules. 065 * 066 * Rule 1: 067 * 068 * Runs on Tu, Wed, Th on the interval: [22:00, 4:00) 069 * Max Gap: 15 minutes 070 * Min Hours: 3 071 * 072 * Rule 2: 073 * 074 * Runs on Tu, Th on the interval: [23:00, 2:00) 075 * Max Gap: 2 hours 076 * Min Hours: 3 077 * 078 * Rule 3: 079 * 080 * Runs on W, Th on the interval: [5:00, 12:00) 081 * Max Gap: 15 minutes 082 * Min Hours: 7 hours 083 * 084 * Rule 4: 085 * 086 * Runs on W on the interval: [5:00, 12:00) 087 * Max Gap: 15 minutes 088 * Min Hours: 5 089 * 090 * 091 * |--------------+----+------------+------------| 092 * | Tu : 8/31/10 | XX | W : 9/1/10 | Th: 9/2/10 | 093 * |--------------+----+------------+------------| 094 * | 9:45p - 11:45| XX | Mid - 5a | 5p - 11p | 095 * | | XX | 6a - Noon | | 096 * |--------------+----+------------+------------| 097 * 098 * 099 * Aug 31: 2h : 21:45 - 23:45 (Tue) ** 100 * [1: 5h 45m] // [2: 2h 45m] - Not qualifying, min hours must be 3. 101 * Sep 1: 5h : 00:00 - 05:00 (Wed) ** 102 * Sep 1: 6h : 06:00 - 12:00 (Wed) [4: 6h] 103 * 104 * Sep 1: 2h : 22:00 - 24:00 (Wed) 105 * Sep 2: 1h : 00:00 - 01:00 (Thu) [1: 3h] 106 * 107 * Sep 2: 6h : 17:00 - 22:00 (Thu) 108 * 109 * 1: [22:00, 4:00) (Tue/Wed/Thu) minimum: 3h gap: 15m 110 * 2: [23:00, 2:00) (Tue/Thu) minimum: 3h gap: 2h 111 * 3: [05:00, 12:00) (Wed/Thu) minimum: 7h gap: 15m 112 * 4: [05:00, 12:00) (Wed) minimum: 5h gap: 15m 113 * 114 */ 115 @SuppressWarnings("serial") 116 @Test 117 public void testProcessTimesheetBoundaryCarryoverOverlapCase() throws Exception { 118 DateTimeZone tz = HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback(); 119 // Create the Rule Sun, Mon, Tue, Wed, Thu, Fri, Sat 120 boolean[] dayArray = {false, false, true, true, true, true, true}; 121 // Matches HR Job ID #1 (job # 30) 122 Long jobNumber = 30L; 123 Long workArea = 0L; 124 this.createShiftDifferentialRule( 125 "BWS-CAL", "REG", "PRM", "IN", "SD1", "SD1",// // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job 126 (new LocalTime(22, 0)), 127 (new LocalTime(4, 0)), 128 new BigDecimal(3), // minHours 129 new BigDecimal("15.00"), // maxGap 130 dayArray); 131 132 133 // Timeblocks 134 135 // August 136 DateTime beginPeriodDate = new DateTime(2010, 8, 15, 0, 0, 0, 0, tz); 137 CalendarEntry endOfAugust = HrServiceLocator.getCalendarEntryService().getCalendarEntryByIdAndPeriodEndDate("2", new DateTime(2010, 9, 1, 0, 0, 0, 0)); 138 DateTime start = new DateTime(2010, 8, 31, 21, 45, 0, 0, tz); 139 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 140 TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", endOfAugust); 141 Assignment assignment = HrServiceLocator.getAssignmentService().getAssignment("admin", AssignmentDescriptionKey.get("IU-IN_30_30_30"), beginPeriodDate.toLocalDate()); 142 blocks.addAll(TkTestUtils.createUniformActualTimeBlocks(tdoc, assignment, "RGN", start, 1, new BigDecimal(2), BigDecimal.ZERO, "admin")); 143 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, endOfAugust, HrServiceLocator.getCalendarService().getCalendar(endOfAugust.getHrCalendarId()), true); 144 tdoc.setTimeBlocks(blocks); 145 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 146 TkTestUtils.verifyAggregateHourSumsFlatList("August Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(2));}},aggregate); 147 TkServiceLocator.getTimeBlockService().saveOrUpdateTimeBlocks(new ArrayList<TimeBlock>(), aggregate.getFlattenedTimeBlockList(), "admin"); 148 149 150 // September 151 152 start = new DateTime(2010, 9, 1, 0, 0, 0, 0, tz); 153 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start.toLocalDate().toDateTimeAtStartOfDay()); 154 tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", payCalendarEntry); 155 blocks = new ArrayList<TimeBlock>(); 156 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("5"), "RGN", jobNumber, workArea)); 157 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(6), 1, new BigDecimal("6"), "RGN", jobNumber, workArea)); 158 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(22), 1, new BigDecimal("2"), "RGN", jobNumber, workArea)); 159 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusDays(1), 1, new BigDecimal("1"), "RGN", jobNumber, workArea)); 160 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusDays(1).plusHours(17), 1, new BigDecimal("6"), "RGN", jobNumber, workArea)); 161 blocks = setDocumentIdOnBlocks(blocks, tdoc.getDocumentId()); 162 163 aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry, HrServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId()), true); 164 165 TkTestUtils.verifyAggregateHourSumsFlatList("September Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(20));}},aggregate); 166 167 // Verify carry over and applied PRM bucket 168 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 169 TkTestUtils.verifyAggregateHourSumsFlatList("September Post-Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal("8.75"));put("RGN", new BigDecimal(22));}},aggregate); 170 } 171 172 private List<TimeBlock> setDocumentIdOnBlocks(List<TimeBlock> blocks, String id) { 173 List<TimeBlock> updatedTimeBlocks = new ArrayList<TimeBlock>(); 174 for (TimeBlock b : blocks) { 175 TimeBlock.Builder builder = TimeBlock.Builder.create(b); 176 builder.setDocumentId(id); 177 updatedTimeBlocks.add(builder.build()); 178 } 179 return updatedTimeBlocks; 180 } 181 182 183 /** 184 * Test where previous time sheet contains hours that should be added to 185 * the next pay periods first day shift. 186 * 187 * Runs on Tu, Th on the interval: [22:00, 4:00) 188 * Max Gap: 15 minutes 189 * Min Hours: 3 190 * 191 * |--------------+----+------------+-------------| 192 * | Tu : 8/31/10 | XX | W : 9/1/10 | Th : 9/2/10 | 193 * |--------------+----+------------+-------------| 194 * | 10pm - Mid | XX | Mid - 5am | 5pm - 11pm | 195 * |--------------+----+------------+-------------| 196 * 197 * @throws Exception 198 */ 199 @SuppressWarnings("serial") 200 @Test 201 public void testProcessShiftTimesheeetBoundaryCarryoverCase() throws Exception { 202 // Create the Rule Sun, Mon, Tue, Wed, Thu, Fri, Sat 203 boolean[] dayArray = {false, false, true, false, true, true, true}; 204 // Matches HR Job ID #1 (job # 30) 205 Long jobNumber = 30L; 206 Long workArea = 0L; 207 208 DateTimeZone tz = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 209 this.createShiftDifferentialRule( 210 "BWS-CAL", 211 "REG", 212 "PRM", 213 "IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job 214 "SD1", 215 "SD1", 216 (new LocalTime(22, 0)), 217 (new LocalTime(5, 0)), 218 new BigDecimal(3), // minHours 219 new BigDecimal("0.25"), // maxGap 220 dayArray); 221 222 // August 223 DateTime endPeriodDate = new DateTime(2010, 9, 1, 0, 0, 0, 0); 224 CalendarEntry endOfAugust = HrServiceLocator.getCalendarEntryService().getCalendarEntryByIdAndPeriodEndDate("2", endPeriodDate); 225 DateTime start = new DateTime(2010, 8, 31, 22, 0, 0, 0, tz); 226 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 227 TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", endOfAugust); 228 Assignment assignment = HrServiceLocator.getAssignmentService().getAssignment("admin", AssignmentDescriptionKey.get("IU-IN_30_30_30"), endOfAugust.getBeginPeriodFullDateTime().toLocalDate()); 229 blocks.addAll(TkTestUtils.createUniformActualTimeBlocks(tdoc, assignment, "RGN", start, 1, new BigDecimal(2), BigDecimal.ZERO, "admin")); 230 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, endOfAugust, HrServiceLocator.getCalendarService().getCalendar(endOfAugust.getHrCalendarId()), true); 231 232 233 234 tdoc.setTimeBlocks(blocks); 235 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 236 TkTestUtils.verifyAggregateHourSumsFlatList("August Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(2));}},aggregate); 237 TkServiceLocator.getTimeBlockService().saveOrUpdateTimeBlocks(new ArrayList<TimeBlock>(), aggregate.getFlattenedTimeBlockList(), "admin"); 238 239 240 // September 241 start = new DateTime(2010, 9, 1, 0, 0, 0, 0, tz); 242 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start.toLocalDate().toDateTimeAtStartOfDay()); 243 tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", payCalendarEntry); 244 blocks = new ArrayList<TimeBlock>(); 245 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("5"), "RGN", jobNumber, workArea)); 246 aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry, HrServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId()), true); 247 TkTestUtils.verifyAggregateHourSumsFlatList("September Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(5));}},aggregate); 248 249 // Verify carry over and applied PRM bucket 250 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 251 TkTestUtils.verifyAggregateHourSumsFlatList("September Post-Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(7));put("RGN", new BigDecimal(7));}},aggregate); 252 } 253 254 @SuppressWarnings("serial") 255 @Test 256 /** 257 * Runs on every day on the interval: [16:00, 24:00) 258 * Max Gap: 15 minutes 259 * Min Hours: 4 260 * 261 * Added some extra time blocks that are not in the shift interval, but 262 * close to the time blocks that are. 263 * 264 * @throws Exception 265 */ 266 public void testProcessShiftSimpleNoisyCase() throws Exception { 267 // Create the Rule 268 boolean[] dayArray = {true, true, true, true, true, true, true}; 269 // Matches HR Job ID #1 (job # 30) 270 Long jobNumber = 30L; 271 Long workArea = 0L; 272 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 273 this.createShiftDifferentialRule( 274 "BWS-CAL", 275 "REG", 276 "PRM", 277 "IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job 278 "SD1", 279 "SD1", 280 (new LocalTime(16, 0)), 281 (new LocalTime(0, 0)), 282 new BigDecimal(4), // minHours 283 new BigDecimal("15"), // maxGap 284 dayArray); 285 286 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 287 DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, zone); 288 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 289 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 290 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 2, new BigDecimal("4"), "RGN", jobNumber, workArea)); 291 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(4).plusMinutes(15), 2, new BigDecimal("2"), "RGN", jobNumber, workArea)); 292 blocks.addAll(TkTestUtils.createUniformTimeBlocks(new DateTime(2010, 3, 29, 12, 58, 0, 0, zone), 2, new BigDecimal(1), "RGN", jobNumber, workArea)); 293 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 294 295 // Verify pre-Rule Run 296 TkTestUtils.verifyAggregateHourSums("admin", "Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(14));}},aggregate,2); 297 298 // Run Rule 299 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 300 tdoc.setTimeBlocks(blocks); 301 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 302 303 // Verify post-Rule Run 304 TkTestUtils.verifyAggregateHourSums("admin", "Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("RGN", new BigDecimal(14));}},aggregate,2); 305 } 306 307 @SuppressWarnings("serial") 308 @Test 309 /** 310 * Runs on every day on the interval: [16:00, 24:00) 311 * Max Gap: 15 minutes 312 * Min Hours: 4 313 * 314 * @throws Exception 315 */ 316 public void testProcessShiftSimpleCase() throws Exception { 317 // Create the Rule 318 boolean[] dayArray = {true, true, true, true, true, true, true}; 319 // Matches HR Job ID #1 (job # 30) 320 Long jobNumber = 30L; 321 Long workArea = 0L; 322 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 323 this.createShiftDifferentialRule( 324 "BWS-CAL", 325 "REG", 326 "PRM", 327 "IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job 328 "SD1", 329 "SD1", 330 (new LocalTime(16, 0)), //4pm 331 (new LocalTime(0, 0)), //midnight 332 new BigDecimal(4), // minHours 333 new BigDecimal("15.00"), // maxGap minutes 334 dayArray); 335 336 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 337 DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, zone); 338 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 339 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 340 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 2, new BigDecimal("4"), "REG", jobNumber, workArea)); 341 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(4).plusMinutes(15), 2, new BigDecimal("2"), "REG", jobNumber, workArea)); 342 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 343 344 // Verify pre-Rule Run 345 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(12));}},aggregate,2); 346 347 // Run Rule 348 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 349 tdoc.setTimeBlocks(blocks); 350 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 351 352 // Verify post-Rule Run 353 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("REG", new BigDecimal(12));}},aggregate,2); 354 } 355 356 /** 357 * Stores the Shift Differential Rule in the database for testing. 358 * 359 * dayBooleans[] is a 7 element array of booleans, [0, 6] is [sun, sat] 360 */ 361 private void createShiftDifferentialRule(String pyCalendarGroup, String fromEarnGroup, String premiumEarnCode, String location, String payGrade, String hrSalGroup, LocalTime startTime, LocalTime endTime, BigDecimal minHours, BigDecimal maxGap, boolean dayBooleans[]) { 362 Assert.assertTrue("Wrong number of day booleans", dayBooleans.length == 7); 363 364 ShiftDifferentialRuleService service = TkServiceLocator.getShiftDifferentialRuleService(); 365 ShiftDifferentialRule sdr = new ShiftDifferentialRule(); 366 367 sdr.setBeginTime(new Time(startTime.toDateTimeToday().getMillis())); 368 sdr.setEndTime(new Time(endTime.toDateTimeToday().getMillis())); 369 sdr.setMinHours(minHours); 370 sdr.setMaxGap(maxGap); 371 sdr.setActive(true); 372 sdr.setUserPrincipalId(USER_PRINCIPAL_ID); 373 sdr.setEffectiveLocalDate(JAN_AS_OF_DATE.toLocalDate()); 374 sdr.setLocation(location); 375 sdr.setPayGrade(payGrade); 376 sdr.setHrSalGroup(hrSalGroup); 377 sdr.setFromEarnGroup(fromEarnGroup); 378 sdr.setPyCalendarGroup(pyCalendarGroup); 379 sdr.setEarnCode(premiumEarnCode); 380 sdr.setRuleType("default"); 381 382 for (int i=0; i<dayBooleans.length; i++) { 383 switch(i) { 384 case 0: 385 sdr.setSunday(dayBooleans[i]); 386 break; 387 case 1: 388 sdr.setMonday(dayBooleans[i]); 389 break; 390 case 2: 391 sdr.setTuesday(dayBooleans[i]); 392 break; 393 case 3: 394 sdr.setWednesday(dayBooleans[i]); 395 break; 396 case 4: 397 sdr.setThursday(dayBooleans[i]); 398 break; 399 case 5: 400 sdr.setFriday(dayBooleans[i]); 401 break; 402 case 6: 403 sdr.setSaturday(dayBooleans[i]); 404 break; 405 } 406 } 407 408 service.saveOrUpdate(sdr); 409 410 ShiftDifferentialRule sdrBack = service.getShiftDifferentialRule(sdr.getTkShiftDiffRuleId()); 411 412 DateTimeZone tz = HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback(); 413 LocalTime orig_start = new LocalTime(sdr.getBeginTime()); 414 LocalTime orig_end = new LocalTime(sdr.getEndTime()); 415 416 LocalTime stored_start = new LocalTime(sdrBack.getBeginTime()); 417 LocalTime stored_end = new LocalTime(sdrBack.getEndTime()); 418 419 Assert.assertTrue("Start times not equal.", orig_start.equals(stored_start)); 420 Assert.assertTrue("End times not equal.", orig_end.equals(stored_end)); 421 } 422 423 424 /** 425 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 426 * 427 * Create a single 24 hour timeblock that spans two different shift, both exceeding the min hours 428 */ 429 @Test 430 public void overlapMultipleShiftsWithSameTimeBlock() { 431 // Create the Rule 432 boolean[] dayArray = {true, true, true, true, true, true, true}; 433 // Matches HR Job ID #1 (job # 30) 434 Long jobNumber = 30L; 435 Long workArea = 0L; 436 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 437 438 //3pm to 8am, 6 hour minimum, 90 minute max gap 439 this.createShiftDifferentialRule( 440 "BWS-CAL", 441 "REG", 442 "PRM", 443 "IN", 444 "SD1", 445 "SD1", 446 (new LocalTime(15, 0)), 447 (new LocalTime(8, 0)), 448 new BigDecimal(6), // minHours 449 new BigDecimal("90.00"), // maxGap 450 dayArray); 451 452 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 453 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 454 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 455 456 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 457 DateTime tbStart = new DateTime(2010, 3, 29, 0, 0, 0, 0, zone); 458 459 //24 time block (midnight to midnight) 460 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("24"), "REG", jobNumber, workArea)); 461 462 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 463 464 // Verify pre-Rule Run 465 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(24));}},aggregate,2); 466 467 // Run Rule 468 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 469 tdoc.setTimeBlocks(blocks); 470 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 471 472 // Verify post-Rule Run 473 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(17));put("REG", new BigDecimal(24));}},aggregate,2); 474 475 } 476 477 /** 478 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 479 * 480 * Create a two 24 hour timeblocks that span three different shifts, all exceeding the min hours 481 */ 482 @Test 483 public void overlapMultipleShiftsWithMultipleTimeBlocks() { 484 // Create the Rule 485 boolean[] dayArray = {true, true, true, true, true, true, true}; 486 // Matches HR Job ID #1 (job # 30) 487 Long jobNumber = 30L; 488 Long workArea = 0L; 489 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 490 491 //3pm to 8am, 6 hour minimum, 90 minute max gap 492 this.createShiftDifferentialRule( 493 "BWS-CAL", 494 "REG", 495 "PRM", 496 "IN", 497 "SD1", 498 "SD1", 499 (new LocalTime(15, 0)), 500 (new LocalTime(8, 0)), 501 new BigDecimal(6), // minHours 502 new BigDecimal("90.00"), // maxGap 503 dayArray); 504 505 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 506 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 507 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 508 509 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 510 DateTime tbStart = new DateTime(2010, 3, 29, 0, 0, 0, 0, zone); 511 512 //24 time block (midnight to midnight) 513 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("24"), "REG", jobNumber, workArea)); 514 515 //24 time block (midnight to midnight) 516 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart.plusDays(1), 1, new BigDecimal("24"), "REG", jobNumber, workArea)); 517 518 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 519 520 // Verify pre-Rule Run 521 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(48));}},aggregate,2); 522 523 // Run Rule 524 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 525 tdoc.setTimeBlocks(blocks); 526 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 527 528 // Verify post-Rule Run 529 //overlaps from 12a-8a (8 hours), 3p-8a (17 hours), and 3p - 12a (9 hours) == 34 hours 530 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(34));put("REG", new BigDecimal(48));}},aggregate,2); 531 532 } 533 534 /** 535 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 536 * 537 * Create a single 24 hour timeblock that spans two different shift, both exceeding the min hours 538 */ 539 @Test 540 public void overlapMultipleShiftsWithSameTimeBlockExceedingMinOnOneShift() { 541 // Create the Rule 542 boolean[] dayArray = {true, true, true, true, true, true, true}; 543 // Matches HR Job ID #1 (job # 30) 544 Long jobNumber = 30L; 545 Long workArea = 0L; 546 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 547 548 //3pm to 8am, 6 hour minimum, 90 minute max gap 549 this.createShiftDifferentialRule( 550 "BWS-CAL", 551 "REG", 552 "PRM", 553 "IN", 554 "SD1", 555 "SD1", 556 (new LocalTime(15, 0)), 557 (new LocalTime(8, 0)), 558 new BigDecimal(6), // minHours 559 new BigDecimal("90.00"), // maxGap 560 dayArray); 561 562 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 563 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 564 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 565 566 //reg timeblock 3am - midnight 567 DateTime tbStart = new DateTime(2010, 3, 30, 3, 0, 0, 0, zone); 568 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("21"), "REG", jobNumber, workArea)); 569 570 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 571 572 // Verify pre-Rule Run 573 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 574 .put("PRM", BigDecimal.ZERO) 575 .put("REG", new BigDecimal(21)).build(), aggregate, 2); 576 577 // Run Rule 578 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 579 tdoc.setTimeBlocks(blocks); 580 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 581 582 // Verify post-Rule Run 583 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 584 .put("PRM", new BigDecimal(9)) 585 .put("REG", new BigDecimal(21)).build(), 586 aggregate, 587 2); 588 589 } 590 591 /** 592 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 593 * 594 * Create a single 24 hour timeblock that spans two different shift, both exceeding the min hours 595 */ 596 @Test 597 public void overlapMultipleShiftsWithSameTimeBlockExceedingMinOnFirstShift() { 598 // Create the Rule 599 boolean[] dayArray = {true, true, true, true, true, true, true}; 600 // Matches HR Job ID #1 (job # 30) 601 Long jobNumber = 30L; 602 Long workArea = 0L; 603 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 604 605 //3pm to 8am, 6 hour minimum, 90 minute max gap 606 this.createShiftDifferentialRule( 607 "BWS-CAL", 608 "REG", 609 "PRM", 610 "IN", 611 "SD1", 612 "SD1", 613 (new LocalTime(15, 0)), 614 (new LocalTime(8, 0)), 615 new BigDecimal(6), // minHours 616 new BigDecimal("90.00"), // maxGap 617 dayArray); 618 619 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 620 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 621 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 622 623 //reg timeblock 1am - 9pm 624 DateTime tbStart = new DateTime(2010, 3, 30, 1, 0, 0, 0, zone); 625 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("19"), "REG", jobNumber, workArea)); 626 627 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 628 629 // Verify pre-Rule Run 630 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 631 .put("PRM", BigDecimal.ZERO) 632 .put("REG", new BigDecimal(19)).build(), aggregate, 2); 633 634 // Run Rule 635 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 636 tdoc.setTimeBlocks(blocks); 637 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 638 639 // Verify post-Rule Run 640 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 641 .put("PRM", new BigDecimal(7)) 642 .put("REG", new BigDecimal(19)).build(), 643 aggregate, 644 2); 645 646 } 647 648 /** 649 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 650 * 651 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 652 */ 653 @Test 654 public void overlapMultipleShiftsWithSameTimeBlocNeitherExceedingMin() { 655 // Create the Rule 656 boolean[] dayArray = {true, true, true, true, true, true, true}; 657 // Matches HR Job ID #1 (job # 30) 658 Long jobNumber = 30L; 659 Long workArea = 0L; 660 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 661 662 //3pm to 8am, 6 hour minimum, 90 minute max gap 663 this.createShiftDifferentialRule( 664 "BWS-CAL", 665 "REG", 666 "PRM", 667 "IN", 668 "SD1", 669 "SD1", 670 (new LocalTime(15, 0)), 671 (new LocalTime(8, 0)), 672 new BigDecimal(6), // minHours 673 new BigDecimal("90.00"), // maxGap 674 dayArray); 675 676 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 677 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 678 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 679 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 680 681 //reg timeblock 3am - 8pm 682 DateTime tbStart = new DateTime(2010, 3, 30, 3, 0, 0, 0, zone); 683 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("17"), "REG", jobNumber, workArea)); 684 685 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 686 687 // Verify pre-Rule Run 688 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 689 .put("PRM", BigDecimal.ZERO) 690 .put("REG", new BigDecimal(17)).build(), aggregate, 2); 691 692 // Run Rule 693 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 694 tdoc.setTimeBlocks(blocks); 695 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 696 697 // Verify post-Rule Run 698 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 699 .put("PRM", BigDecimal.ZERO) 700 .put("REG", new BigDecimal(17)).build(), 701 aggregate, 702 2); 703 } 704 705 /** 706 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 707 * 708 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 709 */ 710 @Test 711 public void multipleTimeBlocksOvernightExceedingMin() { 712 // Create the Rule 713 boolean[] dayArray = {true, true, true, true, true, true, true}; 714 // Matches HR Job ID #1 (job # 30) 715 Long jobNumber = 30L; 716 Long workArea = 0L; 717 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 718 719 //3pm to 8am, 6 hour minimum, 90 minute max gap 720 this.createShiftDifferentialRule( 721 "BWS-CAL", 722 "REG", 723 "PRM", 724 "IN", 725 "SD1", 726 "SD1", 727 (new LocalTime(15, 0)), 728 (new LocalTime(8, 0)), 729 new BigDecimal(6), // minHours 730 new BigDecimal("90.00"), // maxGap 731 dayArray); 732 733 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 734 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 735 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 736 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 737 738 //reg timeblock 10pm - midnight 739 DateTime tbStart1 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 740 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 741 //reg timeblock midnight - 5am 742 DateTime tbStart2 = new DateTime(2010, 3, 31, 0, 0, 0, 0, zone); 743 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("5"), "REG", jobNumber, workArea)); 744 745 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 746 747 // Verify pre-Rule Run 748 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 749 .put("PRM", BigDecimal.ZERO) 750 .put("REG", BigDecimal.valueOf(7)).build(), aggregate, 2); 751 752 // Run Rule 753 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 754 tdoc.setTimeBlocks(blocks); 755 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 756 757 // Verify post-Rule Run 758 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 759 .put("PRM", BigDecimal.valueOf(7)) 760 .put("REG", BigDecimal.valueOf(7)).build(), 761 aggregate, 762 2); 763 } 764 765 /** 766 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 767 * 768 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 769 */ 770 @Test 771 public void multipleTimeBlocksOvernightExceedingMinWithSixtyMinuteGap() { 772 // Create the Rule 773 boolean[] dayArray = {true, true, true, true, true, true, true}; 774 // Matches HR Job ID #1 (job # 30) 775 Long jobNumber = 30L; 776 Long workArea = 0L; 777 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 778 779 //3pm to 8am, 6 hour minimum, 90 minute max gap 780 this.createShiftDifferentialRule( 781 "BWS-CAL", 782 "REG", 783 "PRM", 784 "IN", 785 "SD1", 786 "SD1", 787 (new LocalTime(15, 0)), 788 (new LocalTime(8, 0)), 789 new BigDecimal(6), // minHours 790 new BigDecimal("90.00"), // maxGap 791 dayArray); 792 793 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 794 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 795 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 796 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 797 798 //reg timeblock 10pm - midnight 799 DateTime tbStart1 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 800 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 801 //reg timeblock 1am - 5am 802 DateTime tbStart2 = new DateTime(2010, 3, 31, 1, 0, 0, 0, zone); 803 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("4"), "REG", jobNumber, workArea)); 804 805 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 806 807 // Verify pre-Rule Run 808 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 809 .put("PRM", BigDecimal.ZERO) 810 .put("REG", BigDecimal.valueOf(6)).build(), aggregate, 2); 811 812 // Run Rule 813 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 814 tdoc.setTimeBlocks(blocks); 815 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 816 817 // Verify post-Rule Run 818 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 819 .put("PRM", BigDecimal.valueOf(6)) 820 .put("REG", BigDecimal.valueOf(6)).build(), 821 aggregate, 822 2); 823 } 824 825 /** 826 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 827 * 828 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 829 */ 830 @Test 831 public void multipleTimeBlocksOvernightExceedingMinWithNinetyMinuteGap() { 832 // Create the Rule 833 boolean[] dayArray = {true, true, true, true, true, true, true}; 834 // Matches HR Job ID #1 (job # 30) 835 Long jobNumber = 30L; 836 Long workArea = 0L; 837 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 838 839 //3pm to 8am, 6 hour minimum, 90 minute max gap 840 this.createShiftDifferentialRule( 841 "BWS-CAL", 842 "REG", 843 "PRM", 844 "IN", 845 "SD1", 846 "SD1", 847 (new LocalTime(15, 0)), 848 (new LocalTime(8, 0)), 849 new BigDecimal(6), // minHours 850 new BigDecimal("90.00"), // maxGap 851 dayArray); 852 853 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 854 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 855 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 856 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 857 858 //reg timeblock 10pm - midnight 859 DateTime tbStart1 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 860 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 861 //reg timeblock 1:30am - 5:30pm 862 DateTime tbStart2 = new DateTime(2010, 3, 31, 1, 30, 0, 0, zone); 863 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("4"), "REG", jobNumber, workArea)); 864 865 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 866 867 // Verify pre-Rule Run 868 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 869 .put("PRM", BigDecimal.ZERO) 870 .put("REG", BigDecimal.valueOf(6)).build(), aggregate, 2); 871 872 // Run Rule 873 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 874 tdoc.setTimeBlocks(blocks); 875 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 876 877 // Verify post-Rule Run 878 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 879 .put("PRM", BigDecimal.valueOf(6)) 880 .put("REG", BigDecimal.valueOf(6)).build(), 881 aggregate, 882 2); 883 } 884 885 /** 886 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 887 * 888 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 889 */ 890 @Test 891 public void multipleTimeBlocksOvernightExceedingMinButExceedingGap() { 892 // Create the Rule 893 boolean[] dayArray = {true, true, true, true, true, true, true}; 894 // Matches HR Job ID #1 (job # 30) 895 Long jobNumber = 30L; 896 Long workArea = 0L; 897 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 898 899 //3pm to 8am, 6 hour minimum, 90 minute max gap 900 this.createShiftDifferentialRule( 901 "BWS-CAL", 902 "REG", 903 "PRM", 904 "IN", 905 "SD1", 906 "SD1", 907 (new LocalTime(15, 0)), 908 (new LocalTime(8, 0)), 909 new BigDecimal(6), // minHours 910 new BigDecimal("90.00"), // maxGap 911 dayArray); 912 913 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 914 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 915 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 916 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 917 918 //reg timeblock 10pm - midnight 919 DateTime tbStart1 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 920 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 921 //reg timeblock 1:36am - 5:36am 922 DateTime tbStart2 = new DateTime(2010, 3, 31, 1, 36, 0, 0, zone); 923 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("4"), "REG", jobNumber, workArea)); 924 925 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 926 927 // Verify pre-Rule Run 928 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 929 .put("PRM", BigDecimal.ZERO) 930 .put("REG", BigDecimal.valueOf(6)).build(), aggregate, 2); 931 932 // Run Rule 933 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 934 tdoc.setTimeBlocks(blocks); 935 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 936 937 // Verify post-Rule Run 938 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 939 .put("PRM", BigDecimal.valueOf(0)) 940 .put("REG", BigDecimal.valueOf(6)).build(), 941 aggregate, 942 2); 943 } 944 945 946 /** 947 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 948 * 949 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 950 */ 951 @Test 952 public void threeBlocksWithinSameShift() { 953 // Create the Rule 954 boolean[] dayArray = {true, true, true, true, true, true, true}; 955 // Matches HR Job ID #1 (job # 30) 956 Long jobNumber = 30L; 957 Long workArea = 0L; 958 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 959 960 //3pm to 8am, 6 hour minimum, 90 minute max gap 961 this.createShiftDifferentialRule( 962 "BWS-CAL", 963 "REG", 964 "PRM", 965 "IN", 966 "SD1", 967 "SD1", 968 (new LocalTime(15, 0)), 969 (new LocalTime(8, 0)), 970 new BigDecimal(6), // minHours 971 new BigDecimal("90.00"), // maxGap 972 dayArray); 973 974 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 975 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 976 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 977 978 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 979 980 //reg timeblock 3pm - 5pm 981 DateTime tbStart1 = new DateTime(2010, 3, 30, 15, 0, 0, 0, zone); 982 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 983 984 // 6pm - 9pm 985 DateTime tbStart2 = new DateTime(2010, 3, 30, 18, 0, 0, 0, zone); 986 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("3"), "REG", jobNumber, workArea)); 987 988 // 10pm - 11pm 989 DateTime tbStart3 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 990 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("1"), "REG", jobNumber, workArea)); 991 992 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 993 994 // Verify pre-Rule Run 995 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 996 .put("PRM", BigDecimal.ZERO) 997 .put("REG", BigDecimal.valueOf(6)).build(), aggregate, 2); 998 999 // Run Rule 1000 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 1001 tdoc.setTimeBlocks(blocks); 1002 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 1003 1004 // Verify post-Rule Run 1005 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1006 .put("PRM", BigDecimal.valueOf(6)) 1007 .put("REG", BigDecimal.valueOf(6)).build(), 1008 aggregate, 1009 2); 1010 } 1011 1012 /** 1013 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 1014 * 1015 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 1016 */ 1017 @Test 1018 public void fourBlocksWithinSameShiftSpanningTwoDays() { 1019 // Create the Rule 1020 boolean[] dayArray = {true, true, true, true, true, true, true}; 1021 // Matches HR Job ID #1 (job # 30) 1022 Long jobNumber = 30L; 1023 Long workArea = 0L; 1024 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1025 1026 //3pm to 8am, 6 hour minimum, 90 minute max gap 1027 this.createShiftDifferentialRule( 1028 "BWS-CAL", 1029 "REG", 1030 "PRM", 1031 "IN", 1032 "SD1", 1033 "SD1", 1034 (new LocalTime(15, 0)), 1035 (new LocalTime(8, 0)), 1036 new BigDecimal(6), // minHours 1037 new BigDecimal("90.00"), // maxGap 1038 dayArray); 1039 1040 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1041 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1042 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1043 1044 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1045 1046 //reg timeblock 5pm - 6pm 1047 DateTime tbStart1 = new DateTime(2010, 3, 30, 17, 0, 0, 0, zone); 1048 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("1"), "REG", jobNumber, workArea)); 1049 1050 // 7:30pm - 8:30pm 1051 DateTime tbStart2 = new DateTime(2010, 3, 30, 19, 30, 0, 0, zone); 1052 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("1"), "REG", jobNumber, workArea)); 1053 1054 // 10pm - midnight 1055 DateTime tbStart3 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 1056 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 1057 1058 // 1:30am - 4:30am 1059 DateTime tbStart4 = new DateTime(2010, 3, 31, 1, 30, 0, 0, zone); 1060 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 1, new BigDecimal("3"), "REG", jobNumber, workArea)); 1061 1062 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1063 1064 // Verify pre-Rule Run 1065 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1066 .put("PRM", BigDecimal.ZERO) 1067 .put("REG", BigDecimal.valueOf(7)).build(), aggregate, 2); 1068 1069 // Run Rule 1070 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 1071 tdoc.setTimeBlocks(blocks); 1072 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 1073 1074 // Verify post-Rule Run 1075 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1076 .put("PRM", BigDecimal.valueOf(7)) 1077 .put("REG", BigDecimal.valueOf(7)).build(), 1078 aggregate, 1079 2); 1080 } 1081 1082 1083 /** 1084 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 1085 * 1086 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 1087 */ 1088 @Test 1089 public void EarnGroupTest() { 1090 // Create the Rule 1091 // Matches HR Job ID #1 (job # 30) 1092 String principalId = "10112"; 1093 1094 1095 Long jobNumber = 0L; 1096 String groupKey = "IU-IN"; 1097 Long workArea = 1010L; 1098 Long task = 0L; 1099 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1100 1101 1102 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1103 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1104 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1105 1106 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1107 1108 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1109 1110 //rgh - monday 8a-11a no-shift 1111 DateTime tbStart1 = new DateTime(2010, 3, 30, 8, 0, 0, 0, zone); 1112 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1113 1114 //echr - monday 2p-5p - should have 3 hrs SHEG 1115 DateTime tbStart2 = new DateTime(2010, 3, 30, 14, 0, 0, 0, zone); 1116 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("3"), "ECHR", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1117 1118 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1119 1120 // Verify pre-Rule Run 1121 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1122 .put("RGH", BigDecimal.valueOf(3)) 1123 .put("ECHR", BigDecimal.valueOf(3)).build(), aggregate, 2); 1124 1125 // Run Rule 1126 1127 //td.setTimeBlocks(blocks); 1128 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1129 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1130 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1131 1132 //reset time block 1133 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1134 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1135 1136 //refresh Timesheet 1137 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1138 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1139 // Verify post-Rule Run 1140 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1141 .put("RGH", BigDecimal.valueOf(3)) 1142 .put("ECHR", BigDecimal.valueOf(3)) 1143 .put("SHEG", BigDecimal.valueOf(3)).build(), 1144 aggregate, 1145 2); 1146 } 1147 1148 @Test 1149 public void calendarGroupTest() { 1150 // Create the Rule 1151 // Matches HR Job ID #1 (job # 30) 1152 String principalId = "10113"; 1153 1154 1155 Long jobNumber = 0L; 1156 String groupKey = "IU-IN"; 1157 Long workArea = 1010L; 1158 Long task = 0L; 1159 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1160 1161 1162 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1163 DateTime start = new DateTime(2010, 3, 16, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1164 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates(principalId, start); 1165 1166 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1167 1168 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1169 1170 //rgh - monday 8a-11a no-shift 1171 DateTime tbStart1 = new DateTime(2010, 3, 21, 8, 0, 0, 0, zone); 1172 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1173 1174 //echr - monday 2p-5p - should have 3 hrs SHEG 1175 //DateTime tbStart2 = new DateTime(2010, 3, 30, 14, 0, 0, 0, zone); 1176 //blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("3"), "ECHR", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1177 1178 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1179 1180 // Verify pre-Rule Run 1181 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1182 .put("RGH", BigDecimal.valueOf(3)).build(), aggregate, 1); 1183 1184 // Run Rule 1185 1186 //td.setTimeBlocks(blocks); 1187 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1188 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1189 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1190 1191 //reset time block 1192 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1193 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1194 1195 //refresh Timesheet 1196 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1197 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1198 // Verify post-Rule Run 1199 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1200 .put("RGH", BigDecimal.valueOf(3)) 1201 .put("SHCG", BigDecimal.valueOf(3)) 1202 .put("SHDY", BigDecimal.valueOf(0)).build(), 1203 aggregate, 1204 1); 1205 } 1206 1207 @Test 1208 public void daysTest() { 1209 // Create the Rule 1210 // Matches HR Job ID #1 (job # 30) 1211 String principalId = "10114"; 1212 1213 1214 Long jobNumber = 0L; 1215 String groupKey = "IU-IN"; 1216 Long workArea = 1010L; 1217 Long task = 0L; 1218 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1219 1220 1221 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1222 DateTime start = new DateTime(2010, 3, 21, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1223 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1224 1225 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1226 1227 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1228 1229 //rgh - sunday 3p-5p shift: 2 hr SHDY 1230 DateTime tbStart1 = new DateTime(2010, 3, 28, 15, 0, 0, 0, zone); 1231 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1232 1233 //rgh - monday 3p-5p - shift: none 1234 DateTime tbStart2 = new DateTime(2010, 3, 29, 15, 0, 0, 0, zone); 1235 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1236 1237 //rgh - sun 10p- mon 3a - shift: 2hr SHDY (on sunday timeblock) 1238 DateTime tbStart3 = new DateTime(2010, 3, 28, 22, 0, 0, 0, zone); 1239 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1240 DateTime tbStart4 = new DateTime(2010, 3, 29, 0, 0, 0, 0, zone); 1241 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1242 1243 1244 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1245 1246 // Verify pre-Rule Run 1247 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1248 .put("RGH", BigDecimal.valueOf(9)).build(), aggregate, 2); 1249 1250 // Run Rule 1251 1252 //td.setTimeBlocks(blocks); 1253 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1254 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1255 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1256 1257 //reset time block 1258 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1259 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1260 1261 //refresh Timesheet 1262 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1263 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1264 // Verify post-Rule Run 1265 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1266 .put("RGH", BigDecimal.valueOf(9)) 1267 .put("SHDY", BigDecimal.valueOf(4)).build(), 1268 aggregate, 1269 2); 1270 } 1271 1272 1273 @Test 1274 public void daysTestTimeZone() { 1275 // Create the Rule 1276 // Matches HR Job ID #1 (job # 30) 1277 String principalId = "10115"; 1278 1279 1280 Long jobNumber = 0L; 1281 String groupKey = "IU-IN"; 1282 Long workArea = 1010L; 1283 Long task = 0L; 1284 HrContext.setTargetPrincipalId(principalId); 1285 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1286 1287 1288 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1289 DateTime start = new DateTime(2010, 3, 21, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1290 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1291 1292 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1293 1294 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1295 1296 //rgh - sunday 3p-5p shift: 2 hr SHDY 1297 DateTime tbStart1 = new DateTime(2010, 3, 28, 15, 0, 0, 0, zone); 1298 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1299 1300 //rgh - monday 3p-5p - shift: none 1301 DateTime tbStart2 = new DateTime(2010, 3, 29, 15, 0, 0, 0, zone); 1302 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1303 1304 //rgh - sun 10p- mon 3a - shift: 2hr SHDY2 (on sunday timeblock) 1305 DateTime tbStart3 = new DateTime(2010, 3, 28, 22, 0, 0, 0, zone); 1306 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1307 DateTime tbStart4 = new DateTime(2010, 3, 29, 0, 0, 0, 0, zone); 1308 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1309 1310 1311 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1312 1313 // Verify pre-Rule Run 1314 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1315 .put("RGH", BigDecimal.valueOf(9)).build(), aggregate, 2); 1316 1317 // Run Rule 1318 1319 //td.setTimeBlocks(blocks); 1320 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1321 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1322 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1323 1324 //reset time block 1325 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1326 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1327 1328 //refresh Timesheet 1329 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1330 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1331 // Verify post-Rule Run 1332 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1333 .put("RGH", BigDecimal.valueOf(9)) 1334 .put("SHDY2", BigDecimal.valueOf(4)).build(), 1335 aggregate, 1336 2); 1337 HrContext.clearTargetUser(); 1338 } 1339 1340 @Test 1341 public void daysTimeTest() { 1342 // Create the Rule 1343 // Matches HR Job ID #1 (job # 30) 1344 String principalId = "10116"; 1345 1346 1347 Long jobNumber = 0L; 1348 String groupKey = "IU-IN"; 1349 Long workArea = 1010L; 1350 Long task = 0L; 1351 HrContext.setTargetPrincipalId(principalId); 1352 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1353 1354 1355 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1356 DateTime start = new DateTime(2010, 3, 21, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1357 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1358 1359 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1360 1361 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1362 1363 //rgh - monday 2p-4p - shift: 1 hr SHDT 1364 DateTime tbStart1 = new DateTime(2010, 3, 22, 14, 0, 0, 0, zone); 1365 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1366 1367 //rgh - tuesday 4:30p-8p - shift: 3.5 hr SHDT 1368 DateTime tbStart2 = new DateTime(2010, 3, 23, 16, 30, 0, 0, zone); 1369 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("3.5"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1370 1371 //rgh - sun 3p - 8p - no shift 1372 DateTime tbStart3 = new DateTime(2010, 3, 21, 15, 0, 0, 0, zone); 1373 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("5"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1374 1375 //rgh - wed, thurs, fri, sat 2p - 7p - shift: SHDT 4hr on wed-fri (none saturday) 1376 DateTime tbStart4 = new DateTime(2010, 3, 24, 14, 0, 0, 0, zone); 1377 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 4, new BigDecimal("5"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1378 1379 1380 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1381 1382 // Verify pre-Rule Run 1383 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1384 .put("RGH", BigDecimal.valueOf(30.5)).build(), aggregate, 1); 1385 1386 // Run Rule 1387 1388 //td.setTimeBlocks(blocks); 1389 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1390 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1391 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1392 1393 //reset time block 1394 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1395 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1396 1397 //refresh Timesheet 1398 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1399 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1400 // Verify post-Rule Run 1401 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1402 .put("RGH", BigDecimal.valueOf(30.5)) 1403 .put("SHDT", BigDecimal.valueOf(16.5)).build(), 1404 aggregate, 1405 1); 1406 HrContext.clearTargetUser(); 1407 } 1408 1409 @Test 1410 public void timeTest() { 1411 // Create the Rule 1412 // Matches HR Job ID #1 (job # 30) 1413 String principalId = "10117"; 1414 1415 1416 Long jobNumber = 0L; 1417 String groupKey = "IU-IN"; 1418 Long workArea = 1010L; 1419 Long task = 0L; 1420 HrContext.setTargetPrincipalId(principalId); 1421 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1422 1423 1424 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1425 DateTime start = new DateTime(2010, 3, 21, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1426 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1427 1428 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1429 1430 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1431 1432 //rgh - sunday 3p - monday 3a - shift: 9 hr SHTT 1433 DateTime tbStart1a = new DateTime(2010, 3, 21, 15, 0, 0, 0, zone); 1434 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1a, 1, new BigDecimal("9"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1435 DateTime tbStart1b = new DateTime(2010, 3, 22, 0, 0, 0, 0, zone); 1436 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1b, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1437 1438 1439 //rgh - monday 3a-9a - shift: 3 hr SHTT 1440 DateTime tbStart2 = new DateTime(2010, 3, 22, 3, 0, 0, 0, zone); 1441 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("6"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1442 1443 //rgh - monday 10p - 11:30p - shift: 1.5 hr SHTT 1444 DateTime tbStart3 = new DateTime(2010, 3, 22, 22, 0, 0, 0, zone); 1445 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("1.5"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1446 1447 //rgh - tues 12a - 7a - shift: SHTT 6hr 1448 DateTime tbStart4 = new DateTime(2010, 3, 23, 0, 0, 0, 0, zone); 1449 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 1, new BigDecimal("7"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1450 1451 //rgh - wed 6a - 11a - no shift 1452 DateTime tbStart5 = new DateTime(2010, 3, 24, 6, 0, 0, 0, zone); 1453 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart5, 1, new BigDecimal("5"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1454 1455 1456 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1457 1458 // Verify pre-Rule Run 1459 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1460 .put("RGH", BigDecimal.valueOf(31.5)).build(), aggregate, 1); 1461 1462 // Run Rule 1463 1464 //td.setTimeBlocks(blocks); 1465 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1466 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1467 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1468 1469 //reset time block 1470 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1471 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1472 1473 //refresh Timesheet 1474 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1475 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1476 // Verify post-Rule Run 1477 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1478 .put("RGH", BigDecimal.valueOf(31.5)) 1479 .put("SHTT", BigDecimal.valueOf(19.5)).build(), 1480 aggregate, 1481 1); 1482 HrContext.clearTargetUser(); 1483 } 1484 1485 1486 @Ignore 1487 @Test 1488 public void minHoursTest() { 1489 // Create the Rule 1490 // Matches HR Job ID #1 (job # 30) 1491 String principalId = "10118"; 1492 1493 1494 Long jobNumber = 0L; 1495 String groupKey = "IU-IN"; 1496 Long workArea = 1010L; 1497 Long task = 0L; 1498 HrContext.setTargetPrincipalId(principalId); 1499 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1500 1501 1502 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1503 DateTime start = new DateTime(2010, 3, 21, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1504 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1505 1506 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1507 1508 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1509 1510 //rgh - sunday 3p - monday 3a - shift: 9 hr SHMH 1511 DateTime tbStart1a = new DateTime(2010, 3, 21, 15, 0, 0, 0, zone); 1512 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1a, 1, new BigDecimal("9"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1513 DateTime tbStart1b = new DateTime(2010, 3, 22, 0, 0, 0, 0, zone); 1514 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1b, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1515 1516 1517 //rgh - monday 3a-9a - shift: 3 hr SHMH 1518 DateTime tbStart2 = new DateTime(2010, 3, 22, 3, 0, 0, 0, zone); 1519 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("6"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1520 1521 //rgh - monday 10p - 11:30p - shift: 1.5 hr SHMH (after timeblock added below) 1522 DateTime tbStart3 = new DateTime(2010, 3, 22, 22, 0, 0, 0, zone); 1523 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("1.5"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1524 1525 //rgh - tues 12a - 7a - shift: SHTT 6hr 1526 DateTime tbStart4 = new DateTime(2010, 3, 23, 0, 0, 0, 0, zone); 1527 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 1, new BigDecimal("7"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1528 1529 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1530 1531 // Verify pre-Rule Run 1532 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1533 .put("RGH", BigDecimal.valueOf(26.5)).build(), aggregate, 1); 1534 1535 // Run Rule 1536 1537 //td.setTimeBlocks(blocks); 1538 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1539 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1540 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1541 1542 //reset time block 1543 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1544 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1545 1546 //refresh Timesheet 1547 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1548 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1549 // Verify post-Rule Run 1550 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1551 .put("RGH", BigDecimal.valueOf(26.5)) 1552 .put("SHTT", BigDecimal.valueOf(7.5)) 1553 .put("SHMH", BigDecimal.valueOf(12)).build(), 1554 aggregate, 1555 1); 1556 HrContext.clearTargetUser(); 1557 } 1558}