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     */
016    package org.kuali.hr.time.shiftdiff.rule;
017    
018    import java.math.BigDecimal;
019    import java.sql.Time;
020    import java.util.ArrayList;
021    import java.util.HashMap;
022    import java.util.List;
023    
024    import org.joda.time.DateTime;
025    import org.joda.time.DateTimeZone;
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.KPMEWebTestCase;
031    import org.kuali.kpme.core.FunctionalTest;
032    import org.kuali.kpme.core.assignment.Assignment;
033    import org.kuali.kpme.core.assignment.AssignmentDescriptionKey;
034    import org.kuali.kpme.core.calendar.entry.CalendarEntry;
035    import org.kuali.kpme.core.service.HrServiceLocator;
036    import org.kuali.kpme.core.util.TKUtils;
037    import org.kuali.kpme.tklm.time.rules.shiftdifferential.ShiftDifferentialRule;
038    import org.kuali.kpme.tklm.time.rules.shiftdifferential.service.ShiftDifferentialRuleService;
039    import org.kuali.kpme.tklm.time.service.TkServiceLocator;
040    import org.kuali.kpme.tklm.time.timeblock.TimeBlock;
041    import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
042    import org.kuali.kpme.tklm.time.util.TkTimeBlockAggregate;
043    import org.kuali.kpme.tklm.utils.TkTestUtils;
044    
045    /**
046     *
047     * @author djunk
048     *
049     */
050    @FunctionalTest
051    public 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    }