1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 @SuppressWarnings("serial")
106 @Test
107 public void testProcessTimesheetBoundaryCarryoverOverlapCase() throws Exception {
108
109 boolean[] dayArray = {false, false, true, true, true, true, true};
110
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),
118 new BigDecimal("0.25"),
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),
127 new BigDecimal("2.0"),
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"),
136 new BigDecimal(".25"),
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"),
144 new BigDecimal("0.25"),
145 dayArray);
146
147
148
149
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
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
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 @SuppressWarnings("serial")
210 @Test
211 public void testProcessShiftTimesheeetBoundaryCarryoverCase() throws Exception {
212
213 boolean[] dayArray = {false, false, true, false, true, true, true};
214
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),
227 new BigDecimal("0.25"),
228 dayArray);
229
230
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
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
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
267
268
269
270
271
272
273
274
275 public void testProcessShiftSimpleNoisyCase() throws Exception {
276
277 boolean[] dayArray = {true, true, true, true, true, true, true};
278
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),
291 new BigDecimal("0.25"),
292 dayArray);
293
294
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
304 TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(14));}},aggregate,2);
305
306
307 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
308 tdoc.setTimeBlocks(blocks);
309 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
310
311
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
319
320
321
322
323
324 public void testProcessShiftSimpleCase() throws Exception {
325
326 boolean[] dayArray = {true, true, true, true, true, true, true};
327
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),
340 new BigDecimal("0.25"),
341 dayArray);
342
343
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
352 TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(12));}},aggregate,2);
353
354
355 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
356 tdoc.setTimeBlocks(blocks);
357 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
358
359
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
365
366
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
433
434
435
436
437
438
439
440
441 public void simpleCaseWithWorkSchedule() throws Exception {
442
443 boolean[] dayArray = {true, true, true, true, true, true, true};
444
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),
457 new BigDecimal("0.25"),
458 dayArray);
459
460
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
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
474 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
475 tdoc.setTimeBlocks(blocks);
476 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
477
478
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 }