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.assignment.Assignment;
32 import org.kuali.hr.time.assignment.AssignmentDescriptionKey;
33 import org.kuali.hr.time.calendar.CalendarEntries;
34 import org.kuali.hr.time.service.base.TkServiceLocator;
35 import org.kuali.hr.time.shiftdiff.rule.ShiftDifferentialRule;
36 import org.kuali.hr.time.test.TkTestUtils;
37 import org.kuali.hr.time.timeblock.TimeBlock;
38 import org.kuali.hr.time.timesheet.TimesheetDocument;
39 import org.kuali.hr.time.util.TKUtils;
40 import org.kuali.hr.time.util.TkConstants;
41 import org.kuali.hr.time.util.TkTimeBlockAggregate;
42
43
44
45
46
47
48 public class ShiftDifferentialRuleServiceProcessTest extends KPMETestCase {
49
50
51 public static final String USER_PRINCIPAL_ID = "admin";
52 private Date JAN_AS_OF_DATE = new Date((new DateTime(2010, 1, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone())).getMillis());
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
106
107 @SuppressWarnings("serial")
108 @Test
109 public void testProcessTimesheetBoundaryCarryoverOverlapCase() throws Exception {
110
111 boolean[] dayArray = {false, false, true, true, true, true, true};
112
113 Long jobNumber = 30L;
114 Long workArea = 0L;
115 this.createShiftDifferentialRule(
116 "BWS-CAL", "REG", "PRM", "SD1", "SD1", "SD1",
117 (new DateTime(2010, 8, 31, 22, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
118 (new DateTime(2010, 8, 31, 4, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
119 new BigDecimal(3),
120 new BigDecimal("0.25"),
121 dayArray);
122
123 dayArray = new boolean [] {false, false, true, false, true, true, true};
124 this.createShiftDifferentialRule(
125 "BWS-CAL", "REG", "PRM", "SD1", "SD1", "SD1",
126 (new DateTime(2010, 8, 31, 23, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
127 (new DateTime(2010, 8, 31, 2, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
128 new BigDecimal(3),
129 new BigDecimal("2.0"),
130 dayArray);
131
132 dayArray = new boolean[] {false, false, false, true, true, false, false};
133 this.createShiftDifferentialRule(
134 "BWS-CAL", "REG", "PRM", "SD1", "SD1", "SD1",
135 (new DateTime(2010, 8, 31, 5, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
136 (new DateTime(2010, 8, 31, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
137 new BigDecimal("7.0"),
138 new BigDecimal(".25"),
139 dayArray);
140 dayArray = new boolean[] {false, false, false, true, false, false, false};
141 this.createShiftDifferentialRule(
142 "BWS-CAL", "REG", "PRM", "SD1", "SD1", "SD1",
143 (new DateTime(2010, 8, 31, 5, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
144 (new DateTime(2010, 8, 31, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
145 new BigDecimal("5"),
146 new BigDecimal("0.25"),
147 dayArray);
148
149
150
151
152 Date beginPeriodDate = new Date(new DateTime(2010, 8, 15, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()).getMillis());
153 Date endPeriodDate = new Date(new DateTime(2010, 9, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()).getMillis());
154 CalendarEntries endOfAugust = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesByBeginAndEndDate(beginPeriodDate, endPeriodDate);
155 DateTime start = new DateTime(2010, 8, 31, 21, 45, 0, 0, TKUtils.getSystemDateTimeZone());
156 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
157 TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", endOfAugust);
158 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment("admin", new AssignmentDescriptionKey("30_30_30"), beginPeriodDate);
159 blocks.addAll(TkTestUtils.createUniformActualTimeBlocks(tdoc, assignment, "RGN", start, 1, new BigDecimal(2), BigDecimal.ZERO));
160 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, endOfAugust);
161 tdoc.setTimeBlocks(blocks);
162 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
163 TkTestUtils.verifyAggregateHourSumsFlatList("August Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(2));}},aggregate);
164 TkServiceLocator.getTimeBlockService().saveTimeBlocks(new ArrayList<TimeBlock>(), aggregate.getFlattenedTimeBlockList());
165
166
167
168 start = new DateTime(2010, 9, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone());
169 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
170 tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", payCalendarEntry);
171 blocks = new ArrayList<TimeBlock>();
172 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("5"), "RGN", jobNumber, workArea));
173 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(6), 1, new BigDecimal("6"), "RGN", jobNumber, workArea));
174 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(22), 1, new BigDecimal("2"), "RGN", jobNumber, workArea));
175 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusDays(1), 1, new BigDecimal("1"), "RGN", jobNumber, workArea));
176 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusDays(1).plusHours(17), 1, new BigDecimal("6"), "RGN", jobNumber, workArea));
177 setDocumentIdOnBlocks(blocks, tdoc.getDocumentId());
178
179 aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
180
181 TkTestUtils.verifyAggregateHourSumsFlatList("September Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(20));}},aggregate);
182
183
184 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
185 TkTestUtils.verifyAggregateHourSumsFlatList("September Post-Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal("14.75"));put("RGN", new BigDecimal(20));}},aggregate);
186 }
187
188 private void setDocumentIdOnBlocks(List<TimeBlock> blocks, String id) {
189 for (TimeBlock b : blocks) {
190 b.setDocumentId(id);
191 }
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 @SuppressWarnings("serial")
212 @Test
213 public void testProcessShiftTimesheeetBoundaryCarryoverCase() throws Exception {
214
215 boolean[] dayArray = {false, false, true, false, true, true, true};
216
217 Long jobNumber = 30L;
218 Long workArea = 0L;
219 this.createShiftDifferentialRule(
220 "BWS-CAL",
221 "REG",
222 "PRM",
223 "SD1",
224 "SD1",
225 "SD1",
226 (new DateTime(2010, 8, 31, 22, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
227 (new DateTime(2010, 8, 31, 5, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
228 new BigDecimal(3),
229 new BigDecimal("0.25"),
230 dayArray);
231
232
233 Date beginPeriodDate = new Date(new DateTime(2010, 8, 15, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()).getMillis());
234 Date endPeriodDate = new Date(new DateTime(2010, 9, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()).getMillis());
235 CalendarEntries endOfAugust = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesByBeginAndEndDate(beginPeriodDate, endPeriodDate);
236 DateTime start = new DateTime(2010, 8, 31, 22, 0, 0, 0, TKUtils.getSystemDateTimeZone());
237 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
238 TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", endOfAugust);
239 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment("admin", new AssignmentDescriptionKey("30_30_30"), beginPeriodDate);
240 blocks.addAll(TkTestUtils.createUniformActualTimeBlocks(tdoc, assignment, "RGN", start, 1, new BigDecimal(2), BigDecimal.ZERO));
241 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, endOfAugust);
242
243
244
245 tdoc.setTimeBlocks(blocks);
246 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
247 TkTestUtils.verifyAggregateHourSumsFlatList("August Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(2));}},aggregate);
248 TkServiceLocator.getTimeBlockService().saveTimeBlocks(new ArrayList<TimeBlock>(), aggregate.getFlattenedTimeBlockList());
249
250
251
252 start = new DateTime(2010, 9, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone());
253 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
254 tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument("admin", payCalendarEntry);
255 blocks = new ArrayList<TimeBlock>();
256 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("5"), "RGN", jobNumber, workArea));
257 aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
258 TkTestUtils.verifyAggregateHourSumsFlatList("September Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(5));}},aggregate);
259
260
261 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
262 TkTestUtils.verifyAggregateHourSumsFlatList("September Post-Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(7));put("RGN", new BigDecimal(5));}},aggregate);
263 }
264
265 @SuppressWarnings("serial")
266 @Test
267
268
269
270
271
272
273
274
275
276
277 public void testProcessShiftSimpleNoisyCase() throws Exception {
278
279 boolean[] dayArray = {true, true, true, true, true, true, true};
280
281 Long jobNumber = 30L;
282 Long workArea = 0L;
283 this.createShiftDifferentialRule(
284 "BWS-CAL",
285 "REG",
286 "PRM",
287 "SD1",
288 "SD1",
289 "SD1",
290 (new DateTime(2010, 3, 29, 16, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
291 (new DateTime(2010, 3, 30, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
292 new BigDecimal(4),
293 new BigDecimal("15"),
294 dayArray);
295
296
297 DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, TKUtils.getSystemDateTimeZone());
298 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
299 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
300 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 2, new BigDecimal("4"), "RGN", jobNumber, workArea));
301 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(4).plusMinutes(15), 2, new BigDecimal("2"), "RGN", jobNumber, workArea));
302 blocks.addAll(TkTestUtils.createUniformTimeBlocks(new DateTime(2010, 3, 29, 12, 58, 0, 0, TKUtils.getSystemDateTimeZone()), 2, new BigDecimal(1), "RGN", jobNumber, workArea));
303 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
304
305
306 TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("RGN", new BigDecimal(14));}},aggregate,2);
307
308
309 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
310 tdoc.setTimeBlocks(blocks);
311 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
312
313
314 TkTestUtils.verifyAggregateHourSums("Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("RGN", new BigDecimal(14));}},aggregate,2);
315 }
316
317 @SuppressWarnings("serial")
318 @Test
319
320
321
322
323
324
325
326 public void testProcessShiftSimpleCase() throws Exception {
327
328 boolean[] dayArray = {true, true, true, true, true, true, true};
329
330 Long jobNumber = 30L;
331 Long workArea = 0L;
332 this.createShiftDifferentialRule(
333 "BWS-CAL",
334 "REG",
335 "PRM",
336 "SD1",
337 "SD1",
338 "SD1",
339 (new DateTime(2010, 3, 29, 16, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
340 (new DateTime(2010, 3, 30, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
341 new BigDecimal(4),
342 new BigDecimal("15"),
343 dayArray);
344
345
346 DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, TKUtils.getSystemDateTimeZone());
347 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
348 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
349 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 2, new BigDecimal("4"), "REG", jobNumber, workArea));
350 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start.plusHours(4).plusMinutes(15), 2, new BigDecimal("2"), "REG", jobNumber, workArea));
351 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
352
353
354 TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(12));}},aggregate,2);
355
356
357 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
358 tdoc.setTimeBlocks(blocks);
359 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
360
361
362 TkTestUtils.verifyAggregateHourSums("Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("REG", new BigDecimal(12));}},aggregate,2);
363 }
364
365
366
367
368
369
370 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[]) {
371 Assert.assertTrue("Wrong number of day booleans", dayBooleans.length == 7);
372
373 ShiftDifferentialRuleService service = TkServiceLocator.getShiftDifferentialRuleService();
374 ShiftDifferentialRule sdr = new ShiftDifferentialRule();
375
376 sdr.setBeginTime(new Time(startTime.getMillis()));
377 sdr.setEndTime(new Time(endTime.getMillis()));
378 sdr.setMinHours(minHours);
379 sdr.setMaxGap(maxGap);
380 sdr.setActive(true);
381 sdr.setUserPrincipalId(USER_PRINCIPAL_ID);
382 sdr.setEffectiveDate(JAN_AS_OF_DATE);
383 sdr.setLocation(location);
384 sdr.setPayGrade(payGrade);
385 sdr.setHrSalGroup(hrSalGroup);
386 sdr.setFromEarnGroup(fromEarnGroup);
387 sdr.setPyCalendarGroup(pyCalendarGroup);
388 sdr.setEarnCode(premiumEarnCode);
389
390 for (int i=0; i<dayBooleans.length; i++) {
391 switch(i) {
392 case 0:
393 sdr.setSunday(dayBooleans[i]);
394 break;
395 case 1:
396 sdr.setMonday(dayBooleans[i]);
397 break;
398 case 2:
399 sdr.setTuesday(dayBooleans[i]);
400 break;
401 case 3:
402 sdr.setWednesday(dayBooleans[i]);
403 break;
404 case 4:
405 sdr.setThursday(dayBooleans[i]);
406 break;
407 case 5:
408 sdr.setFriday(dayBooleans[i]);
409 break;
410 case 6:
411 sdr.setSaturday(dayBooleans[i]);
412 break;
413 }
414 }
415
416 service.saveOrUpdate(sdr);
417
418 ShiftDifferentialRule sdrBack = TkServiceLocator.getShiftDifferentialRuleService().getShiftDifferentialRule(sdr.getTkShiftDiffRuleId());
419
420 LocalTime orig_start = new LocalTime(sdr.getBeginTime(), TKUtils.getSystemDateTimeZone());
421 LocalTime orig_end = new LocalTime(sdr.getEndTime(), TKUtils.getSystemDateTimeZone());
422
423 LocalTime stored_start = new LocalTime(sdrBack.getBeginTime(), TKUtils.getSystemDateTimeZone());
424 LocalTime stored_end = new LocalTime(sdrBack.getEndTime(), TKUtils.getSystemDateTimeZone());
425
426 Assert.assertTrue("Start times not equal.", orig_start.equals(stored_start));
427 Assert.assertTrue("End times not equal.", orig_end.equals(stored_end));
428 }
429
430
431 @Ignore
432 @Test
433
434
435
436
437
438
439
440
441
442
443 public void simpleCaseWithWorkSchedule() throws Exception {
444
445 boolean[] dayArray = {true, true, true, true, true, true, true};
446
447 Long jobNumber = 30L;
448 Long workArea = 0L;
449 this.createShiftDifferentialRule(
450 "BWS-CAL",
451 "REG",
452 "PRM",
453 "SD1",
454 "SD1",
455 "SD1",
456 (new DateTime(2010, 3, 29, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
457 (new DateTime(2010, 3, 29, 17, 0, 0, 0, TKUtils.getSystemDateTimeZone())),
458 new BigDecimal(4),
459 new BigDecimal("0.25"),
460 dayArray);
461
462
463 DateTime start = new DateTime(2010, 3, 29, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone());
464 DateTime holtime = new DateTime(2010, 3, 30, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone());
465 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
466 CalendarEntries payCalendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDates("admin", new Date(start.getMillis()));
467 blocks.addAll(TkTestUtils.createUniformTimeBlocks(start, 1, new BigDecimal("4"), "REG", jobNumber, workArea));
468 blocks.addAll(TkTestUtils.createUniformTimeBlocks(holtime, 1, new BigDecimal("4"), "HOL", jobNumber, workArea));
469
470 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
471
472
473 TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("PRM", BigDecimal.ZERO);put("REG", new BigDecimal(4));put("HOL", new BigDecimal(4));}},aggregate,2);
474
475
476 TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(new Date(start.getMillis()));
477 tdoc.setTimeBlocks(blocks);
478 TkServiceLocator.getShiftDifferentialRuleService().processShiftDifferentialRules(tdoc, aggregate);
479
480
481 TkTestUtils.verifyAggregateHourSums("Post Rules Check", new HashMap<String,BigDecimal>() {{put("PRM", new BigDecimal(8));put("REG", new BigDecimal(4));}},aggregate,2);
482
483 }
484
485 }