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