001 /**
002 * Copyright 2004-2012 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 */
016 package org.kuali.hr.time.shiftdiff.rule.service;
017
018 import java.math.BigDecimal;
019 import java.sql.Date;
020 import java.sql.Time;
021 import java.util.ArrayList;
022 import java.util.HashMap;
023 import java.util.List;
024
025 import org.joda.time.DateTime;
026 import org.joda.time.LocalTime;
027 import org.junit.Assert;
028 import org.junit.Ignore;
029 import org.junit.Test;
030 import org.kuali.hr.test.KPMETestCase;
031 import org.kuali.hr.time.calendar.CalendarEntries;
032 import org.kuali.hr.time.service.base.TkServiceLocator;
033 import org.kuali.hr.time.shiftdiff.rule.ShiftDifferentialRule;
034 import org.kuali.hr.time.test.TkTestUtils;
035 import org.kuali.hr.time.timeblock.TimeBlock;
036 import org.kuali.hr.time.timesheet.TimesheetDocument;
037 import org.kuali.hr.time.util.TKUtils;
038 import org.kuali.hr.time.util.TkConstants;
039 import org.kuali.hr.time.util.TkTimeBlockAggregate;
040
041 /**
042 *
043 * @author djunk
044 *
045 */
046 public class ShiftDifferentialRuleServiceProcessTest extends KPMETestCase {
047
048
049 public static final String USER_PRINCIPAL_ID = "admin";
050 private Date JAN_AS_OF_DATE = new Date((new DateTime(2010, 1, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone())).getMillis());
051
052
053 /**
054 * Test with boundary carryover and overlapping rules.
055 *
056 * Rule 1:
057 *
058 * Runs on Tu, Wed, Th on the interval: [22:00, 4:00)
059 * Max Gap: 15 minutes
060 * Min Hours: 3
061 *
062 * Rule 2:
063 *
064 * Runs on Tu, Th on the interval: [23:00, 2:00)
065 * Max Gap: 2 hours
066 * Min Hours: 3
067 *
068 * Rule 3:
069 *
070 * Runs on W, Th on the interval: [5:00, 12:00)
071 * Max Gap: 15 minutes
072 * Min Hours: 7 hours
073 *
074 * Rule 4:
075 *
076 * Runs on W on the interval: [5:00, 12:00)
077 * Max Gap: 15 minutes
078 * Min Hours: 5
079 *
080 *
081 * |--------------+----+------------+------------|
082 * | Tu : 8/31/10 | XX | W : 9/1/10 | Th: 9/2/10 |
083 * |--------------+----+------------+------------|
084 * | 9:45p - 11:45| XX | Mid - 5a | 5p - 11p |
085 * | | XX | 6a - Noon | |
086 * |--------------+----+------------+------------|
087 *
088 *
089 * Aug 31: 2h : 21:45 - 23:45 (Tue) **
090 * [1: 5h 45m] // [2: 2h 45m] - Not qualifying, min hours must be 3.
091 * Sep 1: 5h : 00:00 - 05:00 (Wed) **
092 * Sep 1: 6h : 06:00 - 12:00 (Wed) [4: 6h]
093 *
094 * Sep 1: 2h : 22:00 - 24:00 (Wed)
095 * Sep 2: 1h : 00:00 - 01:00 (Thu) [1: 3h]
096 *
097 * Sep 2: 6h : 17:00 - 22:00 (Thu)
098 *
099 * 1: [22:00, 4:00) (Tue/Wed/Thu) minimum: 3h gap: 15m
100 * 2: [23:00, 2:00) (Tue/Thu) minimum: 3h gap: 2h
101 * 3: [05:00, 12:00) (Wed/Thu) minimum: 7h gap: 15m
102 * 4: [05:00, 12:00) (Wed) minimum: 5h gap: 15m
103 *
104 */
105 @SuppressWarnings("serial")
106 @Test
107 public void testProcessTimesheetBoundaryCarryoverOverlapCase() throws Exception {
108 // Create the Rule Sun, Mon, Tue, Wed, Thu, Fri, Sat
109 boolean[] dayArray = {false, false, true, true, true, true, true};
110 // Matches HR Job ID #1 (job # 30)
111 Long jobNumber = 30L;
112 Long workArea = 0L;
113 this.createShiftDifferentialRule(
114 "BWS-CAL", "REG", "PRM", "SD1", "SD1", "SD1",
115 (new DateTime(2010, 8, 31, 22, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
116 (new DateTime(2010, 8, 31, 4, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
117 new BigDecimal(3), // minHours
118 new BigDecimal("0.25"), // maxGap
119 dayArray);
120
121 dayArray = new boolean [] {false, false, true, false, true, true, true};
122 this.createShiftDifferentialRule(
123 "BWS-CAL", "REG", "PRM", "SD1", "SD1", "SD1",
124 (new DateTime(2010, 8, 31, 23, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
125 (new DateTime(2010, 8, 31, 2, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
126 new BigDecimal(3), // minHours
127 new BigDecimal("2.0"), // maxGap
128 dayArray);
129
130 dayArray = new boolean[] {false, false, false, true, true, false, false};
131 this.createShiftDifferentialRule(
132 "BWS-CAL", "REG", "PRM", "SD1", "SD1", "SD1",
133 (new DateTime(2010, 8, 31, 5, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
134 (new DateTime(2010, 8, 31, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
135 new BigDecimal("7.0"), // minHours
136 new BigDecimal(".25"), // maxGap
137 dayArray);
138 dayArray = new boolean[] {false, false, false, true, false, false, false};
139 this.createShiftDifferentialRule(
140 "BWS-CAL", "REG", "PRM", "SD1", "SD1", "SD1",
141 (new DateTime(2010, 8, 31, 5, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
142 (new DateTime(2010, 8, 31, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
143 new BigDecimal("5"), // minHours
144 new BigDecimal("0.25"), // maxGap
145 dayArray);
146
147 // Timeblocks
148
149 // August
150 Date beginPeriodDate = new Date(new DateTime(2010, 8, 15, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()).getMillis());
151 Date endPeriodDate = new Date(new DateTime(2010, 9, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()).getMillis());
152 CalendarEntries endOfAugust = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesByBeginAndEndDate(beginPeriodDate, endPeriodDate);
153 DateTime start = new DateTime(2010, 8, 31, 21, 45, 0, 0, TKUtils.getSystemDateTimeZone());
154 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
155 TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", endOfAugust);
156 Assert.assertTrue("No Assignments Found.", tdoc.getAssignments().size() > 0);
157 blocks.addAll(TkTestUtils.createUniformActualTimeBlocks(tdoc, tdoc.getAssignments().get(0), "RGN", start, 1, new BigDecimal(2), BigDecimal.ZERO));
158 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, endOfAugust);
159 tdoc.setTimeBlocks(blocks);
160 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
161 TkTestUtils.verifyAggregateHourSumsFlatList("August Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(2));}},aggregate);
162 TkServiceLocator.getTimeBlockService().saveTimeBlocks(new ArrayList<TimeBlock>(), aggregate.getFlattenedTimeBlockList());
163
164
165 // September
166 start = new DateTime(2010, 9, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone());
167 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
168 tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", payCalendarEntry);
169 blocks = new ArrayList<TimeBlock>();
170 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("5"), "RGN", jobNumber, workArea));
171 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(6), 1, new BigDecimal("6"), "RGN", jobNumber, workArea));
172 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(22), 1, new BigDecimal("2"), "RGN", jobNumber, workArea));
173 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusDays(1), 1, new BigDecimal("1"), "RGN", jobNumber, workArea));
174 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusDays(1).plusHours(17), 1, new BigDecimal("6"), "RGN", jobNumber, workArea));
175 setDocumentIdOnBlocks(blocks, tdoc.getDocumentId());
176
177 aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
178
179 TkTestUtils.verifyAggregateHourSumsFlatList("September Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(20));}},aggregate);
180
181 // Verify carry over and applied PRM bucket
182 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
183 TkTestUtils.verifyAggregateHourSumsFlatList("September Post-Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal("14.75"));put("RGN", new BigDecimal(20));}},aggregate);
184 }
185
186 private void setDocumentIdOnBlocks(List<TimeBlock> blocks, String id) {
187 for (TimeBlock b : blocks) {
188 b.setDocumentId(id);
189 }
190 }
191
192
193 /**
194 * Test where previous time sheet contains hours that should be added to
195 * the next pay periods first day shift.
196 *
197 * Runs on Tu, Th on the interval: [22:00, 4:00)
198 * Max Gap: 15 minutes
199 * Min Hours: 3
200 *
201 * |--------------+----+------------+-------------|
202 * | Tu : 8/31/10 | XX | W : 9/1/10 | Th : 9/2/10 |
203 * |--------------+----+------------+-------------|
204 * | 10pm - Mid | XX | Mid - 5am | 5pm - 11pm |
205 * |--------------+----+------------+-------------|
206 *
207 * @throws Exception
208 */
209 @SuppressWarnings("serial")
210 @Test
211 public void testProcessShiftTimesheeetBoundaryCarryoverCase() throws Exception {
212 // Create the Rule Sun, Mon, Tue, Wed, Thu, Fri, Sat
213 boolean[] dayArray = {false, false, true, false, true, true, true};
214 // Matches HR Job ID #1 (job # 30)
215 Long jobNumber = 30L;
216 Long workArea = 0L;
217 this.createShiftDifferentialRule(
218 "BWS-CAL",
219 "REG",
220 "PRM",
221 "SD1",
222 "SD1",
223 "SD1",
224 (new DateTime(2010, 8, 31, 22, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
225 (new DateTime(2010, 8, 31, 5, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
226 new BigDecimal(3), // minHours
227 new BigDecimal("0.25"), // maxGap
228 dayArray);
229
230 // August
231 Date beginPeriodDate = new Date(new DateTime(2010, 8, 15, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()).getMillis());
232 Date endPeriodDate = new Date(new DateTime(2010, 9, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()).getMillis());
233 CalendarEntries endOfAugust = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesByBeginAndEndDate(beginPeriodDate, endPeriodDate);
234 DateTime start = new DateTime(2010, 8, 31, 22, 0, 0, 0, TKUtils.getSystemDateTimeZone());
235 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
236 TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", endOfAugust);
237 Assert.assertTrue("No Assignments Found.", tdoc.getAssignments().size() > 0);
238 blocks.addAll(TkTestUtils.createUniformActualTimeBlocks(tdoc, tdoc.getAssignments().get(0), "RGN", start, 1, new BigDecimal(2), BigDecimal.ZERO));
239 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, endOfAugust);
240
241
242
243 tdoc.setTimeBlocks(blocks);
244 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
245 TkTestUtils.verifyAggregateHourSumsFlatList("August Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(2));}},aggregate);
246 TkServiceLocator.getTimeBlockService().saveTimeBlocks(new ArrayList<TimeBlock>(), aggregate.getFlattenedTimeBlockList());
247
248
249 // September
250 start = new DateTime(2010, 9, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone());
251 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
252 tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", payCalendarEntry);
253 blocks = new ArrayList<TimeBlock>();
254 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("5"), "RGN", jobNumber, workArea));
255 aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
256 TkTestUtils.verifyAggregateHourSumsFlatList("September Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(5));}},aggregate);
257
258 // Verify carry over and applied PRM bucket
259 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
260 TkTestUtils.verifyAggregateHourSumsFlatList("September Post-Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(7));put("RGN", new BigDecimal(5));}},aggregate);
261 }
262
263 @SuppressWarnings("serial")
264 @Test
265 /**
266 * Runs on every day on the interval: [16:00, 24:00)
267 * Max Gap: 15 minutes
268 * Min Hours: 4
269 *
270 * Added some extra time blocks that are not in the shift interval, but
271 * close to the time blocks that are.
272 *
273 * @throws Exception
274 */
275 public void testProcessShiftSimpleNoisyCase() throws Exception {
276 // Create the Rule
277 boolean[] dayArray = {true, true, true, true, true, true, true};
278 // Matches HR Job ID #1 (job # 30)
279 Long jobNumber = 30L;
280 Long workArea = 0L;
281 this.createShiftDifferentialRule(
282 "BWS-CAL",
283 "REG",
284 "PRM",
285 "SD1",
286 "SD1",
287 "SD1",
288 (new DateTime(2010, 3, 29, 16, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
289 (new DateTime(2010, 3, 30, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
290 new BigDecimal(4), // minHours
291 new BigDecimal("0.25"), // maxGap
292 dayArray);
293
294 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each.
295 DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, TKUtils.getSystemDateTimeZone());
296 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
297 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
298 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 2, new BigDecimal("4"), "RGN", jobNumber, workArea));
299 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(4).plusMinutes(15), 2, new BigDecimal("2"), "RGN", jobNumber, workArea));
300 blocks.addAll(TkTestUtils.createUniformTimeBlocks(new DateTime(2010, 3, 29, 12, 58, 0, 0, TKUtils.getSystemDateTimeZone()), 2, new BigDecimal(1), "RGN", jobNumber, workArea));
301 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
302
303 // Verify pre-Rule Run
304 TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(14));}},aggregate,2);
305
306 // Run Rule
307 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
308 tdoc.setTimeBlocks(blocks);
309 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
310
311 // Verify post-Rule Run
312 TkTestUtils.verifyAggregateHourSums("Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("RGN", new BigDecimal(14));}},aggregate,2);
313 }
314
315 @SuppressWarnings("serial")
316 @Test
317 /**
318 * Runs on every day on the interval: [16:00, 24:00)
319 * Max Gap: 15 minutes
320 * Min Hours: 4
321 *
322 * @throws Exception
323 */
324 public void testProcessShiftSimpleCase() throws Exception {
325 // Create the Rule
326 boolean[] dayArray = {true, true, true, true, true, true, true};
327 // Matches HR Job ID #1 (job # 30)
328 Long jobNumber = 30L;
329 Long workArea = 0L;
330 this.createShiftDifferentialRule(
331 "BWS-CAL",
332 "REG",
333 "PRM",
334 "SD1",
335 "SD1",
336 "SD1",
337 (new DateTime(2010, 3, 29, 16, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
338 (new DateTime(2010, 3, 30, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
339 new BigDecimal(4), // minHours
340 new BigDecimal("0.25"), // maxGap
341 dayArray);
342
343 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each.
344 DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, TKUtils.getSystemDateTimeZone());
345 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
346 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
347 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 2, new BigDecimal("4"), "REG", jobNumber, workArea));
348 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(4).plusMinutes(15), 2, new BigDecimal("2"), "REG", jobNumber, workArea));
349 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
350
351 // Verify pre-Rule Run
352 TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(12));}},aggregate,2);
353
354 // Run Rule
355 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
356 tdoc.setTimeBlocks(blocks);
357 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
358
359 // Verify post-Rule Run
360 TkTestUtils.verifyAggregateHourSums("Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("REG", new BigDecimal(12));}},aggregate,2);
361 }
362
363 /**
364 * Stores the Shift Differential Rule in the database for testing.
365 *
366 * dayBooleans[] is a 7 element array of booleans, [0, 6] is [sun, sat]
367 */
368 private void createShiftDifferentialRule(String pyCalendarGroup, String fromEarnGroup, String premiumEarnCode, String location, String payGrade, String hrSalGroup, DateTime startTime, DateTime endTime, BigDecimal minHours, BigDecimal maxGap, boolean dayBooleans[]) {
369 Assert.assertTrue("Wrong number of day booleans", dayBooleans.length == 7);
370
371 ShiftDifferentialRuleService service = TkServiceLocator.getShiftDifferentialRuleService();
372 ShiftDifferentialRule sdr = new ShiftDifferentialRule();
373
374 sdr.setBeginTime(new Time(startTime.getMillis()));
375 sdr.setEndTime(new Time(endTime.getMillis()));
376 sdr.setMinHours(minHours);
377 sdr.setMaxGap(maxGap);
378 sdr.setActive(true);
379 sdr.setUserPrincipalId(USER_PRINCIPAL_ID);
380 sdr.setEffectiveDate(JAN_AS_OF_DATE);
381 sdr.setLocation(location);
382 sdr.setPayGrade(payGrade);
383 sdr.setHrSalGroup(hrSalGroup);
384 sdr.setFromEarnGroup(fromEarnGroup);
385 sdr.setPyCalendarGroup(pyCalendarGroup);
386 sdr.setEarnCode(premiumEarnCode);
387
388 for (int i=0; i<dayBooleans.length; i++) {
389 switch(i) {
390 case 0:
391 sdr.setSunday(dayBooleans[i]);
392 break;
393 case 1:
394 sdr.setMonday(dayBooleans[i]);
395 break;
396 case 2:
397 sdr.setTuesday(dayBooleans[i]);
398 break;
399 case 3:
400 sdr.setWednesday(dayBooleans[i]);
401 break;
402 case 4:
403 sdr.setThursday(dayBooleans[i]);
404 break;
405 case 5:
406 sdr.setFriday(dayBooleans[i]);
407 break;
408 case 6:
409 sdr.setSaturday(dayBooleans[i]);
410 break;
411 }
412 }
413
414 service.saveOrUpdate(sdr);
415
416 ShiftDifferentialRule sdrBack = TkServiceLocator.getShiftDifferentialRuleService().getShiftDifferentialRule(sdr.getTkShiftDiffRuleId());
417
418 LocalTime orig_start = new LocalTime(sdr.getBeginTime(), TKUtils.getSystemDateTimeZone());
419 LocalTime orig_end = new LocalTime(sdr.getEndTime(), TKUtils.getSystemDateTimeZone());
420
421 LocalTime stored_start = new LocalTime(sdrBack.getBeginTime(), TKUtils.getSystemDateTimeZone());
422 LocalTime stored_end = new LocalTime(sdrBack.getEndTime(), TKUtils.getSystemDateTimeZone());
423
424 Assert.assertTrue("Start times not equal.", orig_start.equals(stored_start));
425 Assert.assertTrue("End times not equal.", orig_end.equals(stored_end));
426 }
427
428
429 @Ignore
430 @Test
431 /**
432 * Tests WorkSchedules impact on Shift Differential Rule: Simple Case
433 *
434 * Create a timeblock on two days, one day has normal REG shift eligible
435 * hours, one day has HOL time.
436 *
437 * Modified version of the simple case, SDR from 12:00 to 17:00, every day,
438 * must have at least 4 hours with a maximum 15 minute gap.
439 *
440 */
441 public void simpleCaseWithWorkSchedule() throws Exception {
442 // Create the Rule
443 boolean[] dayArray = {true, true, true, true, true, true, true};
444 // Matches HR Job ID #1 (job # 30)
445 Long jobNumber = 30L;
446 Long workArea = 0L;
447 this.createShiftDifferentialRule(
448 "BWS-CAL",
449 "REG",
450 "PRM",
451 "SD1",
452 "SD1",
453 "SD1",
454 (new DateTime(2010, 3, 29, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
455 (new DateTime(2010, 3, 29, 17, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
456 new BigDecimal(4), // minHours
457 new BigDecimal("0.25"), // maxGap
458 dayArray);
459
460 // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours total each.
461 DateTime start = new DateTime(2010, 3, 29, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone());
462 DateTime holtime = new DateTime(2010, 3, 30, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone());
463 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
464 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
465 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("4"), "REG", jobNumber, workArea));
466 blocks.addAll(TkTestUtils.createUniformTimeBlocks(holtime, 1, new BigDecimal("4"), "HOL", jobNumber, workArea));
467
468 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
469
470 // Verify pre-Rule Run
471 TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(4));put("HOL", new BigDecimal(4));}},aggregate,2);
472
473 // Run Rule
474 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
475 tdoc.setTimeBlocks(blocks);
476 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
477
478 // Verify post-Rule Run
479 TkTestUtils.verifyAggregateHourSums("Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("REG", new BigDecimal(4));}},aggregate,2);
480
481 }
482
483 }