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 org.apache.log4j.Logger;
19 import org.joda.time.*;
20 import org.kuali.hr.job.Job;
21 import org.kuali.hr.time.calendar.CalendarEntries;
22 import org.kuali.hr.time.principal.PrincipalHRAttributes;
23 import org.kuali.hr.time.service.base.TkServiceLocator;
24 import org.kuali.hr.time.shiftdiff.rule.ShiftDifferentialRule;
25 import org.kuali.hr.time.shiftdiff.rule.dao.ShiftDifferentialRuleDao;
26 import org.kuali.hr.time.timeblock.TimeBlock;
27 import org.kuali.hr.time.timeblock.TimeHourDetail;
28 import org.kuali.hr.time.timesheet.TimesheetDocument;
29 import org.kuali.hr.time.util.TKUtils;
30 import org.kuali.hr.time.util.TkConstants;
31 import org.kuali.hr.time.util.TkTimeBlockAggregate;
32 import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
33
34 import java.math.BigDecimal;
35 import java.sql.Date;
36 import java.util.*;
37
38
39 public class ShiftDifferentialRuleServiceImpl implements ShiftDifferentialRuleService {
40
41 @SuppressWarnings("unused")
42 private static final Logger LOG = Logger.getLogger(ShiftDifferentialRuleServiceImpl.class);
43
44
45
46
47 private ShiftDifferentialRuleDao shiftDifferentialRuleDao = null;
48
49 private Map<Long,List<ShiftDifferentialRule>> getJobNumberToShiftRuleMap(TimesheetDocument timesheetDocument) {
50 Map<Long,List<ShiftDifferentialRule>> jobNumberToShifts = new HashMap<Long,List<ShiftDifferentialRule>>();
51 PrincipalHRAttributes principalCal = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(timesheetDocument.getPrincipalId(),timesheetDocument.getPayCalendarEntry().getEndPeriodDate());
52
53 for (Job job : timesheetDocument.getJobs()) {
54 List<ShiftDifferentialRule> shiftDifferentialRules = getShiftDifferentalRules(job.getLocation(),job.getHrSalGroup(),job.getPayGrade(),principalCal.getPayCalendar(),
55 TKUtils.getTimelessDate(timesheetDocument.getPayCalendarEntry().getBeginPeriodDateTime()));
56 if (shiftDifferentialRules.size() > 0)
57 jobNumberToShifts.put(job.getJobNumber(), shiftDifferentialRules);
58 }
59
60 return jobNumberToShifts;
61 }
62
63 private Map<Long,List<TimeBlock>> getPreviousPayPeriodLastDayJobToTimeBlockMap(TimesheetDocument timesheetDocument, Map<Long,List<ShiftDifferentialRule>> jobNumberToShifts) {
64 Map<Long, List<TimeBlock>> jobNumberToTimeBlocksPreviousDay = null;
65
66
67
68 List<TimeBlock> prevBlocks = TkServiceLocator.getTimesheetService().getPrevDocumentTimeBlocks(timesheetDocument.getPrincipalId(), timesheetDocument.getDocumentHeader().getPayBeginDate());
69 if (prevBlocks.size() > 0) {
70 TimesheetDocumentHeader prevTdh = TkServiceLocator.getTimesheetDocumentHeaderService().getPreviousDocumentHeader(timesheetDocument.getPrincipalId(), timesheetDocument.getDocumentHeader().getPayBeginDate());
71 if (prevTdh != null) {
72 CalendarEntries prevPayCalendarEntry = TkServiceLocator.getCalendarService().getCalendarDatesByPayEndDate(timesheetDocument.getPrincipalId(), prevTdh.getPayEndDate(), null);
73 TkTimeBlockAggregate prevTimeAggregate = new TkTimeBlockAggregate(prevBlocks, prevPayCalendarEntry, prevPayCalendarEntry.getCalendarObj(), true);
74 List<List<TimeBlock>> dayBlocks = prevTimeAggregate.getDayTimeBlockList();
75 List<TimeBlock> previousPeriodLastDayBlocks = dayBlocks.get(dayBlocks.size() - 1);
76
77 if (previousPeriodLastDayBlocks.size() > 0) {
78 jobNumberToTimeBlocksPreviousDay = new HashMap<Long, List<TimeBlock>>();
79
80 for (TimeBlock block : previousPeriodLastDayBlocks) {
81
82
83 Long jobNumber = block.getJobNumber();
84 if (jobNumberToShifts.containsKey(jobNumber)) {
85
86 List<TimeBlock> jblist = jobNumberToTimeBlocksPreviousDay.get(jobNumber);
87 if (jblist == null) {
88 jblist = new ArrayList<TimeBlock>();
89 jobNumberToTimeBlocksPreviousDay.put(jobNumber, jblist);
90 }
91 jblist.add(block);
92 }
93 }
94 }
95 }
96 }
97
98 return jobNumberToTimeBlocksPreviousDay;
99 }
100
101 private boolean timeBlockHasEarnCode(Set<String> earnCodes, TimeBlock block) {
102 boolean present = false;
103
104 if (block != null && earnCodes != null)
105 present = earnCodes.contains(block.getEarnCode());
106
107 return present;
108 }
109
110
111
112
113
114
115
116
117
118
119 private BigDecimal negativeTimeHourDetailSum(TimeBlock block) {
120 BigDecimal sum = BigDecimal.ZERO;
121
122 if (block != null) {
123 List<TimeHourDetail> details = block.getTimeHourDetails();
124 for (TimeHourDetail detail : details) {
125 if (detail.getEarnCode().equals(TkConstants.LUNCH_EARN_CODE)) {
126 sum = sum.add(detail.getHours());
127 }
128 }
129 }
130
131 return sum;
132 }
133
134 @Override
135 public void processShiftDifferentialRules(TimesheetDocument timesheetDocument, TkTimeBlockAggregate aggregate) {
136 DateTimeZone zone = TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback();
137 List<List<TimeBlock>> blockDays = aggregate.getDayTimeBlockList();
138 DateTime periodStartDateTime = timesheetDocument.getPayCalendarEntry().getBeginLocalDateTime().toDateTime(zone);
139 Map<Long,List<ShiftDifferentialRule>> jobNumberToShifts = getJobNumberToShiftRuleMap(timesheetDocument);
140
141
142
143 if (jobNumberToShifts.isEmpty()) {
144 return;
145 }
146
147
148
149
150
151
152 boolean previousPayPeriodPrevDay = true;
153 Map<Long, List<TimeBlock>> jobNumberToTimeBlocksPreviousDay =
154 getPreviousPayPeriodLastDayJobToTimeBlockMap(timesheetDocument, jobNumberToShifts);
155
156
157
158
159 for (int pos = 0; pos < blockDays.size(); pos++) {
160 List<TimeBlock> blocks = blockDays.get(pos);
161 if (blocks.isEmpty())
162 continue;
163
164 DateTime currentDay = periodStartDateTime.plusDays(pos);
165 Interval virtualDay = new Interval(currentDay, currentDay.plusHours(24));
166
167
168
169
170
171
172
173 Map<Long, List<TimeBlock>> jobNumberToTimeBlocks = new HashMap<Long,List<TimeBlock>>();
174 for (TimeBlock block : blocks) {
175 Long jobNumber = block.getJobNumber();
176 if (jobNumberToShifts.containsKey(jobNumber)) {
177 List<TimeBlock> jblist = jobNumberToTimeBlocks.get(jobNumber);
178 if (jblist == null) {
179 jblist = new ArrayList<TimeBlock>();
180 jobNumberToTimeBlocks.put(jobNumber, jblist);
181 }
182 jblist.add(block);
183 }
184 }
185
186
187
188
189
190
191
192
193
194 for (Long jobNumber: jobNumberToShifts.keySet()) {
195 List<ShiftDifferentialRule> shiftDifferentialRules = jobNumberToShifts.get(jobNumber);
196
197 List<TimeBlock> ruleTimeBlocksPrev = null;
198 List<TimeBlock> ruleTimeBlocksCurr = jobNumberToTimeBlocks.get(jobNumber);
199 if (ruleTimeBlocksCurr != null && ruleTimeBlocksCurr.size() > 0) {
200 if (jobNumberToTimeBlocksPreviousDay != null)
201 ruleTimeBlocksPrev = jobNumberToTimeBlocksPreviousDay.get(jobNumber);
202 if (ruleTimeBlocksPrev != null && ruleTimeBlocksPrev.size() > 0)
203 this.sortTimeBlocksInverse(ruleTimeBlocksPrev);
204 this.sortTimeBlocksNatural(ruleTimeBlocksCurr);
205 } else {
206
207
208
209 continue;
210 }
211
212 for (ShiftDifferentialRule rule : shiftDifferentialRules) {
213 Set<String> fromEarnGroup = TkServiceLocator.getEarnGroupService().getEarnCodeListForEarnGroup(rule.getFromEarnGroup(), TKUtils.getTimelessDate(timesheetDocument.getPayCalendarEntry().getBeginPeriodDateTime()));
214
215
216
217
218 LocalTime ruleStart = new LocalTime(rule.getBeginTime(), TKUtils.getSystemDateTimeZone());
219 LocalTime ruleEnd = new LocalTime(rule.getEndTime(), TKUtils.getSystemDateTimeZone());
220 ruleStart = new LocalTime(ruleStart, zone);
221 ruleEnd = new LocalTime(ruleEnd, zone);
222
223
224 DateTime shiftEnd = ruleEnd.toDateTime(currentDay);
225 DateTime shiftStart = ruleStart.toDateTime(currentDay);
226
227 if (shiftEnd.isBefore(shiftStart) || shiftEnd.isEqual(shiftStart))
228 shiftEnd = shiftEnd.plusDays(1);
229 Interval shiftInterval = new Interval(shiftStart, shiftEnd);
230
231
232 BigDecimal hoursBeforeVirtualDay = BigDecimal.ZERO;
233
234
235
236 TimeBlock firstBlockOfCurrentDay = null;
237 for (TimeBlock b : ruleTimeBlocksCurr) {
238 if (timeBlockHasEarnCode(fromEarnGroup, b)) {
239 firstBlockOfCurrentDay = b;
240 break;
241 }
242 }
243
244
245 Interval previousDayShiftInterval = new Interval(shiftStart.minusDays(1), shiftEnd.minusDays(1));
246
247
248 Interval evalInterval = null;
249 if (ruleTimeBlocksPrev != null && ruleTimeBlocksPrev.size() > 0 && dayIsRuleActive(currentDay.minusDays(1), rule)) {
250
251
252 if (shiftEnd.isAfter(virtualDay.getEnd())) {
253
254 TimeBlock firstBlockOfPreviousDay = null;
255 for (TimeBlock b : ruleTimeBlocksPrev) {
256 if (timeBlockHasEarnCode(fromEarnGroup, b)) {
257 firstBlockOfPreviousDay = b;
258 break;
259 }
260 }
261
262
263
264
265 if ( (firstBlockOfPreviousDay != null) && (firstBlockOfCurrentDay != null)) {
266 Interval previousBlockInterval = new Interval(new DateTime(firstBlockOfPreviousDay.getEndTimestamp(), zone), new DateTime(firstBlockOfCurrentDay.getBeginTimestamp(), zone));
267 Duration blockGapDuration = previousBlockInterval.toDuration();
268 BigDecimal bgdHours = TKUtils.convertMillisToHours(blockGapDuration.getMillis());
269
270 if (rule.getMaxGap().compareTo(BigDecimal.ZERO) == 0 || bgdHours.compareTo(rule.getMaxGap()) <= 0) {
271
272
273
274
275 for (int i=0; i<ruleTimeBlocksPrev.size(); i++) {
276 TimeBlock b = ruleTimeBlocksPrev.get(i);
277 if (timeBlockHasEarnCode(fromEarnGroup, b)) {
278 Interval blockInterval = new Interval(new DateTime(b.getBeginTimestamp(), zone), new DateTime(b.getEndTimestamp(), zone));
279
280
281 if (previousBlockInterval != null) {
282 blockGapDuration = new Duration(new DateTime(b.getEndTimestamp(), zone), previousBlockInterval.getStart());
283 bgdHours = TKUtils.convertMillisToHours(blockGapDuration.getMillis());
284 }
285
286
287 if (rule.getMaxGap().compareTo(BigDecimal.ZERO) == 0 || bgdHours.compareTo(rule.getMaxGap()) <= 0) {
288
289 if (blockInterval.overlaps(previousDayShiftInterval)) {
290 BigDecimal hrs = TKUtils.convertMillisToHours(blockInterval.overlap(previousDayShiftInterval).toDurationMillis());
291 hoursBeforeVirtualDay = hoursBeforeVirtualDay.add(hrs);
292 }
293
294 } else {
295
296 break;
297 }
298
299 previousBlockInterval = blockInterval;
300
301 }
302 }
303 } else {
304
305 }
306 }
307 }
308 }
309
310 BigDecimal hoursToApply = BigDecimal.ZERO;
311 BigDecimal hoursToApplyPrevious = BigDecimal.ZERO;
312
313
314
315 if (hoursBeforeVirtualDay.compareTo(rule.getMinHours()) <= 0) {
316
317 hoursToApplyPrevious = hoursBeforeVirtualDay;
318 }
319
320
321
322
323 TimeBlock previous = null;
324 List<TimeBlock> accumulatedBlocks = new ArrayList<TimeBlock>();
325 List<Interval> accumulatedBlockIntervals = new ArrayList<Interval>();
326
327 long accumulatedMillis = TKUtils.convertHoursToMillis(hoursBeforeVirtualDay);
328
329 boolean previousDayOnly = false;
330 if (!dayIsRuleActive(currentDay, rule)) {
331 if (dayIsRuleActive(currentDay.minusDays(1), rule)) {
332 previousDayOnly = true;
333 } else {
334
335 continue;
336 }
337
338 }
339
340
341
342
343
344
345
346
347
348
349
350
351 List<TimeBlock> previousBlocksFiltered = (previousPayPeriodPrevDay) ? null : filterBlocksByApplicableEarnGroup(fromEarnGroup, ruleTimeBlocksPrev);
352
353 for (TimeBlock current : ruleTimeBlocksCurr) {
354 if (!timeBlockHasEarnCode(fromEarnGroup, current)) {
355
356 continue;
357 }
358
359 Interval blockInterval = new Interval(new DateTime(current.getBeginTimestamp(), zone), new DateTime(current.getEndTimestamp(), zone));
360
361
362
363
364 if (previousDayShiftInterval.overlaps(shiftInterval))
365 throw new RuntimeException("Interval of greater than 24 hours created in the rules processing.");
366
367
368
369
370
371 Interval overlap = previousDayShiftInterval.overlap(blockInterval);
372 evalInterval = previousDayShiftInterval;
373 if (overlap == null) {
374 if (hoursToApplyPrevious.compareTo(BigDecimal.ZERO) > 0) {
375
376
377
378
379 BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis);
380 this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule);
381 accumulatedMillis = 0L;
382 hoursToApply = BigDecimal.ZERO;
383 hoursToApplyPrevious = BigDecimal.ZERO;
384 }
385
386
387
388
389
390 if (previousDayOnly) {
391 continue;
392 }
393
394 overlap = shiftInterval.overlap(blockInterval);
395 evalInterval = shiftInterval;
396 }
397
398
399
400 if (overlap != null) {
401
402 if (previous != null) {
403
404 if (rule.getMaxGap().compareTo(BigDecimal.ZERO) != 0 && exceedsMaxGap(previous, current, rule.getMaxGap())) {
405 BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis);
406 this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule);
407 accumulatedMillis = 0L;
408 hoursToApply = BigDecimal.ZERO;
409 hoursToApplyPrevious = BigDecimal.ZERO;
410 } else {
411 long millis = overlap.toDurationMillis();
412 accumulatedMillis += millis;
413 hoursToApply = hoursToApply.add(TKUtils.convertMillisToHours(millis));
414 }
415 } else {
416
417 long millis = overlap.toDurationMillis();
418 accumulatedMillis += millis;
419 hoursToApply = hoursToApply.add(TKUtils.convertMillisToHours(millis));
420 }
421 accumulatedBlocks.add(current);
422 accumulatedBlockIntervals.add(blockInterval);
423 previous = current;
424 } else {
425
426 if (previous != null) {
427 BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis);
428 this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule);
429 accumulatedMillis = 0L;
430 hoursToApply = BigDecimal.ZERO;
431 hoursToApplyPrevious = BigDecimal.ZERO;
432 }
433 }
434
435 }
436
437
438
439 BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis);
440 this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule);
441 }
442 }
443
444 jobNumberToTimeBlocksPreviousDay = jobNumberToTimeBlocks;
445 previousPayPeriodPrevDay = false;
446 }
447
448 }
449
450 @Override
451 public List<ShiftDifferentialRule> getShiftDifferentialRules(String location, String hrSalGroup, String payGrade, Date fromEffdt, Date toEffdt, String active, String showHist) {
452 return shiftDifferentialRuleDao.getShiftDifferentialRules(location, hrSalGroup, payGrade, fromEffdt, toEffdt, active, showHist);
453 }
454
455 private List<TimeBlock> filterBlocksByApplicableEarnGroup(Set<String> fromEarnGroup, List<TimeBlock> blocks) {
456 List<TimeBlock> filtered;
457
458 if (blocks == null || blocks.size() == 0)
459 filtered = null;
460 else {
461 filtered = new ArrayList<TimeBlock>();
462 for (TimeBlock b : blocks) {
463 if (timeBlockHasEarnCode(fromEarnGroup, b))
464 filtered.add(b);
465 }
466 }
467
468 return filtered;
469 }
470
471
472 private void applyAccumulatedWrapper(BigDecimal accumHours, Interval evalInterval, List<Interval>accumulatedBlockIntervals, List<TimeBlock>accumulatedBlocks, List<TimeBlock> previousBlocks, BigDecimal hoursToApplyPrevious, BigDecimal hoursToApply, ShiftDifferentialRule rule) {
473 if (accumHours.compareTo(rule.getMinHours()) >= 0) {
474 this.applyPremium(evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocks, hoursToApplyPrevious, hoursToApply, rule.getEarnCode());
475 }
476 accumulatedBlocks.clear();
477 accumulatedBlockIntervals.clear();
478 }
479
480 private void sortTimeBlocksInverse(List<TimeBlock> blocks) {
481 Collections.sort(blocks, new Comparator<TimeBlock>() {
482 public int compare(TimeBlock tb1, TimeBlock tb2) {
483 if (tb1 != null && tb2 != null)
484 return -1 * tb1.getBeginTimestamp().compareTo(tb2.getBeginTimestamp());
485 return 0;
486 }
487 });
488 }
489
490 private void sortTimeBlocksNatural(List<TimeBlock> blocks) {
491 Collections.sort(blocks, new Comparator<TimeBlock>() {
492 public int compare(TimeBlock tb1, TimeBlock tb2) {
493 if (tb1 != null && tb2 != null)
494 return tb1.getBeginTimestamp().compareTo(tb2.getBeginTimestamp());
495 return 0;
496 }
497 });
498 }
499
500
501
502
503
504
505
506
507
508
509
510 void applyPremium(Interval shift, List<Interval> blockIntervals, List<TimeBlock> blocks, List<TimeBlock> previousBlocks, BigDecimal initialHours, BigDecimal hours, String earnCode) {
511 for (int i=0; i<blocks.size(); i++) {
512 TimeBlock b = blocks.get(i);
513
514
515 if (i == 0 && (initialHours.compareTo(BigDecimal.ZERO) > 0)) {
516
517
518 if (previousBlocks != null && previousBlocks.size() > 0 && previousBlocks.get(0).getDocumentId().equals(b.getDocumentId())) {
519 for (TimeBlock pb : previousBlocks) {
520 BigDecimal lunchSub = this.negativeTimeHourDetailSum(pb);
521 initialHours = BigDecimal.ZERO.max(initialHours.add(lunchSub));
522 if (initialHours.compareTo(BigDecimal.ZERO) <= 0)
523 break;
524
525
526 BigDecimal hoursToApply = initialHours.min(pb.getHours().add(lunchSub));
527 addPremiumTimeHourDetail(pb, hoursToApply, earnCode);
528 initialHours = initialHours.subtract(hoursToApply, TkConstants.MATH_CONTEXT);
529 if (initialHours.compareTo(BigDecimal.ZERO) <= 0)
530 break;
531 }
532 } else {
533 addPremiumTimeHourDetail(b, initialHours, earnCode);
534 }
535 }
536
537 BigDecimal lunchSub = this.negativeTimeHourDetailSum(b);
538 hours = BigDecimal.ZERO.max(hours.add(lunchSub));
539
540 if (hours.compareTo(BigDecimal.ZERO) > 0) {
541 Interval blockInterval = blockIntervals.get(i);
542 Interval overlapInterval = shift.overlap(blockInterval);
543 if (overlapInterval == null)
544 continue;
545
546 long overlap = overlapInterval.toDurationMillis();
547 BigDecimal hoursMax = TKUtils.convertMillisToHours(overlap);
548
549
550 BigDecimal hoursToApply = hours.min(hoursMax.add(lunchSub));
551
552 addPremiumTimeHourDetail(b, hoursToApply, earnCode);
553 hours = hours.subtract(hoursToApply, TkConstants.MATH_CONTEXT);
554 }
555 }
556 }
557
558 void addPremiumTimeHourDetail(TimeBlock block, BigDecimal hours, String earnCode) {
559 List<TimeHourDetail> details = block.getTimeHourDetails();
560 TimeHourDetail premium = new TimeHourDetail();
561 premium.setHours(hours);
562 premium.setEarnCode(earnCode);
563 premium.setTkTimeBlockId(block.getTkTimeBlockId());
564 details.add(premium);
565 }
566
567
568
569
570
571
572
573
574
575
576 boolean exceedsMaxGap(TimeBlock previous, TimeBlock current, BigDecimal maxGap) {
577 long difference = current.getBeginTimestamp().getTime() - previous.getEndTimestamp().getTime();
578 BigDecimal gapMinutes = TKUtils.convertMillisToMinutes(difference);
579
580 return (gapMinutes.compareTo(maxGap) > 0);
581 }
582
583 public void setShiftDifferentialRuleDao(ShiftDifferentialRuleDao shiftDifferentialRuleDao) {
584 this.shiftDifferentialRuleDao = shiftDifferentialRuleDao;
585 }
586
587 @Override
588 public ShiftDifferentialRule getShiftDifferentialRule(String tkShiftDifferentialRuleId) {
589 return this.shiftDifferentialRuleDao.findShiftDifferentialRule(tkShiftDifferentialRuleId);
590 }
591
592 @Override
593 public List<ShiftDifferentialRule> getShiftDifferentalRules(String location, String hrSalGroup, String payGrade, String pyCalendarGroup, Date asOfDate) {
594 List<ShiftDifferentialRule> sdrs = new ArrayList<ShiftDifferentialRule>();
595
596
597
598 sdrs.addAll(shiftDifferentialRuleDao.findShiftDifferentialRules(location, hrSalGroup, payGrade, pyCalendarGroup, asOfDate));
599
600
601 sdrs.addAll(shiftDifferentialRuleDao.findShiftDifferentialRules(location, hrSalGroup, "%", pyCalendarGroup, asOfDate));
602
603
604 sdrs.addAll(shiftDifferentialRuleDao.findShiftDifferentialRules(location, "%", payGrade, pyCalendarGroup, asOfDate));
605
606
607 sdrs.addAll(shiftDifferentialRuleDao.findShiftDifferentialRules(location, "%", "%", pyCalendarGroup, asOfDate));
608
609
610 sdrs.addAll(shiftDifferentialRuleDao.findShiftDifferentialRules("%", hrSalGroup, payGrade, pyCalendarGroup, asOfDate));
611
612
613 sdrs.addAll(shiftDifferentialRuleDao.findShiftDifferentialRules("%", hrSalGroup, "%", pyCalendarGroup, asOfDate));
614
615
616 sdrs.addAll(shiftDifferentialRuleDao.findShiftDifferentialRules("%", "%", payGrade, pyCalendarGroup, asOfDate));
617
618
619 sdrs.addAll(shiftDifferentialRuleDao.findShiftDifferentialRules("%", "%", "%", pyCalendarGroup, asOfDate));
620
621 if (sdrs == null)
622 sdrs = Collections.emptyList();
623
624 return sdrs;
625 }
626
627 private boolean dayIsRuleActive(DateTime currentDate, ShiftDifferentialRule sdr) {
628 boolean active = false;
629
630 switch (currentDate.getDayOfWeek()) {
631 case DateTimeConstants.MONDAY:
632 active = sdr.isMonday();
633 break;
634 case DateTimeConstants.TUESDAY:
635 active = sdr.isTuesday();
636 break;
637 case DateTimeConstants.WEDNESDAY:
638 active = sdr.isWednesday();
639 break;
640 case DateTimeConstants.THURSDAY:
641 active = sdr.isThursday();
642 break;
643 case DateTimeConstants.FRIDAY:
644 active = sdr.isFriday();
645 break;
646 case DateTimeConstants.SATURDAY:
647 active = sdr.isSaturday();
648 break;
649 case DateTimeConstants.SUNDAY:
650 active = sdr.isSunday();
651 break;
652 }
653
654 return active;
655 }
656
657 @Override
658 public void saveOrUpdate(List<ShiftDifferentialRule> shiftDifferentialRules) {
659 shiftDifferentialRuleDao.saveOrUpdate(shiftDifferentialRules);
660 }
661
662 @Override
663 public void saveOrUpdate(ShiftDifferentialRule shiftDifferentialRule) {
664 shiftDifferentialRuleDao.saveOrUpdate(shiftDifferentialRule);
665 }
666
667 }