1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.approval.service;
17
18 import com.google.common.collect.HashMultimap;
19 import com.google.common.collect.Multimap;
20 import org.apache.commons.collections.CollectionUtils;
21 import org.apache.commons.lang.StringUtils;
22 import org.apache.commons.lang3.time.DateUtils;
23 import org.apache.log4j.Logger;
24 import org.joda.time.*;
25 import org.joda.time.format.DateTimeFormat;
26 import org.joda.time.format.DateTimeFormatter;
27 import org.kuali.hr.lm.LMConstants;
28 import org.kuali.hr.lm.accrual.AccrualCategory;
29 import org.kuali.hr.lm.accrual.AccrualCategoryRule;
30 import org.kuali.hr.lm.leaveblock.LeaveBlock;
31 import org.kuali.hr.lm.leavecalendar.validation.LeaveCalendarValidationUtil;
32 import org.kuali.hr.lm.util.LeaveBlockAggregate;
33 import org.kuali.hr.time.approval.web.ApprovalTimeSummaryRow;
34 import org.kuali.hr.time.assignment.Assignment;
35 import org.kuali.hr.time.assignment.AssignmentDescriptionKey;
36 import org.kuali.hr.time.calendar.Calendar;
37 import org.kuali.hr.time.calendar.CalendarEntries;
38 import org.kuali.hr.time.clocklog.ClockLog;
39 import org.kuali.hr.time.earncode.EarnCode;
40 import org.kuali.hr.time.flsa.FlsaDay;
41 import org.kuali.hr.time.flsa.FlsaWeek;
42 import org.kuali.hr.time.principal.PrincipalHRAttributes;
43 import org.kuali.hr.time.roles.TkUserRoles;
44 import org.kuali.hr.time.roles.UserRoles;
45 import org.kuali.hr.time.service.base.TkServiceLocator;
46 import org.kuali.hr.time.timeblock.TimeBlock;
47 import org.kuali.hr.time.timeblock.TimeHourDetail;
48 import org.kuali.hr.time.timesheet.TimesheetDocument;
49 import org.kuali.hr.time.util.*;
50 import org.kuali.hr.time.workarea.WorkArea;
51 import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
52 import org.kuali.rice.kew.api.KewApiServiceLocator;
53 import org.kuali.rice.kew.api.note.Note;
54 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
55 import org.kuali.rice.kew.service.KEWServiceLocator;
56 import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
57 import org.kuali.rice.krad.util.GlobalVariables;
58 import org.kuali.rice.kim.api.identity.principal.Principal;
59 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
60 import org.springframework.jdbc.support.rowset.SqlRowSet;
61
62 import java.math.BigDecimal;
63 import java.sql.Types;
64 import java.text.SimpleDateFormat;
65 import java.util.*;
66 import java.util.Map.Entry;
67
68 public class TimeApproveServiceImpl implements TimeApproveService {
69
70 private static final Logger LOG = Logger
71 .getLogger(TimeApproveServiceImpl.class);
72
73 public static final int DAYS_WINDOW_DELTA = 31;
74
75 public Map<String, CalendarEntries> getPayCalendarEntriesForDept(
76 String dept, Date currentDate) {
77 DateTime minDt = new DateTime(currentDate,
78 TKUtils.getSystemDateTimeZone());
79 minDt = minDt.minusDays(DAYS_WINDOW_DELTA);
80 java.sql.Date windowDate = TKUtils.getTimelessDate(minDt.toDate());
81
82 Map<String, CalendarEntries> pceMap = new HashMap<String, CalendarEntries>();
83 Set<String> principals = new HashSet<String>();
84 List<WorkArea> workAreasForDept = TkServiceLocator.getWorkAreaService()
85 .getWorkAreas(dept, new java.sql.Date(currentDate.getTime()));
86
87 for (WorkArea workArea : workAreasForDept) {
88 Long waNum = workArea.getWorkArea();
89 List<Assignment> assignments = TkServiceLocator
90 .getAssignmentService().getActiveAssignmentsForWorkArea(
91 waNum, TKUtils.getTimelessDate(currentDate));
92
93 if (assignments != null) {
94 for (Assignment assignment : assignments) {
95 principals.add(assignment.getPrincipalId());
96 }
97 } else {
98 assignments = TkServiceLocator.getAssignmentService()
99 .getActiveAssignmentsForWorkArea(waNum, windowDate);
100 if (assignments != null) {
101 for (Assignment assignment : assignments) {
102 principals.add(assignment.getPrincipalId());
103 }
104 }
105 }
106 }
107
108
109 Set<Calendar> payCals = new HashSet<Calendar>();
110 for (String pid : principals) {
111 PrincipalHRAttributes pc = TkServiceLocator
112 .getPrincipalHRAttributeService().getPrincipalCalendar(pid,
113 currentDate);
114 if (pc == null)
115 pc = TkServiceLocator.getPrincipalHRAttributeService()
116 .getPrincipalCalendar(pid, windowDate);
117
118 if (pc != null) {
119 payCals.add(pc.getCalendar());
120 } else {
121 LOG.warn("PrincipalCalendar null for principal: '" + pid + "'");
122 }
123 }
124
125
126 for (Calendar pc : payCals) {
127 CalendarEntries pce = TkServiceLocator
128 .getCalendarEntriesService()
129 .getCurrentCalendarEntriesByCalendarId(
130 pc.getHrCalendarId(), currentDate);
131 pceMap.put(pc.getCalendarName(), pce);
132 }
133
134 return pceMap;
135 }
136
137 @Override
138 public Map<String, CalendarEntries> getPayCalendarEntriesForApprover(
139 String principalId, Date currentDate, String dept) {
140
141 Map<String, CalendarEntries> pceMap = new HashMap<String, CalendarEntries>();
142 Set<String> principals = new HashSet<String>();
143 DateTime minDt = new DateTime(currentDate,
144 TKUtils.getSystemDateTimeZone());
145 minDt = minDt.minusDays(DAYS_WINDOW_DELTA);
146 java.sql.Date windowDate = TKUtils.getTimelessDate(minDt.toDate());
147 Set<Long> approverWorkAreas = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getApproverWorkAreas();
148
149
150 for (Long waNum : approverWorkAreas) {
151 List<Assignment> assignments = TkServiceLocator
152 .getAssignmentService().getActiveAssignmentsForWorkArea(
153 waNum, TKUtils.getTimelessDate(currentDate));
154
155 if (assignments != null) {
156 for (Assignment assignment : assignments) {
157 principals.add(assignment.getPrincipalId());
158 }
159 }
160 }
161
162
163 Set<Calendar> payCals = new HashSet<Calendar>();
164 for (String pid : principals) {
165 PrincipalHRAttributes pc = TkServiceLocator
166 .getPrincipalHRAttributeService().getPrincipalCalendar(pid,
167 currentDate);
168 if (pc == null)
169 pc = TkServiceLocator.getPrincipalHRAttributeService()
170 .getPrincipalCalendar(pid, windowDate);
171
172 if (pc != null) {
173 payCals.add(pc.getCalendar());
174 } else {
175 LOG.warn("PrincipalCalendar null for principal: '" + pid + "'");
176 }
177 }
178
179
180 for (Calendar pc : payCals) {
181 CalendarEntries pce = TkServiceLocator
182 .getCalendarEntriesService()
183 .getCurrentCalendarEntriesByCalendarId(
184 pc.getHrCalendarId(), currentDate);
185 pceMap.put(pc.getCalendarName(), pce);
186 }
187
188 return pceMap;
189 }
190
191 public SortedSet<String> getApproverPayCalendarGroups(Date payBeginDate,
192 Date payEndDate) {
193 SortedSet<String> pcg = new TreeSet<String>();
194
195 Set<Long> approverWorkAreas = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getApproverWorkAreas();
196 List<Assignment> assignments = new ArrayList<Assignment>();
197
198 for (Long workArea : approverWorkAreas) {
199 if (workArea != null) {
200 assignments.addAll(TkServiceLocator.getAssignmentService()
201 .getActiveAssignmentsForWorkArea(workArea,
202 new java.sql.Date(payBeginDate.getTime())));
203 }
204 }
205 if (!assignments.isEmpty()) {
206 for (Assignment assign : assignments) {
207 String principalId = assign.getPrincipalId();
208 TimesheetDocumentHeader tdh = TkServiceLocator
209 .getTimesheetDocumentHeaderService().getDocumentHeader(
210 principalId, payBeginDate, payEndDate);
211 if (tdh != null) {
212 String pyCalendarGroup = TkServiceLocator
213 .getPrincipalHRAttributeService()
214 .getPrincipalCalendar(principalId, tdh.getBeginDate())
215 .getCalendar().getCalendarName();
216 pcg.add(pyCalendarGroup);
217 }
218 }
219 }
220 return pcg;
221 }
222
223 @SuppressWarnings("rawtypes")
224 @Override
225 public List<ApprovalTimeSummaryRow> getApprovalSummaryRows(
226 Date payBeginDate, Date payEndDate, String calGroup,
227 List<String> principalIds, List<String> payCalendarLabels,
228 CalendarEntries payCalendarEntries) {
229 List<ApprovalTimeSummaryRow> rows = new LinkedList<ApprovalTimeSummaryRow>();
230 Map<String, TimesheetDocumentHeader> principalDocumentHeader = getPrincipalDocumentHeader(
231 principalIds, payBeginDate, payEndDate);
232
233 Calendar payCalendar = TkServiceLocator.getCalendarService()
234 .getCalendar(payCalendarEntries.getHrCalendarId());
235 DateTimeZone dateTimeZone = TkServiceLocator.getTimezoneService()
236 .getUserTimezoneWithFallback();
237 List<Interval> dayIntervals = TKUtils
238 .getDaySpanForCalendarEntry(payCalendarEntries);
239
240
241 for (String principalId : principalIds) {
242 TimesheetDocumentHeader tdh = new TimesheetDocumentHeader();
243 String documentId = "";
244 if (principalDocumentHeader.containsKey(principalId)) {
245 tdh = principalDocumentHeader.get(principalId);
246 documentId = principalDocumentHeader.get(principalId).getDocumentId();
247 }
248 List<TimeBlock> timeBlocks = new ArrayList<TimeBlock>();
249 List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>();
250 List<Note> notes = new ArrayList<Note>();
251 List<String> warnings = new ArrayList<String>();
252
253 ApprovalTimeSummaryRow approvalSummaryRow = new ApprovalTimeSummaryRow();
254
255 if (principalDocumentHeader.containsKey(principalId)) {
256 approvalSummaryRow
257 .setApprovalStatus(TkConstants.DOC_ROUTE_STATUS.get(tdh
258 .getDocumentStatus()));
259 }
260
261 Set<String> regularEarnCodes = new HashSet<String>();
262 if (StringUtils.isNotBlank(documentId)) {
263 TimesheetDocument td = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
264 if (td != null) {
265 timeBlocks = td.getTimeBlocks();
266
267
268 List<String> assignKeys = new ArrayList<String>();
269 for(Assignment a : td.getAssignments()) {
270 assignKeys.add(a.getAssignmentKey());
271 regularEarnCodes.add(a.getJob().getPayTypeObj().getRegEarnCode());
272 }
273 leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(principalId,
274 payBeginDate, payEndDate, assignKeys);
275 notes = getNotesForDocument(documentId);
276
277 warnings = TkServiceLocator.getWarningService().getWarnings(td);
278 }
279
280 }
281 Map<String, Set<String>> transactionalWarnings = LeaveCalendarValidationUtil.validatePendingTransactions(principalId, payCalendarEntries.getBeginPeriodDate(), payCalendarEntries.getEndPeriodDate());
282
283 warnings.addAll(transactionalWarnings.get("infoMessages"));
284 warnings.addAll(transactionalWarnings.get("warningMessages"));
285 warnings.addAll(transactionalWarnings.get("actionMessages"));
286
287 Map<String, Set<String>> eligibleTransfers = findWarnings(principalId, payCalendarEntries);
288 warnings.addAll(eligibleTransfers.get("warningMessages"));
289
290 Map<String, BigDecimal> hoursToPayLabelMap = getHoursToPayDayMap(
291 principalId, payEndDate, payCalendarLabels,
292 timeBlocks, leaveBlocks, null, payCalendarEntries, payCalendar,
293 dateTimeZone, dayIntervals);
294
295 Map<String, BigDecimal> hoursToFlsaPayLabelMap = getHoursToFlsaWeekMap(
296 principalId, payEndDate, payCalendarLabels,
297 timeBlocks, leaveBlocks, null, payCalendarEntries, payCalendar,
298 dateTimeZone, dayIntervals);
299
300 EntityNamePrincipalName name = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId);
301 approvalSummaryRow.setName(name != null
302 && name.getDefaultName() != null
303 && name.getDefaultName().getCompositeName() != null ? name.getDefaultName().getCompositeName() : principalId);
304 approvalSummaryRow.setPrincipalId(principalId);
305 approvalSummaryRow.setPayCalendarGroup(calGroup);
306 approvalSummaryRow.setDocumentId(documentId);
307 approvalSummaryRow.setHoursToPayLabelMap(hoursToPayLabelMap);
308 approvalSummaryRow.setHoursToFlsaPayLabelMap(hoursToFlsaPayLabelMap);
309 approvalSummaryRow.setPeriodTotal(hoursToPayLabelMap
310 .get("Period Total"));
311 approvalSummaryRow.setLstTimeBlocks(timeBlocks);
312 approvalSummaryRow.setNotes(notes);
313 approvalSummaryRow.setWarnings(warnings);
314
315
316
317 ClockLog lastClockLog = TkServiceLocator.getClockLogService()
318 .getLastClockLog(principalId);
319 if (isSynchronousUser(principalId)) {
320 approvalSummaryRow.setClockStatusMessage(createLabelForLastClockLog(lastClockLog));
321 }
322 if (lastClockLog != null
323 && (StringUtils.equals(lastClockLog.getClockAction(),
324 TkConstants.CLOCK_IN) || StringUtils
325 .equals(lastClockLog.getClockAction(),
326 TkConstants.LUNCH_IN))) {
327 DateTime startTime = new DateTime(lastClockLog
328 .getClockTimestamp().getTime());
329 DateTime endTime = new DateTime(System.currentTimeMillis());
330
331 Hours hour = Hours.hoursBetween(startTime, endTime);
332 if (hour != null) {
333 int elapsedHours = hour.getHours();
334 if (elapsedHours >= TkConstants.NUMBER_OF_HOURS_CLOCKED_IN_APPROVE_TAB_HIGHLIGHT) {
335 approvalSummaryRow.setClockedInOverThreshold(true);
336 }
337 }
338
339 }
340 rows.add(approvalSummaryRow);
341 }
342 return rows;
343 }
344
345 private boolean isSynchronousUser(String principalId) {
346 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(principalId, TKUtils.getCurrentDate());
347 boolean isSynchronousUser = false;
348 if (CollectionUtils.isNotEmpty(assignments)) {
349 for (Assignment assignment : assignments) {
350 isSynchronousUser |= assignment.isSynchronous();
351 }
352 }
353 return isSynchronousUser;
354 }
355
356 public List<TimesheetDocumentHeader> getDocumentHeadersByPrincipalIds(
357 Date payBeginDate, Date payEndDate, List<String> principalIds) {
358 List<TimesheetDocumentHeader> headers = new LinkedList<TimesheetDocumentHeader>();
359 for (String principalId : principalIds) {
360 TimesheetDocumentHeader tdh = TkServiceLocator
361 .getTimesheetDocumentHeaderService().getDocumentHeader(
362 principalId, payBeginDate, payEndDate);
363 if (tdh != null) {
364 headers.add(tdh);
365 }
366 }
367
368 return headers;
369 }
370
371
372
373
374 public List<String> getPayCalendarLabelsForApprovalTab(Date payBeginDate,
375 Date payEndDate) {
376
377
378 List<String> lstPayCalendarLabels = new ArrayList<String>();
379 DateTime payBegin = new DateTime(payBeginDate.getTime());
380 DateTime payEnd = new DateTime(payEndDate.getTime());
381 DateTime currTime = payBegin;
382 int dayCounter = 1;
383 int weekCounter = 1;
384
385 while (currTime.isBefore(payEnd)) {
386 String labelForDay = createLabelForDay(currTime);
387 lstPayCalendarLabels.add(labelForDay);
388 currTime = currTime.plusDays(1);
389 if ((dayCounter % 7) == 0) {
390 lstPayCalendarLabels.add("Week " + weekCounter);
391 weekCounter++;
392 }
393 dayCounter++;
394 }
395 lstPayCalendarLabels.add("Total Hours");
396 return lstPayCalendarLabels;
397 }
398
399 private Map<String, Set<String>> findWarnings(String principalId, CalendarEntries calendarEntry) {
400
401 Map<String, Set<String>> allMessages = new HashMap<String,Set<String>>();
402 allMessages.put("warningMessages", new HashSet<String>());
403
404 Map<String, Set<LeaveBlock>> eligibilities;
405
406 eligibilities = TkServiceLocator.getAccrualCategoryMaxBalanceService().getMaxBalanceViolations(calendarEntry, principalId);
407
408 if (eligibilities != null) {
409 for (Entry<String,Set<LeaveBlock>> entry : eligibilities.entrySet()) {
410 for(LeaveBlock lb : entry.getValue()) {
411 AccrualCategoryRule rule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(lb.getAccrualCategoryRuleId());
412 if (rule != null) {
413 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(rule.getLmAccrualCategoryId());
414 if (rule.getActionAtMaxBalance().equals(LMConstants.ACTION_AT_MAX_BAL.TRANSFER)) {
415
416 allMessages.get("warningMessages").add("Accrual Category '" + accrualCategory.getAccrualCategory() + "' is over max balance.");
417 } else if (rule.getActionAtMaxBalance().equals(LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
418
419 allMessages.get("warningMessages").add("Accrual Category '" + accrualCategory.getAccrualCategory() + "' is over max balance.");
420 } else if (rule.getActionAtMaxBalance().equals(LMConstants.ACTION_AT_MAX_BAL.PAYOUT)) {
421
422 allMessages.get("warningMessages").add("Accrual Category '" + accrualCategory.getAccrualCategory() + "' is over max balance.");
423 }
424 }
425 }
426 }
427 }
428
429 return allMessages;
430 }
431
432
433
434
435
436
437
438 private String createLabelForDay(DateTime fromDate) {
439 DateMidnight dateMidnight = new DateMidnight(fromDate);
440 if (dateMidnight.compareTo(fromDate) == 0) {
441 DateTimeFormatter fmt = DateTimeFormat.forPattern("MMM/dd");
442 return fmt.print(fromDate);
443 }
444 DateTime toDate = fromDate.plusDays(1);
445 DateTimeFormatter fmt = DateTimeFormat.forPattern("MMM/dd k:m:s");
446 return fmt.print(fromDate) + "-" + fmt.print(toDate);
447 }
448
449
450
451
452
453
454
455 private String createLabelForLastClockLog(ClockLog cl) {
456
457 if (cl == null) {
458 return "No previous clock information";
459 }
460 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm a");
461 String dateTime = sdf.format(new java.sql.Date(cl.getClockTimestamp()
462 .getTime()));
463 if (StringUtils.equals(cl.getClockAction(), TkConstants.CLOCK_IN)) {
464 return "Clocked in since: " + dateTime;
465 } else if (StringUtils.equals(cl.getClockAction(),
466 TkConstants.LUNCH_OUT)) {
467 return "At Lunch since: " + dateTime;
468 } else if (StringUtils
469 .equals(cl.getClockAction(), TkConstants.LUNCH_IN)) {
470 return "Returned from Lunch : " + dateTime;
471 } else if (StringUtils.equals(cl.getClockAction(),
472 TkConstants.CLOCK_OUT)) {
473 return "Clocked out since: " + dateTime;
474 } else {
475 return "No previous clock information";
476 }
477
478 }
479
480 public List<Map<String, Map<String, BigDecimal>>> getHoursByDayAssignmentBuckets(
481 TkTimeBlockAggregate aggregate,
482 List<Assignment> approverAssignments, List<String> payCalendarLabels) {
483 Map<String, Assignment> mappedAssignments = mapAssignmentsByAssignmentKey(approverAssignments);
484 List<List<TimeBlock>> blocksByDay = aggregate.getDayTimeBlockList();
485
486
487 Map<String, List<BigDecimal>> approverHours = new HashMap<String, List<BigDecimal>>();
488 Map<String, List<BigDecimal>> otherHours = new HashMap<String, List<BigDecimal>>();
489 for (int day = 0; day < blocksByDay.size(); day++) {
490 List<TimeBlock> dayBlocks = blocksByDay.get(day);
491 for (TimeBlock block : dayBlocks) {
492 List<BigDecimal> hours;
493
494 if (mappedAssignments.containsKey(block.getAssignmentKey())) {
495 hours = approverHours.get(block.getAssignmentKey());
496 if (hours == null) {
497 hours = new ArrayList<BigDecimal>();
498 approverHours.put(block.getAssignmentKey(), hours);
499 }
500 } else {
501 hours = otherHours.get(block.getAssignmentKey());
502 if (hours == null) {
503 hours = new ArrayList<BigDecimal>();
504 otherHours.put(block.getAssignmentKey(), hours);
505 }
506 }
507
508
509 for (int fill = hours.size(); fill <= day; fill++) {
510 hours.add(TkConstants.BIG_DECIMAL_SCALED_ZERO);
511 }
512
513
514 BigDecimal timeToAdd = hours.get(day);
515 timeToAdd = timeToAdd.add(block.getHours(),
516 TkConstants.MATH_CONTEXT);
517 hours.set(day, timeToAdd);
518 }
519 }
520
521
522
523
524 Map<String, Map<String, BigDecimal>> approverAssignToPayHourTotals = new HashMap<String, Map<String, BigDecimal>>();
525 Map<String, Map<String, BigDecimal>> otherAssignToPayHourTotals = new HashMap<String, Map<String, BigDecimal>>();
526
527
528 generateSummaries(approverAssignToPayHourTotals, approverHours,
529 payCalendarLabels);
530 generateSummaries(otherAssignToPayHourTotals, otherHours,
531 payCalendarLabels);
532
533
534 List<Map<String, Map<String, BigDecimal>>> returnTuple = new ArrayList<Map<String, Map<String, BigDecimal>>>(
535 2);
536 returnTuple.add(approverAssignToPayHourTotals);
537 returnTuple.add(otherAssignToPayHourTotals);
538
539 return returnTuple;
540 }
541
542
543 private void generateSummaries(
544 Map<String, Map<String, BigDecimal>> payHourTotals,
545 Map<String, List<BigDecimal>> assignmentToHours,
546 List<String> payCalendarLabels) {
547 for (Entry<String, List<BigDecimal>> entry : assignmentToHours.entrySet()) {
548
549 Map<String, BigDecimal> hoursToPayLabelMap = new LinkedHashMap<String, BigDecimal>();
550 List<BigDecimal> dayTotals = entry.getValue();
551 int dayCount = 0;
552 BigDecimal weekTotal = new BigDecimal(0.00);
553 BigDecimal periodTotal = new BigDecimal(0.00);
554 for (String payCalendarLabel : payCalendarLabels) {
555 if (StringUtils.contains(payCalendarLabel, "Week")) {
556 hoursToPayLabelMap.put(payCalendarLabel, weekTotal);
557 weekTotal = new BigDecimal(0.00);
558 } else if (StringUtils
559 .contains(payCalendarLabel, "Total Hours")) {
560 hoursToPayLabelMap.put(payCalendarLabel, periodTotal);
561 } else {
562 BigDecimal dayTotal = TkConstants.BIG_DECIMAL_SCALED_ZERO;
563 if (dayCount < dayTotals.size())
564 dayTotal = dayTotals.get(dayCount);
565
566 hoursToPayLabelMap.put(payCalendarLabel, dayTotal);
567 weekTotal = weekTotal.add(dayTotal,
568 TkConstants.MATH_CONTEXT);
569 periodTotal = periodTotal.add(dayTotal);
570 dayCount++;
571 }
572 }
573 payHourTotals.put(entry.getKey(), hoursToPayLabelMap);
574 }
575 }
576
577 private Map<String, Assignment> mapAssignmentsByAssignmentKey(
578 List<Assignment> assignments) {
579 Map<String, Assignment> assignmentMap = new HashMap<String, Assignment>();
580 for (Assignment assignment : assignments) {
581 assignmentMap
582 .put(AssignmentDescriptionKey
583 .getAssignmentKeyString(assignment), assignment);
584 }
585 return assignmentMap;
586 }
587
588
589
590
591 @Override
592 public Map<String, BigDecimal> getHoursToPayDayMap(String principalId,
593 Date payEndDate, List<String> payCalendarLabels,
594 List<TimeBlock> lstTimeBlocks, List<LeaveBlock> leaveBlocks, Long workArea,
595 CalendarEntries payCalendarEntries, Calendar payCalendar,
596 DateTimeZone dateTimeZone, List<Interval> dayIntervals) {
597
598 Map<String, BigDecimal> hoursToPayLabelMap = new LinkedHashMap<String, BigDecimal>();
599 List<BigDecimal> dayTotals = new ArrayList<BigDecimal>();
600
601 TkTimeBlockAggregate tkTimeBlockAggregate = buildAndMergeAggregates(lstTimeBlocks, leaveBlocks, payCalendarEntries, payCalendar, dayIntervals);
602
603 List<FlsaWeek> flsaWeeks = tkTimeBlockAggregate
604 .getFlsaWeeks(dateTimeZone);
605 for (FlsaWeek week : flsaWeeks) {
606 for (FlsaDay day : week.getFlsaDays()) {
607 BigDecimal total = new BigDecimal(0.00);
608 for (TimeBlock tb : day.getAppliedTimeBlocks()) {
609 for (TimeHourDetail thd : tb.getTimeHourDetails()) {
610 if (workArea != null) {
611 if (tb.getWorkArea().compareTo(workArea) == 0) {
612 total = total.add(thd.getHours(),
613 TkConstants.MATH_CONTEXT);
614 } else {
615 total = total.add(new BigDecimal("0"),
616 TkConstants.MATH_CONTEXT);
617 }
618 } else {
619 total = total.add(thd.getHours(),
620 TkConstants.MATH_CONTEXT);
621 }
622 }
623 }
624 dayTotals.add(total);
625 }
626 }
627
628 int dayCount = 0;
629 BigDecimal weekTotal = new BigDecimal(0.00);
630 BigDecimal periodTotal = new BigDecimal(0.00);
631 for (String payCalendarLabel : payCalendarLabels) {
632 if (StringUtils.contains(payCalendarLabel, "Week")) {
633 hoursToPayLabelMap.put(payCalendarLabel, weekTotal);
634 weekTotal = new BigDecimal(0.00);
635 } else if (StringUtils.contains(payCalendarLabel, "Period Total")) {
636 hoursToPayLabelMap.put(payCalendarLabel, periodTotal);
637 } else {
638 if(dayCount < dayTotals.size()) {
639 hoursToPayLabelMap.put(payCalendarLabel,
640 dayTotals.get(dayCount));
641 weekTotal = weekTotal.add(dayTotals.get(dayCount),
642 TkConstants.MATH_CONTEXT);
643 periodTotal = periodTotal.add(dayTotals.get(dayCount));
644 dayCount++;
645 }
646
647 }
648
649 }
650 return hoursToPayLabelMap;
651 }
652
653 private TkTimeBlockAggregate buildAndMergeAggregates(List<TimeBlock> timeBlocks, List<LeaveBlock> leaveBlocks,
654 CalendarEntries calendarEntries, Calendar calendar, List<Interval> dayIntervals) {
655 TkTimeBlockAggregate tkTimeBlockAggregate = new TkTimeBlockAggregate(timeBlocks, calendarEntries, calendar, true, dayIntervals);
656 LeaveBlockAggregate leaveBlockAggregate = new LeaveBlockAggregate(leaveBlocks, calendarEntries);
657 return TkTimeBlockAggregate.combineTimeAndLeaveAggregates(tkTimeBlockAggregate, leaveBlockAggregate);
658 }
659
660
661
662
663 @Override
664 public Map<String, BigDecimal> getHoursToFlsaWeekMap(String principalId,
665 Date payEndDate, List<String> payCalendarLabels,
666 List<TimeBlock> lstTimeBlocks, List<LeaveBlock> leaveBlocks, Long workArea,
667 CalendarEntries payCalendarEntries, Calendar payCalendar,
668 DateTimeZone dateTimeZone, List<Interval> dayIntervals) {
669
670 Map<String, BigDecimal> hoursToFlsaWeekMap = new LinkedHashMap<String, BigDecimal>();
671
672 TkTimeBlockAggregate tkTimeBlockAggregate = buildAndMergeAggregates(lstTimeBlocks, leaveBlocks, payCalendarEntries, payCalendar, dayIntervals);
673 List<List<FlsaWeek>> flsaWeeks = tkTimeBlockAggregate.getFlsaWeeks(dateTimeZone, principalId);
674
675 int weekCount = 1;
676 for (List<FlsaWeek> flsaWeekParts : flsaWeeks) {
677 BigDecimal weekTotal = new BigDecimal(0.00);
678 for (FlsaWeek flsaWeekPart : flsaWeekParts) {
679 for (FlsaDay flsaDay : flsaWeekPart.getFlsaDays()) {
680 for (TimeBlock timeBlock : flsaDay.getAppliedTimeBlocks()) {
681 for (TimeHourDetail thd : timeBlock.getTimeHourDetails()) {
682 if (workArea != null) {
683 if (timeBlock.getWorkArea().compareTo(workArea) == 0) {
684 weekTotal = weekTotal.add(thd.getHours(), TkConstants.MATH_CONTEXT);
685 } else {
686 weekTotal = weekTotal.add(new BigDecimal("0"), TkConstants.MATH_CONTEXT);
687 }
688 } else {
689 weekTotal = weekTotal.add(thd.getHours(),TkConstants.MATH_CONTEXT);
690 }
691 }
692 }
693 }
694 }
695 hoursToFlsaWeekMap.put("Week " + weekCount++, weekTotal);
696 }
697
698 return hoursToFlsaWeekMap;
699 }
700
701 public boolean doesApproverHavePrincipalsForCalendarGroup(Date asOfDate,
702 String calGroup) {
703 Set<Long> approverWorkAreas = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getApproverWorkAreas();
704 for (Long workArea : approverWorkAreas) {
705 List<Assignment> assignments = TkServiceLocator
706 .getAssignmentService().getActiveAssignmentsForWorkArea(
707 workArea, new java.sql.Date(asOfDate.getTime()));
708 List<String> principalIds = new ArrayList<String>();
709 for (Assignment assign : assignments) {
710 if (principalIds.contains(assign.getPrincipalId())) {
711 continue;
712 }
713 principalIds.add(assign.getPrincipalId());
714 }
715
716 for (String principalId : principalIds) {
717 PrincipalHRAttributes principalCal = TkServiceLocator
718 .getPrincipalHRAttributeService().getPrincipalCalendar(
719 principalId, asOfDate);
720 if (StringUtils.equals(principalCal.getPayCalendar(),
721 calGroup)) {
722 return true;
723 }
724 }
725 }
726 return false;
727 }
728
729 @Override
730 public List<Note> getNotesForDocument(String documentNumber) {
731 return KewApiServiceLocator.getNoteService().getNotes(documentNumber);
732 }
733
734 @Override
735 public List<String> getTimePrincipalIdsWithSearchCriteria(List<String> workAreaList, String calendarGroup, java.sql.Date effdt, java.sql.Date beginDate, java.sql.Date endDate) {
736 if (CollectionUtils.isEmpty(workAreaList)) {
737 return new ArrayList<String>();
738 }
739 List<Assignment> assignmentList = TkServiceLocator.getAssignmentService().getAssignments(workAreaList, effdt, beginDate, endDate);
740 List<Assignment> tempList = this.removeNoTimeAssignment(assignmentList);
741 Set<String> pids = new HashSet<String>();
742 for(Assignment anAssignment : tempList) {
743 if(anAssignment != null) {
744 pids.add(anAssignment.getPrincipalId());
745 }
746 }
747 List<String> ids = new ArrayList<String>();
748 ids.addAll(pids);
749
750 if(CollectionUtils.isEmpty(ids)) {
751 return new ArrayList<String>();
752 }
753
754 List<String> idList = TkServiceLocator.getPrincipalHRAttributeService()
755 .getActiveEmployeesIdForTimeCalendarAndIdList(calendarGroup, ids, endDate);
756 if(CollectionUtils.isEmpty(idList)) {
757 return new ArrayList<String>();
758 }
759 return idList;
760 }
761
762 private List<Assignment> removeNoTimeAssignment(List<Assignment> assignmentList) {
763 List<Assignment> results = new ArrayList<Assignment>();
764 if(CollectionUtils.isNotEmpty(assignmentList)) {
765 for(Assignment anAssignment: assignmentList) {
766 if(anAssignment != null
767 && anAssignment.getJob() != null
768 && anAssignment.getJob().getFlsaStatus() != null
769 && anAssignment.getJob().getFlsaStatus().equalsIgnoreCase(TkConstants.FLSA_STATUS_NON_EXEMPT)) {
770 results.add(anAssignment);
771 }
772 }
773 }
774 return results;
775 }
776
777 @Override
778 public Map<String, TimesheetDocumentHeader> getPrincipalDocumentHeader(
779 List<String> principalIds, Date payBeginDate, Date payEndDate) {
780 Map<String, TimesheetDocumentHeader> principalDocumentHeader = new LinkedHashMap<String, TimesheetDocumentHeader>();
781 for (String principalId : principalIds) {
782
783 TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, payBeginDate, DateUtils.addMilliseconds(payEndDate, 1));
784 if(tdh != null) {
785 principalDocumentHeader.put(principalId, tdh);
786 }
787 }
788 return principalDocumentHeader;
789 }
790
791 @Override
792 public Multimap<String, Long> getDeptWorkAreasByWorkAreas(
793 Set<Long> approverWorkAreas) {
794 Multimap<String, Long> deptWorkAreas = HashMultimap.create();
795
796 if (approverWorkAreas.size() > 0) {
797
798 StringBuilder workAreas = new StringBuilder();
799 for (Long workarea : approverWorkAreas) {
800 if(workarea != null) {
801 workAreas.append("work_area = " + workarea + " or ");
802 }
803 }
804 String workAreasForQuery = workAreas.substring(0,
805 workAreas.length() - 3);
806 String sql = "SELECT DISTINCT work_area, dept FROM tk_work_area_t "
807 + "WHERE " + workAreasForQuery + " AND effdt <= ?";
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823 SqlRowSet rs = TkServiceLocator.getTkJdbcTemplate().queryForRowSet(
824 sql, new Object[] { TKUtils.getCurrentDate() },
825 new int[] { Types.DATE });
826 while (rs.next()) {
827 deptWorkAreas
828 .put(rs.getString("dept"), rs.getLong("work_area"));
829 }
830 }
831 return deptWorkAreas;
832 }
833
834 @Override
835 public Multimap<String, Long> getDeptWorkAreasByDepts(Set<String> userDepts) {
836 Multimap<String, Long> deptWorkAreas = HashMultimap.create();
837
838 if (userDepts.size() > 0) {
839
840 StringBuilder depts = new StringBuilder();
841 for (String dept : userDepts) {
842 depts.append("dept = '" + dept + "' or ");
843 }
844 String deptsForQuery = depts.substring(0, depts.length() - 4);
845 String sql = "SELECT DISTINCT work_area, dept FROM tk_work_area_t "
846 + "WHERE " + deptsForQuery + " AND effdt <= ?";
847
848 SqlRowSet rs = TkServiceLocator.getTkJdbcTemplate().queryForRowSet(
849 sql, new Object[] { TKUtils.getCurrentDate() },
850 new int[] { Types.DATE });
851 while (rs.next()) {
852 deptWorkAreas
853 .put(rs.getString("dept"), rs.getLong("work_area"));
854 }
855 }
856 return deptWorkAreas;
857 }
858
859 public DocumentRouteHeaderValue getRouteHeader(String documentId) {
860 return KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
861 }
862
863 @Override
864 public List<CalendarEntries> getAllPayCalendarEntriesForApprover(String principalId, Date currentDate) {
865 Set<String> principals = new HashSet<String>();
866 UserRoles userRoles = TkUserRoles.getUserRoles(principalId);
867 Set<Long> approverWorkAreas = userRoles.getApproverWorkAreas();
868 approverWorkAreas.addAll(userRoles.getReviewerWorkAreas());
869
870
871 for (Long waNum : approverWorkAreas) {
872 List<Assignment> assignments = TkServiceLocator
873 .getAssignmentService().getActiveAssignmentsForWorkArea(waNum, TKUtils.getTimelessDate(currentDate));
874
875 if (assignments != null) {
876 for (Assignment assignment : assignments) {
877 principals.add(assignment.getPrincipalId());
878 }
879 }
880 }
881 List<TimesheetDocumentHeader> documentHeaders = new ArrayList<TimesheetDocumentHeader>();
882 for(String pid : principals) {
883 documentHeaders.addAll(TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeadersForPrincipalId(pid));
884 }
885 Set<CalendarEntries> payPeriodSet = new HashSet<CalendarEntries>();
886 for(TimesheetDocumentHeader tdh : documentHeaders) {
887 CalendarEntries pe = TkServiceLocator.getTimesheetService().getTimesheetDocument(tdh.getDocumentId()).getCalendarEntry();
888 if(pe != null) {
889 payPeriodSet.add(pe);
890 }
891 }
892 List<CalendarEntries> ppList = new ArrayList<CalendarEntries>(payPeriodSet);
893
894 return ppList;
895 }
896
897 }