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 @Ignore 425 @Test 426 /** 427 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 428 * 429 * Create a timeblock on two days, one day has normal REG shift eligible 430 * hours, one day has HOL time. 431 * 432 * Modified version of the simple case, SDR from 12:00 to 17:00, every day, 433 * must have at least 4 hours with a maximum 15 minute gap. 434 * 435 */ 436 public void simpleCaseWithWorkSchedule() throws Exception { 437 // Create the Rule 438 boolean[] dayArray = {true, true, true, true, true, true, true}; 439 // Matches HR Job ID #1 (job # 30) 440 Long jobNumber = 30L; 441 Long workArea = 0L; 442 this.createShiftDifferentialRule( 443 "BWS-CAL", 444 "REG", 445 "PRM", 446 "IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job 447 "SD1", 448 "SD1", 449 (new LocalTime(12, 0)), 450 (new LocalTime(17, 0)), 451 new BigDecimal(4), // minHours 452 new BigDecimal("15.00"), // maxGap 453 dayArray); 454 455 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 456 DateTime start = new DateTime(2010, 3, 29, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 457 DateTime holtime = new DateTime(2010, 3, 30, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 458 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 459 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 460 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("4"), "REG", jobNumber, workArea)); 461 blocks.addAll(TkTestUtils.createUniformTimeBlocks(holtime, 1, new BigDecimal("4"), "HOL", jobNumber, workArea)); 462 463 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 464 465 // Verify pre-Rule Run 466 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(4));put("HOL", new BigDecimal(4));}},aggregate,2); 467 468 // Run Rule 469 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 470 tdoc.setTimeBlocks(blocks); 471 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 472 473 // Verify post-Rule Run 474 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("REG", new BigDecimal(4));}},aggregate,2); 475 476 } 477 478 479 480 /** 481 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 482 * 483 * Create a single 24 hour timeblock that spans two different shift, both exceeding the min hours 484 */ 485 @Test 486 public void overlapMultipleShiftsWithSameTimeBlock() { 487 // Create the Rule 488 boolean[] dayArray = {true, true, true, true, true, true, true}; 489 // Matches HR Job ID #1 (job # 30) 490 Long jobNumber = 30L; 491 Long workArea = 0L; 492 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 493 494 //3pm to 8am, 6 hour minimum, 90 minute max gap 495 this.createShiftDifferentialRule( 496 "BWS-CAL", 497 "REG", 498 "PRM", 499 "IN", 500 "SD1", 501 "SD1", 502 (new LocalTime(15, 0)), 503 (new LocalTime(8, 0)), 504 new BigDecimal(6), // minHours 505 new BigDecimal("90.00"), // maxGap 506 dayArray); 507 508 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 509 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 510 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 511 512 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 513 DateTime tbStart = new DateTime(2010, 3, 29, 0, 0, 0, 0, zone); 514 515 //24 time block (midnight to midnight) 516 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 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(24));}},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 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(17));put("REG", new BigDecimal(24));}},aggregate,2); 530 531 } 532 533 /** 534 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 535 * 536 * Create a two 24 hour timeblocks that span three different shifts, all exceeding the min hours 537 */ 538 @Test 539 public void overlapMultipleShiftsWithMultipleTimeBlocks() { 540 // Create the Rule 541 boolean[] dayArray = {true, true, true, true, true, true, true}; 542 // Matches HR Job ID #1 (job # 30) 543 Long jobNumber = 30L; 544 Long workArea = 0L; 545 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 546 547 //3pm to 8am, 6 hour minimum, 90 minute max gap 548 this.createShiftDifferentialRule( 549 "BWS-CAL", 550 "REG", 551 "PRM", 552 "IN", 553 "SD1", 554 "SD1", 555 (new LocalTime(15, 0)), 556 (new LocalTime(8, 0)), 557 new BigDecimal(6), // minHours 558 new BigDecimal("90.00"), // maxGap 559 dayArray); 560 561 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 562 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 563 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 564 565 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 566 DateTime tbStart = new DateTime(2010, 3, 29, 0, 0, 0, 0, zone); 567 568 //24 time block (midnight to midnight) 569 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("24"), "REG", jobNumber, workArea)); 570 571 //24 time block (midnight to midnight) 572 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart.plusDays(1), 1, new BigDecimal("24"), "REG", jobNumber, workArea)); 573 574 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 575 576 // Verify pre-Rule Run 577 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(48));}},aggregate,2); 578 579 // Run Rule 580 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 581 tdoc.setTimeBlocks(blocks); 582 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 583 584 // Verify post-Rule Run 585 //overlaps from 12a-8a (8 hours), 3p-8a (17 hours), and 3p - 12a (9 hours) == 34 hours 586 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(34));put("REG", new BigDecimal(48));}},aggregate,2); 587 588 } 589 590 /** 591 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 592 * 593 * Create a single 24 hour timeblock that spans two different shift, both exceeding the min hours 594 */ 595 @Test 596 public void overlapMultipleShiftsWithSameTimeBlockExceedingMinOnOneShift() { 597 // Create the Rule 598 boolean[] dayArray = {true, true, true, true, true, true, true}; 599 // Matches HR Job ID #1 (job # 30) 600 Long jobNumber = 30L; 601 Long workArea = 0L; 602 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 603 604 //3pm to 8am, 6 hour minimum, 90 minute max gap 605 this.createShiftDifferentialRule( 606 "BWS-CAL", 607 "REG", 608 "PRM", 609 "IN", 610 "SD1", 611 "SD1", 612 (new LocalTime(15, 0)), 613 (new LocalTime(8, 0)), 614 new BigDecimal(6), // minHours 615 new BigDecimal("90.00"), // maxGap 616 dayArray); 617 618 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 619 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 620 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 621 622 //reg timeblock 3am - midnight 623 DateTime tbStart = new DateTime(2010, 3, 30, 3, 0, 0, 0, zone); 624 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("21"), "REG", jobNumber, workArea)); 625 626 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 627 628 // Verify pre-Rule Run 629 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 630 .put("PRM", BigDecimal.ZERO) 631 .put("REG", new BigDecimal(21)).build(), aggregate, 2); 632 633 // Run Rule 634 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 635 tdoc.setTimeBlocks(blocks); 636 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 637 638 // Verify post-Rule Run 639 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 640 .put("PRM", new BigDecimal(9)) 641 .put("REG", new BigDecimal(21)).build(), 642 aggregate, 643 2); 644 645 } 646 647 /** 648 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 649 * 650 * Create a single 24 hour timeblock that spans two different shift, both exceeding the min hours 651 */ 652 @Test 653 public void overlapMultipleShiftsWithSameTimeBlockExceedingMinOnFirstShift() { 654 // Create the Rule 655 boolean[] dayArray = {true, true, true, true, true, true, true}; 656 // Matches HR Job ID #1 (job # 30) 657 Long jobNumber = 30L; 658 Long workArea = 0L; 659 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 660 661 //3pm to 8am, 6 hour minimum, 90 minute max gap 662 this.createShiftDifferentialRule( 663 "BWS-CAL", 664 "REG", 665 "PRM", 666 "IN", 667 "SD1", 668 "SD1", 669 (new LocalTime(15, 0)), 670 (new LocalTime(8, 0)), 671 new BigDecimal(6), // minHours 672 new BigDecimal("90.00"), // maxGap 673 dayArray); 674 675 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 676 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 677 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 678 679 //reg timeblock 1am - 9pm 680 DateTime tbStart = new DateTime(2010, 3, 30, 1, 0, 0, 0, zone); 681 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("19"), "REG", jobNumber, workArea)); 682 683 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 684 685 // Verify pre-Rule Run 686 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 687 .put("PRM", BigDecimal.ZERO) 688 .put("REG", new BigDecimal(19)).build(), aggregate, 2); 689 690 // Run Rule 691 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 692 tdoc.setTimeBlocks(blocks); 693 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 694 695 // Verify post-Rule Run 696 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 697 .put("PRM", new BigDecimal(7)) 698 .put("REG", new BigDecimal(19)).build(), 699 aggregate, 700 2); 701 702 } 703 704 /** 705 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 706 * 707 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 708 */ 709 @Test 710 public void overlapMultipleShiftsWithSameTimeBlocNeitherExceedingMin() { 711 // Create the Rule 712 boolean[] dayArray = {true, true, true, true, true, true, true}; 713 // Matches HR Job ID #1 (job # 30) 714 Long jobNumber = 30L; 715 Long workArea = 0L; 716 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 717 718 //3pm to 8am, 6 hour minimum, 90 minute max gap 719 this.createShiftDifferentialRule( 720 "BWS-CAL", 721 "REG", 722 "PRM", 723 "IN", 724 "SD1", 725 "SD1", 726 (new LocalTime(15, 0)), 727 (new LocalTime(8, 0)), 728 new BigDecimal(6), // minHours 729 new BigDecimal("90.00"), // maxGap 730 dayArray); 731 732 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 733 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 734 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 735 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 736 737 //reg timeblock 3am - 8pm 738 DateTime tbStart = new DateTime(2010, 3, 30, 3, 0, 0, 0, zone); 739 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 1, new BigDecimal("17"), "REG", jobNumber, workArea)); 740 741 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 742 743 // Verify pre-Rule Run 744 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 745 .put("PRM", BigDecimal.ZERO) 746 .put("REG", new BigDecimal(17)).build(), aggregate, 2); 747 748 // Run Rule 749 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 750 tdoc.setTimeBlocks(blocks); 751 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 752 753 // Verify post-Rule Run 754 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 755 .put("PRM", BigDecimal.ZERO) 756 .put("REG", new BigDecimal(17)).build(), 757 aggregate, 758 2); 759 } 760 761 /** 762 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 763 * 764 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 765 */ 766 @Test 767 public void multipleTimeBlocksOvernightExceedingMin() { 768 // Create the Rule 769 boolean[] dayArray = {true, true, true, true, true, true, true}; 770 // Matches HR Job ID #1 (job # 30) 771 Long jobNumber = 30L; 772 Long workArea = 0L; 773 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 774 775 //3pm to 8am, 6 hour minimum, 90 minute max gap 776 this.createShiftDifferentialRule( 777 "BWS-CAL", 778 "REG", 779 "PRM", 780 "IN", 781 "SD1", 782 "SD1", 783 (new LocalTime(15, 0)), 784 (new LocalTime(8, 0)), 785 new BigDecimal(6), // minHours 786 new BigDecimal("90.00"), // maxGap 787 dayArray); 788 789 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 790 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 791 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 792 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 793 794 //reg timeblock 10pm - midnight 795 DateTime tbStart1 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 796 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 797 //reg timeblock midnight - 5am 798 DateTime tbStart2 = new DateTime(2010, 3, 31, 0, 0, 0, 0, zone); 799 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("5"), "REG", jobNumber, workArea)); 800 801 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 802 803 // Verify pre-Rule Run 804 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 805 .put("PRM", BigDecimal.ZERO) 806 .put("REG", BigDecimal.valueOf(7)).build(), aggregate, 2); 807 808 // Run Rule 809 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 810 tdoc.setTimeBlocks(blocks); 811 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 812 813 // Verify post-Rule Run 814 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 815 .put("PRM", BigDecimal.valueOf(7)) 816 .put("REG", BigDecimal.valueOf(7)).build(), 817 aggregate, 818 2); 819 } 820 821 /** 822 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 823 * 824 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 825 */ 826 @Test 827 public void multipleTimeBlocksOvernightExceedingMinWithSixtyMinuteGap() { 828 // Create the Rule 829 boolean[] dayArray = {true, true, true, true, true, true, true}; 830 // Matches HR Job ID #1 (job # 30) 831 Long jobNumber = 30L; 832 Long workArea = 0L; 833 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 834 835 //3pm to 8am, 6 hour minimum, 90 minute max gap 836 this.createShiftDifferentialRule( 837 "BWS-CAL", 838 "REG", 839 "PRM", 840 "IN", 841 "SD1", 842 "SD1", 843 (new LocalTime(15, 0)), 844 (new LocalTime(8, 0)), 845 new BigDecimal(6), // minHours 846 new BigDecimal("90.00"), // maxGap 847 dayArray); 848 849 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 850 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 851 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 852 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 853 854 //reg timeblock 10pm - midnight 855 DateTime tbStart1 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 856 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 857 //reg timeblock 1am - 5am 858 DateTime tbStart2 = new DateTime(2010, 3, 31, 1, 0, 0, 0, zone); 859 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("4"), "REG", jobNumber, workArea)); 860 861 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 862 863 // Verify pre-Rule Run 864 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 865 .put("PRM", BigDecimal.ZERO) 866 .put("REG", BigDecimal.valueOf(6)).build(), aggregate, 2); 867 868 // Run Rule 869 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 870 tdoc.setTimeBlocks(blocks); 871 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 872 873 // Verify post-Rule Run 874 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 875 .put("PRM", BigDecimal.valueOf(6)) 876 .put("REG", BigDecimal.valueOf(6)).build(), 877 aggregate, 878 2); 879 } 880 881 /** 882 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 883 * 884 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 885 */ 886 @Test 887 public void multipleTimeBlocksOvernightExceedingMinWithNinetyMinuteGap() { 888 // Create the Rule 889 boolean[] dayArray = {true, true, true, true, true, true, true}; 890 // Matches HR Job ID #1 (job # 30) 891 Long jobNumber = 30L; 892 Long workArea = 0L; 893 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 894 895 //3pm to 8am, 6 hour minimum, 90 minute max gap 896 this.createShiftDifferentialRule( 897 "BWS-CAL", 898 "REG", 899 "PRM", 900 "IN", 901 "SD1", 902 "SD1", 903 (new LocalTime(15, 0)), 904 (new LocalTime(8, 0)), 905 new BigDecimal(6), // minHours 906 new BigDecimal("90.00"), // maxGap 907 dayArray); 908 909 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 910 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 911 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 912 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 913 914 //reg timeblock 10pm - midnight 915 DateTime tbStart1 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 916 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 917 //reg timeblock 1:30am - 5:30pm 918 DateTime tbStart2 = new DateTime(2010, 3, 31, 1, 30, 0, 0, zone); 919 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("4"), "REG", jobNumber, workArea)); 920 921 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 922 923 // Verify pre-Rule Run 924 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 925 .put("PRM", BigDecimal.ZERO) 926 .put("REG", BigDecimal.valueOf(6)).build(), aggregate, 2); 927 928 // Run Rule 929 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 930 tdoc.setTimeBlocks(blocks); 931 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 932 933 // Verify post-Rule Run 934 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 935 .put("PRM", BigDecimal.valueOf(6)) 936 .put("REG", BigDecimal.valueOf(6)).build(), 937 aggregate, 938 2); 939 } 940 941 /** 942 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 943 * 944 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 945 */ 946 @Test 947 public void multipleTimeBlocksOvernightExceedingMinButExceedingGap() { 948 // Create the Rule 949 boolean[] dayArray = {true, true, true, true, true, true, true}; 950 // Matches HR Job ID #1 (job # 30) 951 Long jobNumber = 30L; 952 Long workArea = 0L; 953 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 954 955 //3pm to 8am, 6 hour minimum, 90 minute max gap 956 this.createShiftDifferentialRule( 957 "BWS-CAL", 958 "REG", 959 "PRM", 960 "IN", 961 "SD1", 962 "SD1", 963 (new LocalTime(15, 0)), 964 (new LocalTime(8, 0)), 965 new BigDecimal(6), // minHours 966 new BigDecimal("90.00"), // maxGap 967 dayArray); 968 969 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 970 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 971 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 972 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 973 974 //reg timeblock 10pm - midnight 975 DateTime tbStart1 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 976 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 977 //reg timeblock 1:36am - 5:36am 978 DateTime tbStart2 = new DateTime(2010, 3, 31, 1, 36, 0, 0, zone); 979 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("4"), "REG", jobNumber, workArea)); 980 981 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 982 983 // Verify pre-Rule Run 984 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 985 .put("PRM", BigDecimal.ZERO) 986 .put("REG", BigDecimal.valueOf(6)).build(), aggregate, 2); 987 988 // Run Rule 989 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 990 tdoc.setTimeBlocks(blocks); 991 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 992 993 // Verify post-Rule Run 994 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 995 .put("PRM", BigDecimal.valueOf(0)) 996 .put("REG", BigDecimal.valueOf(6)).build(), 997 aggregate, 998 2); 999 } 1000 1001 1002 /** 1003 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 1004 * 1005 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 1006 */ 1007 @Test 1008 public void threeBlocksWithinSameShift() { 1009 // Create the Rule 1010 boolean[] dayArray = {true, true, true, true, true, true, true}; 1011 // Matches HR Job ID #1 (job # 30) 1012 Long jobNumber = 30L; 1013 Long workArea = 0L; 1014 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1015 1016 //3pm to 8am, 6 hour minimum, 90 minute max gap 1017 this.createShiftDifferentialRule( 1018 "BWS-CAL", 1019 "REG", 1020 "PRM", 1021 "IN", 1022 "SD1", 1023 "SD1", 1024 (new LocalTime(15, 0)), 1025 (new LocalTime(8, 0)), 1026 new BigDecimal(6), // minHours 1027 new BigDecimal("90.00"), // maxGap 1028 dayArray); 1029 1030 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1031 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1032 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1033 1034 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1035 1036 //reg timeblock 3pm - 5pm 1037 DateTime tbStart1 = new DateTime(2010, 3, 30, 15, 0, 0, 0, zone); 1038 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 1039 1040 // 6pm - 9pm 1041 DateTime tbStart2 = new DateTime(2010, 3, 30, 18, 0, 0, 0, zone); 1042 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("3"), "REG", jobNumber, workArea)); 1043 1044 // 10pm - 11pm 1045 DateTime tbStart3 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 1046 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("1"), "REG", jobNumber, workArea)); 1047 1048 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1049 1050 // Verify pre-Rule Run 1051 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1052 .put("PRM", BigDecimal.ZERO) 1053 .put("REG", BigDecimal.valueOf(6)).build(), aggregate, 2); 1054 1055 // Run Rule 1056 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 1057 tdoc.setTimeBlocks(blocks); 1058 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 1059 1060 // Verify post-Rule Run 1061 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1062 .put("PRM", BigDecimal.valueOf(6)) 1063 .put("REG", BigDecimal.valueOf(6)).build(), 1064 aggregate, 1065 2); 1066 } 1067 1068 /** 1069 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 1070 * 1071 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 1072 */ 1073 @Test 1074 public void fourBlocksWithinSameShiftSpanningTwoDays() { 1075 // Create the Rule 1076 boolean[] dayArray = {true, true, true, true, true, true, true}; 1077 // Matches HR Job ID #1 (job # 30) 1078 Long jobNumber = 30L; 1079 Long workArea = 0L; 1080 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1081 1082 //3pm to 8am, 6 hour minimum, 90 minute max gap 1083 this.createShiftDifferentialRule( 1084 "BWS-CAL", 1085 "REG", 1086 "PRM", 1087 "IN", 1088 "SD1", 1089 "SD1", 1090 (new LocalTime(15, 0)), 1091 (new LocalTime(8, 0)), 1092 new BigDecimal(6), // minHours 1093 new BigDecimal("90.00"), // maxGap 1094 dayArray); 1095 1096 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1097 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1098 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1099 1100 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1101 1102 //reg timeblock 5pm - 6pm 1103 DateTime tbStart1 = new DateTime(2010, 3, 30, 17, 0, 0, 0, zone); 1104 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("1"), "REG", jobNumber, workArea)); 1105 1106 // 7:30pm - 8:30pm 1107 DateTime tbStart2 = new DateTime(2010, 3, 30, 19, 30, 0, 0, zone); 1108 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("1"), "REG", jobNumber, workArea)); 1109 1110 // 10pm - midnight 1111 DateTime tbStart3 = new DateTime(2010, 3, 30, 22, 0, 0, 0, zone); 1112 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("2"), "REG", jobNumber, workArea)); 1113 1114 // 1:30am - 4:30am 1115 DateTime tbStart4 = new DateTime(2010, 3, 31, 1, 30, 0, 0, zone); 1116 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 1, new BigDecimal("3"), "REG", jobNumber, workArea)); 1117 1118 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1119 1120 // Verify pre-Rule Run 1121 TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1122 .put("PRM", BigDecimal.ZERO) 1123 .put("REG", BigDecimal.valueOf(7)).build(), aggregate, 2); 1124 1125 // Run Rule 1126 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin"); 1127 tdoc.setTimeBlocks(blocks); 1128 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate); 1129 1130 // Verify post-Rule Run 1131 TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1132 .put("PRM", BigDecimal.valueOf(7)) 1133 .put("REG", BigDecimal.valueOf(7)).build(), 1134 aggregate, 1135 2); 1136 } 1137 1138 1139 /** 1140 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case 1141 * 1142 * Create a single 17 hour timeblock that spans two different shift, neither exceeding the min hours 1143 */ 1144 @Test 1145 public void EarnGroupTest() { 1146 // Create the Rule 1147 // Matches HR Job ID #1 (job # 30) 1148 String principalId = "10112"; 1149 1150 1151 Long jobNumber = 0L; 1152 String groupKey = "IU-IN"; 1153 Long workArea = 1010L; 1154 Long task = 0L; 1155 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1156 1157 1158 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1159 DateTime start = new DateTime(2010, 3, 29, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1160 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1161 1162 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1163 1164 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1165 1166 //rgh - monday 8a-11a no-shift 1167 DateTime tbStart1 = new DateTime(2010, 3, 30, 8, 0, 0, 0, zone); 1168 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1169 1170 //echr - monday 2p-5p - should have 3 hrs SHEG 1171 DateTime tbStart2 = new DateTime(2010, 3, 30, 14, 0, 0, 0, zone); 1172 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("3"), "ECHR", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1173 1174 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1175 1176 // Verify pre-Rule Run 1177 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1178 .put("RGH", BigDecimal.valueOf(3)) 1179 .put("ECHR", BigDecimal.valueOf(3)).build(), aggregate, 2); 1180 1181 // Run Rule 1182 1183 //td.setTimeBlocks(blocks); 1184 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1185 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1186 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1187 1188 //reset time block 1189 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1190 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1191 1192 //refresh Timesheet 1193 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1194 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1195 // Verify post-Rule Run 1196 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1197 .put("RGH", BigDecimal.valueOf(3)) 1198 .put("ECHR", BigDecimal.valueOf(3)) 1199 .put("SHEG", BigDecimal.valueOf(3)).build(), 1200 aggregate, 1201 2); 1202 } 1203 1204 @Test 1205 public void calendarGroupTest() { 1206 // Create the Rule 1207 // Matches HR Job ID #1 (job # 30) 1208 String principalId = "10113"; 1209 1210 1211 Long jobNumber = 0L; 1212 String groupKey = "IU-IN"; 1213 Long workArea = 1010L; 1214 Long task = 0L; 1215 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1216 1217 1218 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1219 DateTime start = new DateTime(2010, 3, 16, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1220 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates(principalId, start); 1221 1222 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1223 1224 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1225 1226 //rgh - monday 8a-11a no-shift 1227 DateTime tbStart1 = new DateTime(2010, 3, 21, 8, 0, 0, 0, zone); 1228 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1229 1230 //echr - monday 2p-5p - should have 3 hrs SHEG 1231 //DateTime tbStart2 = new DateTime(2010, 3, 30, 14, 0, 0, 0, zone); 1232 //blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("3"), "ECHR", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1233 1234 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1235 1236 // Verify pre-Rule Run 1237 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1238 .put("RGH", BigDecimal.valueOf(3)).build(), aggregate, 1); 1239 1240 // Run Rule 1241 1242 //td.setTimeBlocks(blocks); 1243 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1244 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1245 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1246 1247 //reset time block 1248 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1249 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1250 1251 //refresh Timesheet 1252 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1253 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1254 // Verify post-Rule Run 1255 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1256 .put("RGH", BigDecimal.valueOf(3)) 1257 .put("SHCG", BigDecimal.valueOf(3)) 1258 .put("SHDY", BigDecimal.valueOf(0)).build(), 1259 aggregate, 1260 1); 1261 } 1262 1263 @Test 1264 public void daysTest() { 1265 // Create the Rule 1266 // Matches HR Job ID #1 (job # 30) 1267 String principalId = "10114"; 1268 1269 1270 Long jobNumber = 0L; 1271 String groupKey = "IU-IN"; 1272 Long workArea = 1010L; 1273 Long task = 0L; 1274 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1275 1276 1277 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1278 DateTime start = new DateTime(2010, 3, 21, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1279 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1280 1281 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1282 1283 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1284 1285 //rgh - sunday 3p-5p shift: 2 hr SHDY 1286 DateTime tbStart1 = new DateTime(2010, 3, 28, 15, 0, 0, 0, zone); 1287 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1288 1289 //rgh - monday 3p-5p - shift: none 1290 DateTime tbStart2 = new DateTime(2010, 3, 29, 15, 0, 0, 0, zone); 1291 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1292 1293 //rgh - sun 10p- mon 3a - shift: 2hr SHDY (on sunday timeblock) 1294 DateTime tbStart3 = new DateTime(2010, 3, 28, 22, 0, 0, 0, zone); 1295 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1296 DateTime tbStart4 = new DateTime(2010, 3, 29, 0, 0, 0, 0, zone); 1297 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1298 1299 1300 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1301 1302 // Verify pre-Rule Run 1303 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1304 .put("RGH", BigDecimal.valueOf(9)).build(), aggregate, 2); 1305 1306 // Run Rule 1307 1308 //td.setTimeBlocks(blocks); 1309 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1310 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1311 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1312 1313 //reset time block 1314 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1315 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1316 1317 //refresh Timesheet 1318 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1319 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1320 // Verify post-Rule Run 1321 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1322 .put("RGH", BigDecimal.valueOf(9)) 1323 .put("SHDY", BigDecimal.valueOf(4)).build(), 1324 aggregate, 1325 2); 1326 } 1327 1328 1329 @Test 1330 public void daysTestTimeZone() { 1331 // Create the Rule 1332 // Matches HR Job ID #1 (job # 30) 1333 String principalId = "10115"; 1334 1335 1336 Long jobNumber = 0L; 1337 String groupKey = "IU-IN"; 1338 Long workArea = 1010L; 1339 Long task = 0L; 1340 HrContext.setTargetPrincipalId(principalId); 1341 DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); 1342 1343 1344 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each. 1345 DateTime start = new DateTime(2010, 3, 21, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 1346 CalendarEntry payCalendarEntry = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start); 1347 1348 TimesheetDocument td = TkTestUtils.populateBlankTimesheetDocument(start, principalId); 1349 1350 List<TimeBlock> blocks = new ArrayList<TimeBlock>(); 1351 1352 //rgh - sunday 3p-5p shift: 2 hr SHDY 1353 DateTime tbStart1 = new DateTime(2010, 3, 28, 15, 0, 0, 0, zone); 1354 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart1, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1355 1356 //rgh - monday 3p-5p - shift: none 1357 DateTime tbStart2 = new DateTime(2010, 3, 29, 15, 0, 0, 0, zone); 1358 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart2, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1359 1360 //rgh - sun 10p- mon 3a - shift: 2hr SHDY2 (on sunday timeblock) 1361 DateTime tbStart3 = new DateTime(2010, 3, 28, 22, 0, 0, 0, zone); 1362 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart3, 1, new BigDecimal("2"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1363 DateTime tbStart4 = new DateTime(2010, 3, 29, 0, 0, 0, 0, zone); 1364 blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart4, 1, new BigDecimal("3"), "RGH", jobNumber, workArea, task, groupKey, td.getDocumentId())); 1365 1366 1367 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry); 1368 1369 // Verify pre-Rule Run 1370 TkTestUtils.verifyAggregateHourSums(principalId, "Pre-Check", new ImmutableMap.Builder<String, BigDecimal>() 1371 .put("RGH", BigDecimal.valueOf(9)).build(), aggregate, 2); 1372 1373 // Run Rule 1374 1375 //td.setTimeBlocks(blocks); 1376 List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(td); 1377 List<TimeBlock> initialBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(td, true); 1378 List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); 1379 1380 //reset time block 1381 //List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(initialBlocks, td.getAsOfDate()); 1382 TimesheetUtils.processTimeBlocksWithRuleChange(blocks, referenceTimeBlocks, leaveBlocks, td.getCalendarEntry(), td, HrContext.getPrincipalId()); 1383 1384 //refresh Timesheet 1385 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(td.getDocumentId()); 1386 aggregate = new TkTimeBlockAggregate(td.getTimeBlocks(), payCalendarEntry); 1387 // Verify post-Rule Run 1388 TkTestUtils.verifyAggregateHourSums(principalId, "Post Rules Check", new ImmutableMap.Builder<String, BigDecimal>() 1389 .put("RGH", BigDecimal.valueOf(9)) 1390 .put("SHDY2", BigDecimal.valueOf(4)).build(), 1391 aggregate, 1392 2); 1393 HrContext.clearTargetUser(); 1394 } 1395}