Java tutorial
/** * Copyright 2004-2014 The Kuali Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ecl2.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kuali.kpme.tklm.time.timesummary.service; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.joda.time.DateTime; import org.joda.time.DateTimeConstants; import org.joda.time.DateTimeFieldType; import org.joda.time.DateTimeZone; import org.joda.time.Interval; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.kuali.kpme.core.api.accrualcategory.rule.AccrualCategoryRuleContract; import org.kuali.kpme.core.api.assignment.Assignment; import org.kuali.kpme.core.api.assignment.AssignmentDescriptionKey; import org.kuali.kpme.core.api.calendar.Calendar; import org.kuali.kpme.core.api.calendar.entry.CalendarEntry; import org.kuali.kpme.core.api.earncode.EarnCodeContract; import org.kuali.kpme.core.api.earncode.group.EarnCodeGroup; import org.kuali.kpme.core.calendar.entry.CalendarEntryBo; import org.kuali.kpme.core.service.HrServiceLocator; import org.kuali.kpme.core.util.HrConstants; import org.kuali.kpme.core.util.HrContext; import org.kuali.kpme.tklm.api.common.TkConstants; import org.kuali.kpme.tklm.api.leave.block.LeaveBlock; import org.kuali.kpme.tklm.api.leave.block.LeaveBlockContract; import org.kuali.kpme.tklm.api.time.clocklog.ClockLog; import org.kuali.kpme.tklm.api.time.timeblock.TimeBlock; import org.kuali.kpme.tklm.api.time.timehourdetail.TimeHourDetail; import org.kuali.kpme.tklm.api.time.timesummary.TimeSummaryService; import org.kuali.kpme.tklm.leave.block.LeaveBlockAggregate; import org.kuali.kpme.tklm.leave.service.LmServiceLocator; import org.kuali.kpme.tklm.leave.summary.LeaveSummary; import org.kuali.kpme.tklm.leave.summary.LeaveSummaryRow; import org.kuali.kpme.tklm.time.detail.web.ActionFormUtils; import org.kuali.kpme.tklm.time.flsa.FlsaDay; import org.kuali.kpme.tklm.time.flsa.FlsaWeek; import org.kuali.kpme.tklm.time.service.TkServiceLocator; import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument; import org.kuali.kpme.tklm.time.timesummary.AssignmentColumn; import org.kuali.kpme.tklm.time.timesummary.AssignmentRow; import org.kuali.kpme.tklm.time.timesummary.EarnCodeSection; import org.kuali.kpme.tklm.time.timesummary.EarnGroupSection; import org.kuali.kpme.tklm.time.timesummary.TimeSummary; import org.kuali.kpme.tklm.time.util.TkTimeBlockAggregate; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class TimeSummaryServiceImpl implements TimeSummaryService { private static final String OTHER_EARN_GROUP = "Other"; private static final Logger LOG = Logger.getLogger(TimeSummaryServiceImpl.class); @Override public TimeSummary getTimeSummaryForDocument(String timesheetDocumentId) { TimesheetDocument doc = TkServiceLocator.getTimesheetService().getTimesheetDocument(timesheetDocumentId); return getTimeSummary(doc.getPrincipalId(), doc.getTimeBlocks(), doc.getCalendarEntry(), doc.getAssignmentMap()); } @Override public TimeSummary getTimeSummary(String principalId, List<TimeBlock> timeBlocks, CalendarEntry calendarEntry, Map<LocalDate, List<Assignment>> assignments) { TimeSummary timeSummary = new TimeSummary(); //if(principalId == null || CollectionUtils.isEmpty(timeBlocks)) { KPME-3340 if (principalId == null || timeBlocks == null) { return timeSummary; } List<Boolean> dayArrangements = new ArrayList<Boolean>(); timeSummary.setTimeSummaryHeader(getHeaderForSummary(calendarEntry, timeSummary)); String userTZ = HrServiceLocator.getTimezoneService().getUserTimezone(principalId); DateTimeZone userTimeZone = DateTimeZone.forID(userTZ); TkTimeBlockAggregate tkTimeBlockAggregate = new TkTimeBlockAggregate(timeBlocks, calendarEntry, HrServiceLocator.getCalendarService().getCalendar(calendarEntry.getHrCalendarId()), true, userTimeZone); if (userTimeZone == null) { userTimeZone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback(); } List<String> tAssignmentKeys = new ArrayList<String>(); Set<Assignment> allAssignments = new HashSet<Assignment>(); for (List<Assignment> assignmentList : assignments.values()) { allAssignments.addAll(assignmentList); } Set<String> regularEarnCodes = new HashSet<String>(); for (Assignment assign : allAssignments) { tAssignmentKeys.add(assign.getAssignmentKey()); regularEarnCodes.add(assign.getJob().getPayTypeObj().getRegEarnCode()); } List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>(); leaveBlocks.addAll(LmServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(principalId, calendarEntry.getBeginPeriodFullDateTime().toLocalDate(), calendarEntry.getEndPeriodFullDateTime().toLocalDate(), tAssignmentKeys)); LeaveBlockAggregate leaveBlockAggregate = new LeaveBlockAggregate(leaveBlocks, calendarEntry); tkTimeBlockAggregate = TkTimeBlockAggregate.combineTimeAndLeaveAggregates(tkTimeBlockAggregate, leaveBlockAggregate); timeSummary.setWorkedHours( getWorkedHours(principalId, tkTimeBlockAggregate, regularEarnCodes, timeSummary, userTimeZone)); // Set Flsa week total map Map<String, BigDecimal> flsaWeekTotal = getHoursToFlsaWeekMap(tkTimeBlockAggregate, principalId, null, regularEarnCodes, userTimeZone); timeSummary.setFlsaWeekTotalMap(flsaWeekTotal); Map<String, List<EarnGroupSection>> earnGroupSections = getEarnGroupSections(principalId, tkTimeBlockAggregate, timeSummary.getTimeSummaryHeader().size() + 1, dayArrangements, calendarEntry.getEndPeriodFullDateTime().toLocalDate(), calendarEntry.getEndPeriodFullDateTime().toLocalDate()); timeSummary.setWeeklySections(earnGroupSections); for (String key : timeSummary.getWeeklySections().keySet()) { timeSummary.getWeeklySections().put(key, sortEarnGroupSections(timeSummary.getWeeklySections().get(key), regularEarnCodes)); } // timeSummary.setSections(sortEarnGroupSections(earnGroupSections, regularEarnCodes)); Map<String, String> aMap = ActionFormUtils.buildAssignmentStyleClassMap(timeBlocks, leaveBlocks); // set css classes for each assignment row for (String week : timeSummary.getWeeklySections().keySet()) { for (EarnGroupSection earnGroupSection : timeSummary.getWeeklySections().get(week)) { for (EarnCodeSection section : earnGroupSection.getEarnCodeSections()) { for (AssignmentRow assignRow : section.getAssignmentsRows()) { String assignmentCssStyle = MapUtils.getString(aMap, assignRow.getAssignmentKey()); assignRow.setCssClass(assignmentCssStyle); for (AssignmentColumn assignmentColumn : assignRow.getAssignmentColumns().values()) { assignmentColumn.setCssClass(assignmentCssStyle); } } } } } try { List<LeaveSummaryRow> maxedLeaveRows = getMaxedLeaveRows(calendarEntry, principalId); timeSummary.setMaxedLeaveRows(maxedLeaveRows); } catch (Exception e) { // TODO Auto-generated catch block LOG.error("error retreiving maxed leave rows", e); } return timeSummary; } private List<EarnGroupSection> sortEarnGroupSections(List<EarnGroupSection> sections, Set<String> regularEarnCodes) { List<EarnGroupSection> sortedList = new ArrayList<EarnGroupSection>(); //first sort by alpha Collections.sort(sections, new Comparator<EarnGroupSection>() { @Override public int compare(EarnGroupSection egs1, EarnGroupSection egs2) { if (egs1 == null ^ egs2 == null) { return egs1 == null ? -1 : 1; } if (egs1 == null && egs2 == null) { return 0; } //'other' earn group needs to be last. boolean isOther1 = StringUtils.equals(egs1.getEarnGroup(), OTHER_EARN_GROUP); boolean isOther2 = StringUtils.equals(egs2.getEarnGroup(), OTHER_EARN_GROUP); if (isOther1 ^ isOther2) { return isOther1 ? 1 : -1; } if (isOther1 && isOther2) { return 0; } return egs1.getEarnGroup().compareTo(egs2.getEarnGroup()); } }); List<EarnGroupSection> copy = new ArrayList<EarnGroupSection>(sections); //loop through in reverse for (EarnGroupSection egs : copy) { if (!CollectionUtils.intersection(regularEarnCodes, egs.getEarnCodeToEarnCodeSectionMap().keySet()) .isEmpty()) { sortedList.add(egs); sections.remove(egs); } } sortedList.addAll(sections); return sortedList; } private List<LeaveSummaryRow> getMaxedLeaveRows(CalendarEntry calendarEntry, String principalId) throws Exception { List<LeaveSummaryRow> maxedLeaveRows = new ArrayList<LeaveSummaryRow>(); if (LmServiceLocator.getLeaveApprovalService().isActiveAssignmentFoundOnJobFlsaStatus(principalId, HrConstants.FLSA_STATUS_NON_EXEMPT, true)) { Map<String, Set<LeaveBlock>> eligibilities = LmServiceLocator.getAccrualCategoryMaxBalanceService() .getMaxBalanceViolations(calendarEntry, principalId); Set<? extends LeaveBlock> onDemandTransfers = eligibilities .get(HrConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND); Interval calendarEntryInterval = new Interval(calendarEntry.getBeginPeriodFullDateTime(), calendarEntry.getEndPeriodFullDateTime()); //use the current date if on the current calendar? yes -> no warning given until accrual is reached. If accrual occurs on last day of period or last day of service interval //change, no warning given to the employee of balance limits being exceeded except on or after that day. if (!onDemandTransfers.isEmpty()) { for (LeaveBlock lb : onDemandTransfers) { LocalDate leaveDate = lb.getLeaveLocalDate(); LeaveSummary summary = (LeaveSummary) LmServiceLocator.getLeaveSummaryService() .getLeaveSummaryAsOfDate(principalId, leaveDate.plusDays(1)); LeaveSummaryRow row = summary.getLeaveSummaryRowForAccrualCtgy(lb.getAccrualCategory()); if (row != null) { //AccrualCategory accrualCategory = HrServiceLocator.getAccrualCategoryService().getAccrualCategory(row.getAccrualCategoryId()); //AccrualCategoryRule currentRule = HrServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRuleForDate(accrualCategory, asOfDate, pha.getServiceDate()); if (calendarEntryInterval.contains(leaveDate.toDate().getTime())) { //do not allow the on-demand max balance action if the rule the action occurs under is no longer in effect, //or if the infraction did not occur within this interval. ( if it occurred during the previous interval, //the employee will have the option to take action in that interval up to & including the end date of that interval. ) row.setInfractingLeaveBlockId(lb.getAccrualCategoryRuleId()); AccrualCategoryRuleContract aRule = lb.getAccrualCategoryRule(); if (StringUtils.equals(aRule.getActionAtMaxBalance(), HrConstants.ACTION_AT_MAX_BALANCE.TRANSFER)) row.setTransferable(true); else if (StringUtils.equals(aRule.getActionAtMaxBalance(), HrConstants.ACTION_AT_MAX_BALANCE.PAYOUT)) row.setPayoutable(true); boolean exists = false; for (LeaveSummaryRow maxedRow : maxedLeaveRows) { if (StringUtils.equals(maxedRow.getAccrualCategoryId(), row.getAccrualCategoryId())) exists = true; } if (!exists) { maxedLeaveRows.add(row); } } } } } } return maxedLeaveRows; } /** * Aggregates timeblocks into the appropriate earngroup-> earncode -> assignment rows * @param tkTimeBlockAggregate * @param numEntries * @param dayArrangements * @param asOfDate * @return */ public Map<String, List<EarnGroupSection>> getEarnGroupSections(String principalId, TkTimeBlockAggregate tkTimeBlockAggregate, int numEntries, List<Boolean> dayArrangements, LocalDate asOfDate, LocalDate docEndDate) { List<EarnGroupSection> earnGroupSections = new ArrayList<EarnGroupSection>(); Map<String, List<EarnGroupSection>> weeklyEarnGroupSections = new LinkedHashMap<String, List<EarnGroupSection>>(); Map<String, List<EarnCodeSection>> earnCodeSections = new LinkedHashMap<String, List<EarnCodeSection>>(); String userTz = HrServiceLocator.getTimezoneService().getUserTimezone(principalId); DateTimeZone userTimeZone = DateTimeZone.forID(userTz); List<FlsaWeek> flsaWeeks = tkTimeBlockAggregate.getFlsaWeeks(userTimeZone, DateTimeConstants.SUNDAY, true); Map<String, EarnCodeSection> earnCodeToEarnCodeSection = new TreeMap<String, EarnCodeSection>(); Map<String, EarnGroupSection> earnGroupToEarnGroupSection = new HashMap<String, EarnGroupSection>(); int dayCount = 0; //TODO remove this and correct the aggregate .. not sure what the down stream changes are //so leaving this for initial release List<FlsaWeek> trimmedFlsaWeeks = new ArrayList<FlsaWeek>(); for (FlsaWeek flsaWeek : flsaWeeks) { if (flsaWeek.getFlsaDays().size() > 0) { trimmedFlsaWeeks.add(flsaWeek); } } //For every flsa week and day aggegate each time hour detail // buckets it by earn code section first int weekCount = 1; for (FlsaWeek flsaWeek : trimmedFlsaWeeks) { earnCodeToEarnCodeSection = new TreeMap<String, EarnCodeSection>(); int weekSize = 0; List<FlsaDay> flsaDays = flsaWeek.getFlsaDays(); for (FlsaDay flsaDay : flsaDays) { LocalDateTime ld = flsaDay.getFlsaDate(); DateTime td = flsaDay.getFlsaDate().toDateTime(userTimeZone); int ldDay = ld.getDayOfWeek(); Map<String, List<TimeBlock>> earnCodeToTimeBlocks = flsaDay.getEarnCodeToTimeBlocks(); for (List<TimeBlock> timeBlocks : earnCodeToTimeBlocks.values()) { for (TimeBlock timeBlock : timeBlocks) { for (TimeHourDetail thd : timeBlock.getTimeHourDetails()) { if (StringUtils.equals(HrConstants.LUNCH_EARN_CODE, thd.getEarnCode())) { continue; } EarnCodeSection earnCodeSection = earnCodeToEarnCodeSection.get(thd.getEarnCode()); if (earnCodeSection == null) { earnCodeSection = new EarnCodeSection(); earnCodeSection.setEarnCode(thd.getEarnCode()); EarnCodeContract earnCodeObj = HrServiceLocator.getEarnCodeService() .getEarnCode(thd.getEarnCode(), asOfDate); earnCodeSection .setDescription(earnCodeObj != null ? earnCodeObj.getDescription() : null); earnCodeSection.setIsAmountEarnCode( earnCodeObj != null ? HrConstants.EARN_CODE_AMOUNT .equalsIgnoreCase(earnCodeObj.getRecordMethod()) : false); for (int i = 0; i < (numEntries - 1); i++) { earnCodeSection.getTotals().add(BigDecimal.ZERO); } earnCodeToEarnCodeSection.put(thd.getEarnCode(), earnCodeSection); } String assignKey = timeBlock.getAssignmentKey(); AssignmentRow assignRow = earnCodeSection.getAssignKeyToAssignmentRowMap() .get(assignKey); if (assignRow == null) { assignRow = new AssignmentRow(); assignRow.setAssignmentKey(assignKey); AssignmentDescriptionKey assignmentKey = HrServiceLocator.getAssignmentService() .getAssignmentDescriptionKey(assignKey); Assignment assignment = HrServiceLocator.getAssignmentService() .getAssignment(timeBlock.getPrincipalId(), assignmentKey, asOfDate); // some assignment may not be effective at the beginning of the pay period, use the end date of the period to find it if (assignment == null) { assignment = HrServiceLocator.getAssignmentService() .getAssignment(timeBlock.getPrincipalId(), assignmentKey, docEndDate); } if (assignment != null) { assignRow.setDescr(assignment.getAssignmentDescription()); } assignRow.setEarnCodeSection(earnCodeSection); for (int i = 1; i < numEntries; i++) { AssignmentColumn assignmentColumn = new AssignmentColumn(); // assignmentColumn.setTotal(HrConstants.BIG_DECIMAL_SCALED_ZERO); // assignmentColumn.setAmount(HrConstants.BIG_DECIMAL_SCALED_ZERO); assignRow.addAssignmentColumn(i, assignmentColumn); } earnCodeSection.addAssignmentRow(assignRow); } assignRow.addToTotal(td.getDayOfWeek(), thd.getHours()); assignRow.addToAmount(td.getDayOfWeek(), thd.getAmount()); } } } dayCount++; weekSize++; } weekSize = 0; dayCount = 0; earnCodeSections.put("Week " + weekCount++, new LinkedList<EarnCodeSection>(earnCodeToEarnCodeSection.values())); } dayCount = 0; //now create all teh earn group sections and aggregate accordingly for (String key : earnCodeSections.keySet()) { earnGroupToEarnGroupSection = new HashMap<String, EarnGroupSection>(); earnGroupSections = new ArrayList<EarnGroupSection>(); List<EarnCodeSection> earnCodeToEarnCodeSections = earnCodeSections.get(key); for (EarnCodeSection earnCodeSection : earnCodeToEarnCodeSections) { String earnCode = earnCodeSection.getEarnCode(); EarnCodeGroup earnGroupObj = HrServiceLocator.getEarnCodeGroupService() .getEarnCodeGroupSummaryForEarnCode(earnCode, asOfDate); String earnGroup = null; if (earnGroupObj == null) { earnGroup = OTHER_EARN_GROUP; } else { earnGroup = earnGroupObj.getDescr(); } EarnGroupSection earnGroupSection = earnGroupToEarnGroupSection.get(earnGroup); if (earnGroupSection == null) { earnGroupSection = new EarnGroupSection(); earnGroupSection.setEarnGroup(earnGroup); earnGroupSection.setEarnGroupCode( earnGroupObj == null ? OTHER_EARN_GROUP : earnGroupObj.getEarnCodeGroup()); for (int i = 1; i < (numEntries); i++) { earnGroupSection.getTotals().put(i, BigDecimal.ZERO); earnGroupSection.getTotals().get(i).setScale(HrConstants.BIG_DECIMAL_SCALE, HrConstants.BIG_DECIMAL_SCALE_ROUNDING); } earnGroupToEarnGroupSection.put(earnGroup, earnGroupSection); } earnGroupSection.addEarnCodeSection(earnCodeSection, dayArrangements); } for (EarnGroupSection earnGroupSection : earnGroupToEarnGroupSection.values()) { earnGroupSections.add(earnGroupSection); } weeklyEarnGroupSections.put(key, earnGroupSections); } return weeklyEarnGroupSections; } /** * Generate a list of string describing this pay calendar entry for the summary * @param payCalEntry * @return */ protected List<String> getSummaryHeader(CalendarEntryBo payCalEntry) { List<String> summaryHeader = new ArrayList<String>(); int dayCount = 0; DateTime beginDateTime = payCalEntry.getBeginPeriodFullDateTime(); DateTime endDateTime = payCalEntry.getEndPeriodFullDateTime(); boolean virtualDays = false; LocalDateTime endDate = payCalEntry.getEndPeriodLocalDateTime(); if (endDate.get(DateTimeFieldType.hourOfDay()) != 0 || endDate.get(DateTimeFieldType.minuteOfHour()) != 0 || endDate.get(DateTimeFieldType.secondOfMinute()) != 0) { virtualDays = true; } DateTime currentDateTime = beginDateTime; while (currentDateTime.isBefore(endDateTime)) { LocalDateTime currDate = currentDateTime.toLocalDateTime(); summaryHeader.add(makeHeaderDiplayString(currDate, virtualDays)); dayCount++; if ((dayCount % 7) == 0) { summaryHeader.add("Week " + ((dayCount / 7))); } currentDateTime = currentDateTime.plusDays(1); } summaryHeader.add("Period Total"); return summaryHeader; } /** * Provides the number of hours worked for the pay period indicated in the * aggregate. * * @param aggregate The aggregate we are summing * * @return A list of BigDecimals containing the number of hours worked. * This list will line up with the header. */ private List<BigDecimal> getWorkedHours(String principalId, TkTimeBlockAggregate aggregate, Set<String> regularEarnCodes, TimeSummary timeSummary, DateTimeZone timezone) { List<BigDecimal> hours = new ArrayList<BigDecimal>(); Map<Integer, BigDecimal> weekHours; Map<Integer, Boolean> weekClockLogMap; Map<String, BigDecimal> weekTotalMap = new LinkedHashMap<String, BigDecimal>(); Map<String, Integer> weekDateToCalendarDayInt = new HashMap<String, Integer>(); Map<String, Map<Integer, Boolean>> clockLogMap = new LinkedHashMap<String, Map<Integer, Boolean>>(); ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId); DateTime userClockLogTime = null; if (lastClockLog != null) { String approverId = HrContext.getPrincipalId(); String timeZoneString = HrServiceLocator.getTimezoneService().getApproverTimezone(approverId); DateTimeZone approverTimeZone = StringUtils.isNotBlank(timeZoneString) ? DateTimeZone.forID(timeZoneString) : null; userClockLogTime = lastClockLog.getClockDateTime().withZone(approverTimeZone); } BigDecimal periodTotal = HrConstants.BIG_DECIMAL_SCALED_ZERO; int i = 0; int dayInt = 0; for (FlsaWeek week : aggregate.getFlsaWeeks(timezone, DateTimeConstants.SUNDAY, true)) { weekHours = new TreeMap<Integer, BigDecimal>(); weekClockLogMap = new TreeMap<Integer, Boolean>(); BigDecimal weeklyTotal = HrConstants.BIG_DECIMAL_SCALED_ZERO; for (FlsaDay day : week.getFlsaDays()) { BigDecimal totalForDay = HrConstants.BIG_DECIMAL_SCALED_ZERO; LocalDateTime ld = day.getFlsaDate(); int ldDay = ld.getDayOfWeek(); // check for clocklog exists on the day. if (userClockLogTime != null) { if (userClockLogTime.getDayOfMonth() == ld.getDayOfMonth()) { weekClockLogMap.put(ldDay, Boolean.TRUE); } } for (TimeBlock block : day.getAppliedTimeBlocks()) { EarnCodeContract ec = HrServiceLocator.getEarnCodeService().getEarnCode(block.getEarnCode(), block.getEndDateTime().toLocalDate()); if (ec != null && (ec.isOvtEarnCode() || regularEarnCodes.contains(ec.getEarnCode()) || ec.getCountsAsRegularPay().equals("Y"))) { totalForDay = totalForDay.add(block.getHours(), HrConstants.MATH_CONTEXT); weeklyTotal = weeklyTotal.add(block.getHours(), HrConstants.MATH_CONTEXT); periodTotal = periodTotal.add(block.getHours(), HrConstants.MATH_CONTEXT); } } weekHours.put(ldDay, totalForDay); weekDateToCalendarDayInt.put(("Week" + (i + 1) + "_day" + ldDay), dayInt); dayInt++; hours.add(totalForDay); } i++; weekTotalMap.put("Week " + i, weeklyTotal); timeSummary.getWeeklyWorkedHours().put("Week " + i, weekHours); clockLogMap.put("Week " + i, weekClockLogMap); hours.add(weeklyTotal); } hours.add(periodTotal); timeSummary.setGrandTotal(periodTotal); timeSummary.setWeekTotalMap(weekTotalMap); timeSummary.setWeeklyClockLogs(clockLogMap); timeSummary.setWeekDateToCalendarDayInt(weekDateToCalendarDayInt); return hours; } /** * Handles the generation of the display header for the time summary. * * @param cal The PayCalendarEntries object we are using to derive information. * @param dayArrangements Container passed in to store the position of week / period aggregate sums * * @return An in-order string of days for this period that properly accounts * for FLSA week boundaries in the pay period. */ @Override public List<String> getHeaderForSummary(CalendarEntry cal, List<Boolean> dayArrangements) { List<String> header = new ArrayList<String>(); if (cal == null) { return Collections.emptyList(); } // Maps directly to joda time day of week constants. int flsaBeginDay = this.getPayCalendarForEntry(cal).getFlsaBeginDayConstant(); boolean virtualDays = false; LocalDateTime startDate = cal.getBeginPeriodLocalDateTime(); LocalDateTime endDate = cal.getEndPeriodLocalDateTime(); // Increment end date if we are on a virtual day calendar, so that the // for loop can account for having the proper amount of days on the // summary calendar. if (endDate.get(DateTimeFieldType.hourOfDay()) != 0 || endDate.get(DateTimeFieldType.minuteOfHour()) != 0 || endDate.get(DateTimeFieldType.secondOfMinute()) != 0) { endDate = endDate.plusDays(1); virtualDays = true; } boolean afterFirstDay = false; int week = 1; for (LocalDateTime currentDate = startDate; currentDate.compareTo(endDate) < 0; currentDate = currentDate .plusDays(1)) { if (currentDate.getDayOfWeek() == flsaBeginDay && afterFirstDay) { header.add("Week " + week); dayArrangements.add(false); week++; } header.add(makeHeaderDiplayString(currentDate, virtualDays)); dayArrangements.add(true); afterFirstDay = true; } // We may have a very small final "week" on this pay period. For now // we will mark it as a week, and if someone doesn't like it, it can // be removed. if (!header.isEmpty() && !header.get(header.size() - 1).startsWith("Week")) { dayArrangements.add(false); header.add("Week " + week); } header.add("Period Total"); dayArrangements.add(false); return header; } public Map<Integer, String> getHeaderForSummary(CalendarEntry cal, TimeSummary timeSummary) { Map<Integer, String> header = new LinkedHashMap<Integer, String>(); Map<String, String> weekDates = new LinkedHashMap<String, String>(); header.put(DateTimeConstants.SUNDAY, "Sun"); header.put(DateTimeConstants.MONDAY, "Mon"); header.put(DateTimeConstants.TUESDAY, "Tue"); header.put(DateTimeConstants.WEDNESDAY, "Wed"); header.put(DateTimeConstants.THURSDAY, "Thu"); header.put(DateTimeConstants.FRIDAY, "Fri"); header.put(DateTimeConstants.SATURDAY, "Sat"); LocalDateTime startDate = cal.getBeginPeriodLocalDateTime(); LocalDateTime endDate = cal.getEndPeriodLocalDateTime(); LocalDateTime actualStartDate = cal.getBeginPeriodLocalDateTime(); LocalDateTime actualEndDate = cal.getEndPeriodLocalDateTime(); int daysToMinus = 0; if (DateTimeConstants.SUNDAY != startDate.getDayOfWeek()) { daysToMinus = startDate.getDayOfWeek(); } actualStartDate = startDate.minusDays(daysToMinus); int daysToAdd = 0; if (endDate.getDayOfWeek() != DateTimeConstants.SUNDAY) { daysToAdd = DateTimeConstants.SATURDAY - endDate.getDayOfWeek(); } else { daysToAdd = DateTimeConstants.SATURDAY; } actualEndDate = endDate.plusDays(daysToAdd); // Increment end date if we are on a virtual day calendar, so that the // for loop can account for having the proper amount of days on the // summary calendar. if (endDate.get(DateTimeFieldType.hourOfDay()) != 0 || endDate.get(DateTimeFieldType.minuteOfHour()) != 0 || endDate.get(DateTimeFieldType.secondOfMinute()) != 0) { endDate = endDate.plusDays(1); } boolean afterFirstDay = false; int week = 1; LocalDateTime weekStart = actualStartDate; LocalDateTime weekEnd = actualStartDate; for (LocalDateTime currentDate = actualStartDate; currentDate .compareTo(actualEndDate) < 0; currentDate = currentDate.plusDays(1)) { if (currentDate.getDayOfWeek() == DateTimeConstants.SUNDAY && afterFirstDay) { StringBuilder display = new StringBuilder(); display.append(weekStart.toString(TkConstants.DT_ABBREV_DATE_FORMAT)); display.append(" - "); display.append(weekEnd.minusDays(1).toString(TkConstants.DT_ABBREV_DATE_FORMAT)); weekDates.put("Week " + week, display.toString()); weekStart = currentDate; week++; } weekEnd = weekEnd.plusDays(1); afterFirstDay = true; } // We may have a very small final "week" on this pay period. For now // we will mark it as a week, and if someone doesn't like it, it can // be removed. if (!header.isEmpty() && !header.get(header.size() - 1).startsWith("Week")) { StringBuilder display = new StringBuilder(); display.append(weekStart.toString(TkConstants.DT_ABBREV_DATE_FORMAT)); display.append(" - "); display.append(actualEndDate.toString(TkConstants.DT_ABBREV_DATE_FORMAT)); weekDates.put("Week " + week, display.toString()); } timeSummary.setWeekDates(weekDates); return header; } /** * Helper function to generate display text for the summary header. * @param currentDate The date we are generating for. * @param virtualDays Whether or not virtual days apply. * @return A string appropriate for UI display. */ private String makeHeaderDiplayString(LocalDateTime currentDate, boolean virtualDays) { StringBuilder display = new StringBuilder(); display.append(currentDate.toString("E")); if (virtualDays) { LocalDateTime nextDate = currentDate.plusDays(1); display.append(" - "); display.append(nextDate.toString("E")); } // display.append("<br />"); // // display.append(currentDate.toString(TkConstants.DT_ABBREV_DATE_FORMAT)); // if (virtualDays) { // LocalDateTime nextDate = currentDate.plusDays(1); // display.append(" - "); // display.append(nextDate.toString(TkConstants.DT_ABBREV_DATE_FORMAT)); // } return display.toString(); } /** * @param calEntry Calendar entry we are using for lookup. * @return The PayCalendar that owns the provided entry. */ private Calendar getPayCalendarForEntry(CalendarEntry calEntry) { Calendar cal = null; if (calEntry != null) { cal = HrServiceLocator.getCalendarService().getCalendar(calEntry.getHrCalendarId()); } return cal; } private Map<String, BigDecimal> getHoursToFlsaWeekMap(TkTimeBlockAggregate tkTimeBlockAggregate, String principalId, Long workArea, Set<String> regularEarnCodes, DateTimeZone timezone) { Map<String, BigDecimal> hoursToFlsaWeekMap = new LinkedHashMap<String, BigDecimal>(); List<List<FlsaWeek>> flsaWeeks = tkTimeBlockAggregate.getFlsaWeeks(timezone, principalId); int weekCount = 1; for (List<FlsaWeek> flsaWeekParts : flsaWeeks) { BigDecimal weekTotal = new BigDecimal(0.00); for (FlsaWeek flsaWeekPart : flsaWeekParts) { for (FlsaDay flsaDay : flsaWeekPart.getFlsaDays()) { for (TimeBlock timeBlock : flsaDay.getAppliedTimeBlocks()) { EarnCodeContract ec = HrServiceLocator.getEarnCodeService() .getEarnCode(timeBlock.getEarnCode(), timeBlock.getEndDateTime().toLocalDate()); if (ec != null && (ec.isOvtEarnCode() || regularEarnCodes.contains(ec.getEarnCode()) || ec.getCountsAsRegularPay().equals("Y"))) { if (workArea != null) { if (timeBlock.getWorkArea().compareTo(workArea) == 0) { weekTotal = weekTotal.add(timeBlock.getHours(), HrConstants.MATH_CONTEXT); } else { weekTotal = weekTotal.add(new BigDecimal("0"), HrConstants.MATH_CONTEXT); } } else { weekTotal = weekTotal.add(timeBlock.getHours(), HrConstants.MATH_CONTEXT); } } } } } hoursToFlsaWeekMap.put("Week " + weekCount++, weekTotal); } return hoursToFlsaWeekMap; } }