001/** 002 * Copyright 2004-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.kpme.tklm.time.approval.service; 017 018import org.apache.commons.collections.CollectionUtils; 019import org.apache.commons.lang.StringUtils; 020import org.joda.time.DateTime; 021import org.joda.time.DateTimeZone; 022import org.joda.time.Hours; 023import org.joda.time.Interval; 024import org.joda.time.LocalDate; 025import org.json.simple.JSONValue; 026import org.kuali.kpme.core.api.accrualcategory.AccrualCategory; 027import org.kuali.kpme.core.api.accrualcategory.rule.AccrualCategoryRuleContract; 028import org.kuali.kpme.core.api.assignment.Assignment; 029import org.kuali.kpme.core.api.calendar.Calendar; 030import org.kuali.kpme.core.api.calendar.entry.CalendarEntry; 031import org.kuali.kpme.core.calendar.web.CalendarDay; 032import org.kuali.kpme.core.calendar.web.CalendarWeek; 033import org.kuali.kpme.core.service.HrServiceLocator; 034import org.kuali.kpme.core.util.HrConstants; 035import org.kuali.kpme.core.util.HrContext; 036import org.kuali.kpme.core.util.TKUtils; 037import org.kuali.kpme.tklm.api.common.TkConstants; 038import org.kuali.kpme.tklm.api.leave.block.LeaveBlock; 039import org.kuali.kpme.tklm.api.leave.block.LeaveBlockContract; 040import org.kuali.kpme.tklm.api.time.clocklog.ClockLog; 041import org.kuali.kpme.tklm.api.time.timeblock.TimeBlock; 042import org.kuali.kpme.tklm.api.time.timehourdetail.TimeHourDetail; 043import org.kuali.kpme.tklm.api.time.timesummary.TimeSummaryContract; 044import org.kuali.kpme.tklm.leave.block.LeaveBlockAggregate; 045import org.kuali.kpme.tklm.leave.calendar.validation.LeaveCalendarValidationUtil; 046import org.kuali.kpme.tklm.leave.service.LmServiceLocator; 047import org.kuali.kpme.tklm.time.approval.summaryrow.ApprovalTimeSummaryRow; 048import org.kuali.kpme.tklm.time.calendar.TkCalendar; 049import org.kuali.kpme.tklm.time.calendar.TkCalendarDay; 050import org.kuali.kpme.tklm.time.flsa.FlsaDay; 051import org.kuali.kpme.tklm.time.flsa.FlsaWeek; 052import org.kuali.kpme.tklm.time.rules.timecollection.TimeCollectionRule; 053import org.kuali.kpme.tklm.time.service.TkServiceLocator; 054import org.kuali.kpme.tklm.time.timeblock.web.TimeBlockRenderer; 055import org.kuali.kpme.tklm.time.timehourdetail.TimeHourDetailRenderer; 056import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument; 057import org.kuali.kpme.tklm.time.util.TkTimeBlockAggregate; 058import org.kuali.kpme.tklm.time.workflow.TimesheetDocumentHeader; 059import org.kuali.rice.kew.api.KewApiServiceLocator; 060import org.kuali.rice.kew.api.note.Note; 061import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName; 062import org.kuali.rice.kim.api.services.KimApiServiceLocator; 063 064import java.math.BigDecimal; 065import java.util.ArrayList; 066import java.util.HashMap; 067import java.util.HashSet; 068import java.util.LinkedHashMap; 069import java.util.LinkedList; 070import java.util.List; 071import java.util.Map; 072import java.util.Map.Entry; 073import java.util.Set; 074 075public class TimeApproveServiceImpl implements TimeApproveService { 076 077 @Override 078 public List<ApprovalTimeSummaryRow> getApprovalSummaryRows(String calGroup, List<String> principalIds, List<String> payCalendarLabels, CalendarEntry payCalendarEntry, String docIdSearchTerm) { 079 DateTime payBeginDate = payCalendarEntry.getBeginPeriodFullDateTime(); 080 DateTime payEndDate = payCalendarEntry.getEndPeriodFullDateTime(); 081 082 List<Map<String, Object>> timeBlockJsonMap = new ArrayList<Map<String,Object>>(); 083 List<ApprovalTimeSummaryRow> rows = new LinkedList<ApprovalTimeSummaryRow>(); 084 Map<String, TimesheetDocumentHeader> principalDocumentHeader = getPrincipalDocumentHeader( 085 principalIds, payBeginDate, payEndDate, docIdSearchTerm); 086 087 Calendar payCalendar = HrServiceLocator.getCalendarService() 088 .getCalendar(payCalendarEntry.getHrCalendarId()); 089 DateTimeZone dateTimeZone = HrServiceLocator.getTimezoneService() 090 .getUserTimezoneWithFallback(); 091 List<Interval> dayIntervals = TKUtils 092 .getDaySpanForCalendarEntry(payCalendarEntry); 093 094 095 String color = null; 096 097 Map<String, String> userColorMap = new HashMap<String, String>(); 098 Set<String> randomColors = new HashSet<String>(); 099 100 String approverId = HrContext.getPrincipalId(); 101 String timeZoneString = HrServiceLocator.getTimezoneService().getApproverTimezone(approverId); 102 DateTimeZone approverTimeZone = StringUtils.isNotBlank(timeZoneString) ? DateTimeZone.forID(timeZoneString) : null; 103 104 for (String principalId : principalIds) { 105 TimesheetDocumentHeader tdh = new TimesheetDocumentHeader(); 106 String documentId = ""; 107 if (principalDocumentHeader.containsKey(principalId)) { 108 tdh = principalDocumentHeader.get(principalId); 109 documentId = principalDocumentHeader.get(principalId).getDocumentId(); 110 } else if(StringUtils.isNotBlank(docIdSearchTerm)){ 111 continue; // if there's a search term for document id, only build the rows for principalIds from principalDocumentHeader 112 } 113 List<TimeBlock> timeBlocks = new ArrayList<TimeBlock>(); 114 List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>(); 115 List<Note> notes = new ArrayList<Note>(); 116 List<String> warnings = new ArrayList<String>(); 117 List<String> clockLogWarnings = new ArrayList<String>(); 118 119 ApprovalTimeSummaryRow approvalSummaryRow = new ApprovalTimeSummaryRow(); 120 121 if (principalDocumentHeader.containsKey(principalId)) { 122 approvalSummaryRow 123 .setApprovalStatus(HrConstants.DOC_ROUTE_STATUS.get(tdh 124 .getDocumentStatus())); 125 } 126 TimesheetDocument td = null; 127 if (StringUtils.isNotBlank(documentId)) { 128 td = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId); 129 timeBlocks = td.getTimeBlocks(); 130 clockLogWarnings = TkServiceLocator.getClockLogService().getUnapprovedIPWarning(timeBlocks); 131 //timeBlocks = TkServiceLocator.getTimeBlockService() 132 // .getTimeBlocks(documentId); 133 List<String> assignKeys = new ArrayList<String>(); 134 for(Assignment a : td.getAllAssignments()) { 135 assignKeys.add(a.getAssignmentKey()); 136 } 137 leaveBlocks.addAll(LmServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(principalId, 138 payBeginDate.toLocalDate(), payEndDate.toLocalDate(), assignKeys)); 139 notes = getNotesForDocument(documentId); 140 Map<String, List<LocalDate>> earnCodeMap = new HashMap<String, List<LocalDate>>(); 141 for(TimeBlock tb : td.getTimeBlocks()) { 142 if(!earnCodeMap.containsKey(tb.getEarnCode())) { 143 List<LocalDate> lst = new ArrayList<LocalDate>(); 144 lst.add(tb.getBeginDateTime().toLocalDate()); 145 earnCodeMap.put(tb.getEarnCode(), lst); 146 } 147 else 148 earnCodeMap.get(tb.getEarnCode()).add(tb.getBeginDateTime().toLocalDate()); 149 } 150 warnings = HrServiceLocator.getEarnCodeGroupService().getWarningTextFromEarnCodeGroups(earnCodeMap); 151 152 // Get Timesheet blocks 153 154 155 List<Interval> intervals = TKUtils.getFullWeekDaySpanForCalendarEntry(payCalendarEntry); 156 TkTimeBlockAggregate tbAggregate = buildAndMergeAggregates(timeBlocks, leaveBlocks, payCalendarEntry, payCalendar, dayIntervals); 157// TkTimeBlockAggregate tbAggregate = new TkTimeBlockAggregate(timeBlocks, payCalendarEntry, payCalendar, true,intervals); 158 // use both time aggregate to populate the calendar 159 TkCalendar cal = TkCalendar.getCalendar(tbAggregate); 160 161 162 for (CalendarWeek week : cal.getWeeks()) { 163 for(CalendarDay day : week.getDays()) { 164 TkCalendarDay tkDay = (TkCalendarDay) day; 165 for (TimeBlockRenderer renderer : tkDay.getBlockRenderers()) { 166 Map<String, Object> timeBlockMap = new HashMap<String, Object>(); 167 168 // set title.. 169 StringBuffer title = new StringBuffer(); 170 if(!renderer.getEarnCodeType().equalsIgnoreCase(HrConstants.EARN_CODE_AMOUNT)) { 171 if(renderer.getDetailRenderers() != null && !renderer.getDetailRenderers().isEmpty()) { 172 for(TimeHourDetailRenderer thdr : renderer.getDetailRenderers()) { 173 title.append("\n"); 174 title = new StringBuffer(thdr.getTitle()); 175 title.append(" - "+thdr.getHours()); 176 } 177 } 178 } 179 180 timeBlockMap.put("start", tkDay.getDateString()); 181 StringBuffer titleString = new StringBuffer(); 182 titleString.append(renderer.getTitle()); 183 if(renderer.getTimeRange() != null && !renderer.getTimeRange().isEmpty()) { 184 titleString.append("\n" +renderer.getTimeRange()); 185 } 186 titleString.append("\n"+title.toString()); 187 timeBlockMap.put("title", titleString.toString()); 188 timeBlockMap.put("id", tkDay.getDayNumberString()); 189 if(!userColorMap.containsKey(principalId)) { 190 color = TKUtils.getRandomColor(randomColors); 191 randomColors.add(color); 192 userColorMap.put(principalId, color); 193 } 194 color = userColorMap.get(principalId); 195 timeBlockMap.put("color", userColorMap.get(principalId)); 196 timeBlockMap.put("className", "event-approval"); 197 timeBlockJsonMap.add(timeBlockMap); 198 } 199 } 200 } 201 202 warnings = HrServiceLocator.getEarnCodeGroupService().getWarningTextFromEarnCodeGroups(td.getEarnCodeMap()); 203 } 204 205 Map<String, Set<String>> transactionalWarnings = LeaveCalendarValidationUtil.validatePendingTransactions(principalId, payCalendarEntry.getBeginPeriodFullDateTime().toLocalDate(), payCalendarEntry.getEndPeriodFullDateTime().toLocalDate()); 206 207 warnings.addAll(transactionalWarnings.get("infoMessages")); 208 warnings.addAll(transactionalWarnings.get("warningMessages")); 209 warnings.addAll(transactionalWarnings.get("actionMessages")); 210 211 Map<String, Set<String>> eligibleTransfers = findWarnings(principalId, payCalendarEntry); 212 warnings.addAll(eligibleTransfers.get("warningMessages")); 213 214 warnings.addAll(clockLogWarnings); 215 Map<String, BigDecimal> hoursToPayLabelMap = getHoursToPayDayMap( 216 principalId, payEndDate, payCalendarLabels, 217 timeBlocks, leaveBlocks, null, payCalendarEntry, payCalendar, 218 dateTimeZone, dayIntervals); 219 220 Map<String, BigDecimal> hoursToFlsaPayLabelMap = getHoursToFlsaWeekMap( 221 principalId, payEndDate, payCalendarLabels, 222 timeBlocks, leaveBlocks, null, payCalendarEntry, payCalendar, 223 dateTimeZone, dayIntervals); 224 225 EntityNamePrincipalName name = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId); 226 approvalSummaryRow.setName(name != null 227 && name.getDefaultName() != null 228 && name.getDefaultName().getCompositeName() != null ? name.getDefaultName().getCompositeName() : principalId); 229 approvalSummaryRow.setPrincipalId(principalId); 230 approvalSummaryRow.setColor(userColorMap.get(principalId)); 231 approvalSummaryRow.setPayCalendarGroup(calGroup); 232 approvalSummaryRow.setDocumentId(documentId); 233 234 235 approvalSummaryRow.setHoursToPayLabelMap(hoursToPayLabelMap); 236 approvalSummaryRow.setHoursToFlsaPayLabelMap(hoursToFlsaPayLabelMap); 237 approvalSummaryRow.setPeriodTotal(hoursToPayLabelMap 238 .get("Period Total")); 239 approvalSummaryRow.setLstTimeBlocks(timeBlocks); 240 approvalSummaryRow.setNotes(notes); 241 approvalSummaryRow.setWarnings(warnings); 242 243 // Compare last clock log versus now and if > threshold 244 // highlight entry 245 ClockLog lastClockLog = TkServiceLocator.getClockLogService() 246 .getLastClockLog(principalId); 247 if (isSynchronousUser(principalId)) { 248 approvalSummaryRow.setClockStatusMessage(createLabelForLastClockLog(lastClockLog, approverTimeZone)); 249 } 250 if (lastClockLog != null 251 && (StringUtils.equals(lastClockLog.getClockAction(), 252 TkConstants.CLOCK_IN) || StringUtils 253 .equals(lastClockLog.getClockAction(), 254 TkConstants.LUNCH_IN))) { 255 DateTime startTime = lastClockLog.getClockDateTime(); 256 DateTime endTime = new DateTime(); 257 258 Hours hour = Hours.hoursBetween(startTime, endTime); 259 if (hour != null) { 260 int elapsedHours = hour.getHours(); 261 if (elapsedHours >= TkConstants.NUMBER_OF_HOURS_CLOCKED_IN_APPROVE_TAB_HIGHLIGHT && isSynchronousUser(principalId)) { 262 approvalSummaryRow.setClockedInOverThreshold(true); 263 } 264 } 265 266 } 267 //KPME-2563 268 try{ 269 if(td != null) { 270 TimeSummaryContract ts = TkServiceLocator.getTimeSummaryService() 271 .getTimeSummary(td.getPrincipalId(), td.getTimeBlocks(), td.getCalendarEntry(), td.getAssignmentMap()); 272 approvalSummaryRow.setTimeSummary(ts); 273 } 274 } catch (Exception ex){ 275 ex.printStackTrace(); 276 } 277 rows.add(approvalSummaryRow); 278 } 279 280 String outputString = JSONValue.toJSONString(timeBlockJsonMap); 281 if(rows != null && !rows.isEmpty()) { 282 rows.get(0).setOutputString(outputString); 283 } 284 return rows; 285 } 286 287 private boolean isSynchronousUser(String principalId) { 288 List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments(principalId, LocalDate.now()); 289 boolean isSynchronousUser = false; 290 if (CollectionUtils.isNotEmpty(assignments)) { 291 for (Assignment assignment : assignments) { 292 if(assignment.getJob() != null) { 293 TimeCollectionRule tcr = TkServiceLocator.getTimeCollectionRuleService().getTimeCollectionRule(assignment.getDept(), assignment.getWorkArea(), assignment.getJob().getHrPayType(), assignment.getGroupKeyCode(), LocalDate.now()); 294 isSynchronousUser |= (tcr == null || tcr.isClockUserFl()); 295 } 296 } 297 } 298 return isSynchronousUser; 299 } 300 301 private Map<String, Set<String>> findWarnings(String principalId, CalendarEntry calendarEntry) { 302 Map<String, Set<String>> allMessages = new HashMap<String,Set<String>>(); 303 allMessages.put("warningMessages", new HashSet<String>()); 304 305 Map<String, Set<LeaveBlockContract>> eligibilities = LmServiceLocator.getAccrualCategoryMaxBalanceService().getMaxBalanceViolations(calendarEntry, principalId); 306 307 if (eligibilities != null) { 308 for (Entry<String,Set<LeaveBlockContract>> entry : eligibilities.entrySet()) { 309 for(LeaveBlockContract lb : entry.getValue()) { 310 AccrualCategoryRuleContract rule = lb.getAccrualCategoryRule(); 311 if (rule != null) { 312 AccrualCategory accrualCategory = HrServiceLocator.getAccrualCategoryService().getAccrualCategory(rule.getLmAccrualCategoryId()); 313 if (rule.getActionAtMaxBalance().equals(HrConstants.ACTION_AT_MAX_BALANCE.TRANSFER)) { 314 //Todo: add link to balance transfer 315 allMessages.get("warningMessages").add("Accrual Category '" + accrualCategory.getAccrualCategory() + "' is over max balance."); //warningMessages 316 } else if (rule.getActionAtMaxBalance().equals(HrConstants.ACTION_AT_MAX_BALANCE.LOSE)) { 317 //Todo: compute and display amount of time lost. 318 allMessages.get("warningMessages").add("Accrual Category '" + accrualCategory.getAccrualCategory() + "' is over max balance."); //warningMessages 319 } else if (rule.getActionAtMaxBalance().equals(HrConstants.ACTION_AT_MAX_BALANCE.PAYOUT)) { 320 //Todo: display payout details. 321 allMessages.get("warningMessages").add("Accrual Category '" + accrualCategory.getAccrualCategory() + "' is over max balance."); //warningMessages 322 } 323 } 324 } 325 } 326 } 327 328 return allMessages; 329 } 330 331 /** 332 * Create label for the last clock log 333 * 334 * @param cl 335 * @return 336 */ 337 private String createLabelForLastClockLog(ClockLog cl, DateTimeZone approverTimeZone) { 338 if (cl == null) { 339 return "No previous clock information"; 340 } 341 342 String zoneString = ""; 343 DateTime clockTimeWithZone = cl.getClockDateTime(); 344 if(approverTimeZone != null) { 345 clockTimeWithZone = clockTimeWithZone.withZone(approverTimeZone); 346 zoneString = DateTime.now(approverTimeZone).toString("z");; 347 } 348 String dateTime = clockTimeWithZone.toString(TkConstants.DT_FULL_DATE_TIME_FORMAT); 349 dateTime += " " + zoneString; 350 351 if (StringUtils.equals(cl.getClockAction(), TkConstants.CLOCK_IN)) { 352 return "Clocked in since: " + dateTime; 353 } else if (StringUtils.equals(cl.getClockAction(), 354 TkConstants.LUNCH_OUT)) { 355 return "At Lunch since: " + dateTime; 356 } else if (StringUtils 357 .equals(cl.getClockAction(), TkConstants.LUNCH_IN)) { 358 return "Returned from Lunch : " + dateTime; 359 } else if (StringUtils.equals(cl.getClockAction(), 360 TkConstants.CLOCK_OUT)) { 361 return "Clocked out since: " + dateTime; 362 } else { 363 return "No previous clock information"; 364 } 365 } 366 367 /** 368 * Aggregate TimeBlocks to hours per day and sum for week 369 */ 370 @Override 371 public Map<String, BigDecimal> getHoursToPayDayMap(String principalId, 372 DateTime payEndDate, List<String> payCalendarLabels, 373 List<TimeBlock> lstTimeBlocks, List<LeaveBlock> leaveBlocks, Long workArea, 374 CalendarEntry payCalendarEntry, Calendar payCalendar, 375 DateTimeZone dateTimeZone, List<Interval> dayIntervals) { 376 Map<String, BigDecimal> hoursToPayLabelMap = new LinkedHashMap<String, BigDecimal>(); 377 List<BigDecimal> dayTotals = new ArrayList<BigDecimal>(); 378 379 TkTimeBlockAggregate tkTimeBlockAggregate = buildAndMergeAggregates(lstTimeBlocks, leaveBlocks, payCalendarEntry, payCalendar, dayIntervals); 380 381 List<FlsaWeek> flsaWeeks = tkTimeBlockAggregate.getFlsaWeeks(dateTimeZone,0, false); 382 for (FlsaWeek week : flsaWeeks) { 383 for (FlsaDay day : week.getFlsaDays()) { 384 BigDecimal total = new BigDecimal(0.00); 385 for (TimeBlock tb : day.getAppliedTimeBlocks()) { 386 for (TimeHourDetail thd : tb.getTimeHourDetails()) { 387 if (workArea != null) { 388 if (tb.getWorkArea().compareTo(workArea) == 0) { 389 total = total.add(thd.getHours(), 390 HrConstants.MATH_CONTEXT); 391 } else { 392 total = total.add(new BigDecimal("0"), 393 HrConstants.MATH_CONTEXT); 394 } 395 } else { 396 total = total.add(thd.getHours(), 397 HrConstants.MATH_CONTEXT); 398 } 399 } 400 } 401 dayTotals.add(total); 402 } 403 } 404 405 int dayCount = 0; 406 BigDecimal weekTotal = new BigDecimal(0.00); 407 BigDecimal periodTotal = new BigDecimal(0.00); 408 for (String payCalendarLabel : payCalendarLabels) { 409 if (StringUtils.contains(payCalendarLabel, "Week")) { 410 hoursToPayLabelMap.put(payCalendarLabel, weekTotal); 411 weekTotal = new BigDecimal(0.00); 412 } else if (StringUtils.contains(payCalendarLabel, "Period Total")) { 413 hoursToPayLabelMap.put(payCalendarLabel, periodTotal); 414 } else { 415 if(dayCount < dayTotals.size()) { 416 hoursToPayLabelMap.put(payCalendarLabel, 417 dayTotals.get(dayCount)); 418 weekTotal = weekTotal.add(dayTotals.get(dayCount), 419 HrConstants.MATH_CONTEXT); 420 periodTotal = periodTotal.add(dayTotals.get(dayCount)); 421 dayCount++; 422 } 423 424 } 425 426 } 427 return hoursToPayLabelMap; 428 } 429 430 private TkTimeBlockAggregate buildAndMergeAggregates(List<TimeBlock> timeBlocks, List<LeaveBlock> leaveBlocks, 431 CalendarEntry calendarEntries, Calendar calendar, List<Interval> dayIntervals) { 432 TkTimeBlockAggregate tkTimeBlockAggregate = new TkTimeBlockAggregate(timeBlocks, calendarEntries, calendar, true, dayIntervals); 433 LeaveBlockAggregate leaveBlockAggregate = new LeaveBlockAggregate(leaveBlocks, calendarEntries); 434 return TkTimeBlockAggregate.combineTimeAndLeaveAggregates(tkTimeBlockAggregate, leaveBlockAggregate); 435 } 436 437 /** 438 * Aggregate TimeBlocks to hours per day and sum for flsa week (including previous/next weeks) 439 */ 440 @Override 441 public Map<String, BigDecimal> getHoursToFlsaWeekMap(String principalId, 442 DateTime payEndDate, List<String> payCalendarLabels, 443 List<TimeBlock> lstTimeBlocks, List<LeaveBlock> leaveBlocks, 444 Long workArea, CalendarEntry payCalendarEntry, Calendar payCalendar, 445 DateTimeZone dateTimeZone, List<Interval> dayIntervals) { 446 447 Map<String, BigDecimal> hoursToFlsaWeekMap = new LinkedHashMap<String, BigDecimal>(); 448 449 TkTimeBlockAggregate tkTimeBlockAggregate = buildAndMergeAggregates(lstTimeBlocks, leaveBlocks, payCalendarEntry, payCalendar, dayIntervals); 450 List<List<FlsaWeek>> flsaWeeks = tkTimeBlockAggregate.getFlsaWeeks(dateTimeZone, principalId); 451 452 int weekCount = 1; 453 for (List<FlsaWeek> flsaWeekParts : flsaWeeks) { 454 BigDecimal weekTotal = new BigDecimal(0.00); 455 for (FlsaWeek flsaWeekPart : flsaWeekParts) { 456 for (FlsaDay flsaDay : flsaWeekPart.getFlsaDays()) { 457 for (TimeBlock timeBlock : flsaDay.getAppliedTimeBlocks()) { 458 for (TimeHourDetail thd : timeBlock.getTimeHourDetails()) { 459 if (workArea != null) { 460 if (timeBlock.getWorkArea().compareTo(workArea) == 0) { 461 weekTotal = weekTotal.add(thd.getHours(), HrConstants.MATH_CONTEXT); 462 } else { 463 weekTotal = weekTotal.add(new BigDecimal("0"), HrConstants.MATH_CONTEXT); 464 } 465 } else { 466 weekTotal = weekTotal.add(thd.getHours(),HrConstants.MATH_CONTEXT); 467 } 468 } 469 } 470 } 471 } 472 hoursToFlsaWeekMap.put("Week " + weekCount++, weekTotal); 473 } 474 475 return hoursToFlsaWeekMap; 476 } 477 478 @Override 479 public List<Note> getNotesForDocument(String documentNumber) { 480 return KewApiServiceLocator.getNoteService().getNotes(documentNumber); 481 } 482 483 @Override 484 public List<String> getTimePrincipalIdsWithSearchCriteria(List<String> workAreaList, String calendarGroup, LocalDate effdt, LocalDate beginDate, LocalDate endDate) { 485 if (CollectionUtils.isEmpty(workAreaList)) { 486 return new ArrayList<String>(); 487 } 488 List<Assignment> assignmentList = HrServiceLocator.getAssignmentService().getAssignments(workAreaList, effdt, beginDate, endDate); 489 List<Assignment> tempList = this.removeNoTimeAssignment(assignmentList); 490 Set<String> pids = new HashSet<String>(); 491 for(Assignment anAssignment : tempList) { 492 if(anAssignment != null) { 493 pids.add(anAssignment.getPrincipalId()); 494 } 495 } 496 List<String> ids = new ArrayList<String>(); 497 ids.addAll(pids); 498 499 if(CollectionUtils.isEmpty(ids)) { 500 return new ArrayList<String>(); 501 } 502 // use unique principalIds and selected calendarGroup to get unique ids from principalHRAttributes table 503 List<String> idList = HrServiceLocator.getPrincipalHRAttributeService() 504 .getActiveEmployeesIdForTimeCalendarAndIdList(calendarGroup, ids, endDate); 505 if(CollectionUtils.isEmpty(idList)) { 506 return new ArrayList<String>(); 507 } 508 return idList; 509 } 510 511 private List<Assignment> removeNoTimeAssignment(List<Assignment> assignmentList) { 512 List<Assignment> results = new ArrayList<Assignment>(); 513 if(CollectionUtils.isNotEmpty(assignmentList)) { 514 for(Assignment anAssignment: assignmentList) { 515 if(anAssignment != null 516 && anAssignment.getJob() != null 517 && anAssignment.getJob().getFlsaStatus() != null 518 && anAssignment.getJob().getFlsaStatus().equalsIgnoreCase(HrConstants.FLSA_STATUS_NON_EXEMPT)) { 519 results.add(anAssignment); 520 } 521 } 522 } 523 return results; 524 } 525 526 @Override 527 public Map<String, TimesheetDocumentHeader> getPrincipalDocumentHeader( 528 List<String> principalIds, DateTime payBeginDate, DateTime payEndDate, String docIdSearchTerm) { 529 Map<String, TimesheetDocumentHeader> principalDocumentHeader = new LinkedHashMap<String, TimesheetDocumentHeader>(); 530 for (String principalId : principalIds) { 531 532 TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, payBeginDate, payEndDate.plusMillis(1)); 533 if(tdh != null) { 534 if(StringUtils.isNotBlank(docIdSearchTerm)) { 535 if(tdh.getDocumentId().contains(docIdSearchTerm)) { 536 principalDocumentHeader.put(principalId, tdh); 537 } 538 } else { 539 principalDocumentHeader.put(principalId, tdh); 540 } 541 } 542 } 543 return principalDocumentHeader; 544 } 545 546}