View Javadoc

1   /**
2    * Copyright 2004-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.hr.time.shiftdiff.rule.service;
17  
18  import java.math.BigDecimal;
19  import java.sql.Date;
20  import java.sql.Time;
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.List;
24  
25  import org.joda.time.DateTime;
26  import org.joda.time.LocalTime;
27  import org.junit.Assert;
28  import org.junit.Ignore;
29  import org.junit.Test;
30  import org.kuali.hr.test.KPMETestCase;
31  import org.kuali.hr.time.calendar.CalendarEntries;
32  import org.kuali.hr.time.service.base.TkServiceLocator;
33  import org.kuali.hr.time.shiftdiff.rule.ShiftDifferentialRule;
34  import org.kuali.hr.time.test.TkTestUtils;
35  import org.kuali.hr.time.timeblock.TimeBlock;
36  import org.kuali.hr.time.timesheet.TimesheetDocument;
37  import org.kuali.hr.time.util.TKUtils;
38  import org.kuali.hr.time.util.TkConstants;
39  import org.kuali.hr.time.util.TkTimeBlockAggregate;
40  
41  /**
42   *
43   * @author djunk
44   *
45   */
46  public class ShiftDifferentialRuleServiceProcessTest extends KPMETestCase {
47  
48  
49  	public static final String USER_PRINCIPAL_ID = "admin";
50  	private Date JAN_AS_OF_DATE = new Date((new DateTime(2010, 1, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone())).getMillis());
51  
52  
53  	/**
54  	 * Test with boundary carryover and overlapping rules.
55  	 *
56  	 * Rule 1:
57  	 *
58  	 * Runs on Tu, Wed, Th on the interval: [22:00, 4:00)
59  	 * Max Gap: 15 minutes
60  	 * Min Hours: 3
61  	 *
62  	 * Rule 2:
63  	 *
64  	 * Runs on Tu, Th on the interval: [23:00, 2:00)
65  	 * Max Gap: 2 hours
66  	 * Min Hours: 3
67  	 *
68  	 * Rule 3:
69  	 *
70  	 * Runs on W, Th on the interval: [5:00, 12:00)
71  	 * Max Gap: 15 minutes
72  	 * Min Hours: 7 hours
73  	 *
74  	 * Rule 4:
75  	 *
76  	 * Runs on W on the interval: [5:00, 12:00)
77  	 * Max Gap: 15 minutes
78  	 * Min Hours: 5
79  	 *
80  	 *
81  	 * |--------------+----+------------+------------|
82  	 * | Tu : 8/31/10 | XX | W : 9/1/10 | Th: 9/2/10 |
83  	 * |--------------+----+------------+------------|
84  	 * | 9:45p - 11:45| XX | Mid - 5a   | 5p - 11p   |
85  	 * |              | XX | 6a - Noon  |            |
86  	 * |--------------+----+------------+------------|
87       *
88       *
89       * Aug 31: 2h  : 21:45 - 23:45 (Tue) **
90       *                           [1: 5h 45m]  // [2: 2h 45m] - Not qualifying, min hours must be 3.
91       * Sep  1: 5h  : 00:00 - 05:00 (Wed) **
92       * Sep  1: 6h  : 06:00 - 12:00 (Wed) [4: 6h]
93       *
94       * Sep  1: 2h  : 22:00 - 24:00 (Wed)
95       * Sep  2: 1h  : 00:00 - 01:00 (Thu) [1: 3h]
96       *
97       * Sep  2: 6h  : 17:00 - 22:00 (Thu)
98       *
99       * 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 }