List of usage examples for org.joda.time DateTime plusDays
public DateTime plusDays(int days)
From source file:org.kuali.kpme.tklm.leave.accrual.service.AccrualServiceImpl.java
License:Educational Community License
@Override public RateRangeAggregate buildRateRangeAggregate(String principalId, DateTime startDate, DateTime endDate) { RateRangeAggregate rrAggregate = new RateRangeAggregate(); List<RateRange> rateRangeList = new ArrayList<RateRange>(); // get all active jobs that are effective before the endDate List<Job> activeJobs = HrServiceLocator.getJobService().getAllActiveLeaveJobs(principalId, endDate.toLocalDate());// w w w . ja v a2 s.c o m List<Job> inactiveJobs = HrServiceLocator.getJobService().getAllInActiveLeaveJobsInRange(principalId, endDate.toLocalDate()); List<PrincipalHRAttributes> phaList = HrServiceLocator.getPrincipalHRAttributeService() .getAllActivePrincipalHrAttributesForPrincipalId(principalId, endDate.toLocalDate()); List<PrincipalHRAttributes> inactivePhaList = HrServiceLocator.getPrincipalHRAttributeService() .getAllInActivePrincipalHrAttributesForPrincipalId(principalId, endDate.toLocalDate()); if (activeJobs.isEmpty() || phaList.isEmpty()) { return rrAggregate; } Set<String> phaLpSet = new HashSet<String>(); Set<String> calNameSet = new HashSet<String>(); if (CollectionUtils.isNotEmpty(phaList)) { for (PrincipalHRAttributes pha : phaList) { phaLpSet.add(pha.getLeavePlan()); calNameSet.add(pha.getPayCalendar()); } } List<LeavePlan> activeLpList = new ArrayList<LeavePlan>(); List<LeavePlan> inactiveLpList = new ArrayList<LeavePlan>(); for (String lpString : phaLpSet) { List<LeavePlan> aList = HrServiceLocator.getLeavePlanService().getAllActiveLeavePlan(lpString, endDate.toLocalDate()); activeLpList.addAll(aList); aList = HrServiceLocator.getLeavePlanService().getAllInActiveLeavePlan(lpString, endDate.toLocalDate()); inactiveLpList.addAll(aList); } // get all pay calendar entries for this employee. used to determine interval dates Map<String, List<CalendarEntry>> calEntryMap = new HashMap<String, List<CalendarEntry>>(); for (String calName : calNameSet) { org.kuali.kpme.core.calendar.Calendar aCal = HrServiceLocator.getCalendarService() .getCalendarByGroup(calName); if (aCal != null) { List<CalendarEntry> aList = HrServiceLocator.getCalendarEntryService() .getAllCalendarEntriesForCalendarId(aCal.getHrCalendarId()); Collections.sort(aList); calEntryMap.put(calName, aList); } } rrAggregate.setCalEntryMap(calEntryMap); Set<String> lpStringSet = new HashSet<String>(); if (CollectionUtils.isNotEmpty(activeLpList)) { for (LeavePlan lp : activeLpList) { lpStringSet.add(lp.getLeavePlan()); } } List<SystemScheduledTimeOff> sstoList = new ArrayList<SystemScheduledTimeOff>(); for (String lpString : lpStringSet) { List<SystemScheduledTimeOff> aList = LmServiceLocator.getSysSchTimeOffService() .getSystemScheduledTimeOffsForLeavePlan(startDate.toLocalDate(), endDate.toLocalDate(), lpString); if (CollectionUtils.isNotEmpty(aList)) { sstoList.addAll(aList); } } List<AccrualCategory> activeAccrCatList = new ArrayList<AccrualCategory>(); List<AccrualCategory> inactiveAccrCatList = new ArrayList<AccrualCategory>(); for (String lpString : lpStringSet) { List<AccrualCategory> aList = HrServiceLocator.getAccrualCategoryService() .getActiveLeaveAccrualCategoriesForLeavePlan(lpString, endDate.toLocalDate()); if (CollectionUtils.isNotEmpty(aList)) { activeAccrCatList.addAll(aList); } aList = HrServiceLocator.getAccrualCategoryService() .getInActiveLeaveAccrualCategoriesForLeavePlan(lpString, endDate.toLocalDate()); if (CollectionUtils.isNotEmpty(aList)) { inactiveAccrCatList.addAll(aList); } } List<AccrualCategoryRule> activeRuleList = new ArrayList<AccrualCategoryRule>(); List<AccrualCategoryRule> inactiveRuleList = new ArrayList<AccrualCategoryRule>(); for (AccrualCategory ac : activeAccrCatList) { List<AccrualCategoryRule> aRuleList = HrServiceLocator.getAccrualCategoryRuleService() .getActiveRulesForAccrualCategoryId(ac.getLmAccrualCategoryId()); activeRuleList.addAll(aRuleList); aRuleList = HrServiceLocator.getAccrualCategoryRuleService() .getInActiveRulesForAccrualCategoryId(ac.getLmAccrualCategoryId()); inactiveRuleList.addAll(aRuleList); } List<LeaveCalendarDocumentHeader> lcDocList = LmServiceLocator.getLeaveCalendarDocumentHeaderService() .getAllDocumentHeadersInRangeForPricipalId(principalId, startDate, endDate); BigDecimal previousFte = null; List<Job> jobs = new ArrayList<Job>(); DateTime currentDate = startDate; while (!currentDate.isAfter(endDate)) { RateRange rateRange = new RateRange(); jobs = this.getJobsForDate(activeJobs, inactiveJobs, currentDate.toLocalDate()); if (jobs.isEmpty()) { // no jobs found for this day currentDate = currentDate.plusDays(1); continue; } rateRange.setJobs(jobs); // detect if there's a status change BigDecimal fteSum = HrServiceLocator.getJobService().getFteSumForJobs(jobs); rateRange.setAccrualRatePercentageModifier(fteSum); BigDecimal standardHours = HrServiceLocator.getJobService().getStandardHoursSumForJobs(jobs); rateRange.setStandardHours(standardHours); if (previousFte != null && !previousFte.equals(fteSum)) { rateRange.setStatusChanged(true); rrAggregate.setRateRangeChanged(true); } previousFte = fteSum; // figure out the PrincipalHRAttributes for this day PrincipalHRAttributes phra = this.getPrincipalHrAttributesForDate(phaList, currentDate.toLocalDate()); rateRange.setPrincipalHRAttributes(phra); if (rateRange.getPrincipalHRAttributes() != null) { // figure out if there's an end principalHrAttributes for the initial principalHRAttributes PrincipalHRAttributes endPhra = this.getInactivePrincipalHrAttributesForDate(inactivePhaList, rateRange.getPrincipalHRAttributes().getEffectiveLocalDate(), currentDate.toLocalDate()); rateRange.setEndPrincipalHRAttributes(endPhra); } // get leave plan for this day if (rateRange.getPrincipalHRAttributes() != null) { rateRange.setLeavePlan(this.getLeavePlanForDate(activeLpList, inactiveLpList, rateRange.getPrincipalHRAttributes().getLeavePlan(), currentDate.toLocalDate())); } if (rateRange.getLeavePlan() != null) { // get accrual category list for this day List<AccrualCategory> acsForDay = this.getAccrualCategoriesForDate(activeAccrCatList, inactiveAccrCatList, rateRange.getLeavePlan().getLeavePlan(), currentDate.toLocalDate()); rateRange.setAcList(acsForDay); // get System scheduled time off for this day for (SystemScheduledTimeOff ssto : sstoList) { if (ssto.getAccruedLocalDate().equals(currentDate.toLocalDate()) && ssto.getLeavePlan().equals(rateRange.getLeavePlan().getLeavePlan())) { // if there exists a ssto accrualed leave block with this ssto id, it means the ssto hours has been banked or transferred by the employee // this logic depends on the deactivateOldAccruals() runs before buildRateRangeAggregate() // because deactivateOldAccruals() removes accrued ssto leave blocks unless they are banked/transferred List<LeaveBlock> sstoLbList = LmServiceLocator.getLeaveBlockService().getSSTOLeaveBlocks( principalId, ssto.getLmSystemScheduledTimeOffId(), ssto.getAccruedLocalDate()); if (CollectionUtils.isEmpty(sstoLbList)) { rateRange.setSysScheTimeOff(ssto); } } } } // set accrual category rules for the day if (CollectionUtils.isNotEmpty(rateRange.getAcList())) { List<AccrualCategoryRule> rulesForDay = new ArrayList<AccrualCategoryRule>(); for (AccrualCategory ac : rateRange.getAcList()) { rulesForDay.addAll(this.getAccrualCategoryRulesForDate(activeRuleList, ac.getLmAccrualCategoryId(), currentDate.toLocalDate(), rateRange.getPrincipalHRAttributes().getServiceLocalDate())); } rateRange.setAcRuleList(rulesForDay); } Interval range = new Interval(currentDate, currentDate.plusDays(1)); rateRange.setRange(range); // assign leave document id to range if there is an existing leave doc for currentDate. // The doc Id will be assigned to leave blocks created at this rate range rateRange.setLeaveCalendarDocumentId(this.getLeaveDocumentForDate(lcDocList, currentDate)); rateRangeList.add(rateRange); currentDate = currentDate.plusDays(1); } rrAggregate.setRateRanges(rateRangeList); rrAggregate.setCurrentRate(null); return rrAggregate; }
From source file:org.kuali.kpme.tklm.leave.batch.CarryOverSchedulerJob.java
License:Educational Community License
@Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { LocalDate asOfDate = LocalDate.now(); List<LeavePlan> leavePlans = HrServiceLocator.getLeavePlanService() .getLeavePlansNeedsCarryOverScheduled(getLeavePlanPollingWindow(), asOfDate); try {/*from w w w . ja va 2 s. c o m*/ if (leavePlans != null && !leavePlans.isEmpty()) { DateTime current = asOfDate.toDateTimeAtStartOfDay(); DateTime windowStart = current.minusDays(getLeavePlanPollingWindow()); DateTime windowEnd = current.plusDays(getLeavePlanPollingWindow()); // schedule batch job for all LeavePlans who fall in leave polling window. for (LeavePlan leavePlan : leavePlans) { if (leavePlan.getBatchPriorYearCarryOverStartDate() != null && leavePlan.getBatchPriorYearCarryOverStartTime() != null) { DateTimeFormatter formatter = DateTimeFormat.forPattern("MM/dd"); DateTime batchPriorYearCarryOverStartDateTime = formatter .parseDateTime(leavePlan.getBatchPriorYearCarryOverStartDate()) .plus(leavePlan.getBatchPriorYearCarryOverStartTime().getTime()); if (batchPriorYearCarryOverStartDateTime.compareTo(windowStart) >= 0 && batchPriorYearCarryOverStartDateTime.compareTo(windowEnd) <= 0) { getBatchJobService().scheduleLeaveCarryOverJobs(leavePlan); } } } } } catch (SchedulerException se) { LOG.warn("Exception thrown during job scheduling of Carry over for Leave", se); // throw new JobExecutionException("Exception thrown during job scheduling of Carry over for Leave", se); } }
From source file:org.kuali.kpme.tklm.leave.calendar.LeaveCalendar.java
License:Educational Community License
public LeaveCalendar(String principalId, CalendarEntry calendarEntry, List<String> assignmentKeys) { super(calendarEntry); DateTime currentDisplayDateTime = getBeginDateTime(); DateTime endDisplayDateTime = getEndDateTime(); // Fill in the days if the first day or end day is in the middle of the week if (currentDisplayDateTime.getDayOfWeek() != DateTimeConstants.SUNDAY) { currentDisplayDateTime = currentDisplayDateTime.minusDays(currentDisplayDateTime.getDayOfWeek()); }//from ww w . ja v a 2 s . c o m if (endDisplayDateTime.getDayOfWeek() != DateTimeConstants.SATURDAY) { endDisplayDateTime = endDisplayDateTime .plusDays(DateTimeConstants.SATURDAY - endDisplayDateTime.getDayOfWeek()); } LeaveCalendarWeek leaveCalendarWeek = new LeaveCalendarWeek(); Integer dayNumber = 0; List<LeaveBlock> blocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocks(principalId, calendarEntry.getBeginPeriodFullDateTime().toLocalDate(), calendarEntry.getEndPeriodFullDateTime().toLocalDate()); Map<String, List<LeaveBlock>> leaveBlockMap = new HashMap<String, List<LeaveBlock>>(); for (LeaveBlock lb : blocks) { String key = lb.getLeaveLocalDate().toString(); if (leaveBlockMap.containsKey(key)) { leaveBlockMap.get(key).add(lb); } else { leaveBlockMap.put(key, createNewLeaveBlockList(lb)); } } //KPME-2560 If leave calendar document is final status, then User wont be able to add leave blocks to the calendar. Boolean dayEditableFlag = true; LeaveCalendarDocumentHeader header = LmServiceLocator.getLeaveCalendarDocumentHeaderService() .getDocumentHeader(principalId, calendarEntry.getBeginPeriodFullDateTime(), calendarEntry.getEndPeriodFullDateTime()); if (header != null && header.getDocumentStatus().equals(HrConstants.ROUTE_STATUS.FINAL)) dayEditableFlag = false; while (currentDisplayDateTime.isBefore(endDisplayDateTime) || currentDisplayDateTime.isEqual(endDisplayDateTime)) { LeaveCalendarDay leaveCalendarDay = new LeaveCalendarDay(); // If the day is not within the current pay period, mark them as read only (gray) if (currentDisplayDateTime.isBefore(getBeginDateTime()) || currentDisplayDateTime.isEqual(getEndDateTime()) || currentDisplayDateTime.isAfter(getEndDateTime())) { leaveCalendarDay.setGray(true); } else { // This is for the div id of the days on the calendar. // It creates a day id like day_11/01/2011 which will make day parsing easier in the javascript. // leaveCalendarDay.setDayNumberDelta(currDateTime.toString(HrConstants.DT_BASIC_DATE_FORMAT)); // leaveCalendarDay.setDayNumberDelta(currDateTime.getDayOfMonth()); leaveCalendarDay.setDayNumberDelta(dayNumber); LocalDate leaveDate = currentDisplayDateTime.toLocalDate(); List<LeaveBlock> lbs = leaveBlockMap.get(currentDisplayDateTime.toLocalDate().toString()); if (lbs == null) { lbs = Collections.emptyList(); } // use given assignmentKeys to control leave blocks displayed on the calendar if (CollectionUtils.isNotEmpty(lbs) && CollectionUtils.isNotEmpty(assignmentKeys)) { List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService() .filterLeaveBlocksForLeaveCalendar(lbs, assignmentKeys); leaveCalendarDay.setLeaveBlocks(leaveBlocks); } else { leaveCalendarDay.setLeaveBlocks(lbs); } if (HrServiceLocator.getHRPermissionService().canViewLeaveTabsWithNEStatus()) { TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService() .getDocumentHeaderForDate(principalId, leaveDate.toDateTimeAtStartOfDay()); if (tdh != null) { if (DateUtils.isSameDay(leaveDate.toDate(), tdh.getEndDate()) || leaveDate.isAfter(LocalDate.fromDateFields(tdh.getEndDate()))) { leaveCalendarDay.setDayEditable(true); } } else { leaveCalendarDay.setDayEditable(true); } } else { leaveCalendarDay.setDayEditable(true); } //KPME-2560 If leave calendar document is final status, then User wont be able to add leave blocks to the calendar. if (!dayEditableFlag) leaveCalendarDay.setDayEditable(false); dayNumber++; } leaveCalendarDay.setDayNumberString(currentDisplayDateTime.dayOfMonth().getAsShortText()); leaveCalendarDay.setDateString(currentDisplayDateTime.toString(HrConstants.DT_BASIC_DATE_FORMAT)); leaveCalendarWeek.getDays().add(leaveCalendarDay); if (leaveCalendarWeek.getDays().size() == DateTimeConstants.DAYS_PER_WEEK) { getWeeks().add(leaveCalendarWeek); leaveCalendarWeek = new LeaveCalendarWeek(); } currentDisplayDateTime = currentDisplayDateTime.plusDays(1); } if (!leaveCalendarWeek.getDays().isEmpty()) { getWeeks().add(leaveCalendarWeek); } boolean isPlanningCal = LmServiceLocator.getLeaveCalendarService().isLeavePlanningCalendar(principalId, calendarEntry.getBeginPeriodFullDateTime().toLocalDate(), calendarEntry.getEndPeriodFullDateTime().toLocalDate()); Map<String, String> earnCodes = HrServiceLocator.getEarnCodeService().getEarnCodesForDisplay(principalId, isPlanningCal); setEarnCodeList(earnCodes); }
From source file:org.kuali.kpme.tklm.leave.calendar.LeaveRequestCalendar.java
License:Educational Community License
public LeaveRequestCalendar(DateTime beginDateTime, DateTime endDateTime, Map<String, List<LeaveRequestDocument>> leaveReqDocsMap, Map<String, List<LeaveBlock>> leaveBlocksMap, Map<String, List<LeaveBlockHistory>> disapprovedLBMap, String calendarType) { this.calendarType = calendarType; setBeginDateTime(beginDateTime);//from w w w .j a v a 2 s .c o m setEndDateTime(endDateTime); DateTime currentDisplayDateTime = new DateTime(beginDateTime.getMillis()); DateTime endDisplayDateTime = new DateTime(endDateTime.getMillis()); // Fill in the days if the first day or end day is in the middle of the week if (currentDisplayDateTime.getDayOfWeek() != DateTimeConstants.SUNDAY) { currentDisplayDateTime = currentDisplayDateTime.minusDays(currentDisplayDateTime.getDayOfWeek()); } if (endDisplayDateTime.getDayOfWeek() != DateTimeConstants.SATURDAY) { endDisplayDateTime = endDisplayDateTime .plusDays(DateTimeConstants.SATURDAY - endDisplayDateTime.getDayOfWeek()); } LeaveRequestCalendarWeek leaveReqCalendarWeek = new LeaveRequestCalendarWeek(); Integer dayNumber = 0; while (currentDisplayDateTime.isBefore(endDisplayDateTime) || currentDisplayDateTime.isEqual(endDisplayDateTime)) { LeaveRequestCalendarDay leaveReqCalendarDay = new LeaveRequestCalendarDay(); // If the day is not within the current pay period, mark them as read only (gray) if (StringUtils.equalsIgnoreCase("M", calendarType) && (currentDisplayDateTime.isBefore(getBeginDateTime()) || currentDisplayDateTime.isEqual(getEndDateTime()) || currentDisplayDateTime.isAfter(getEndDateTime()))) { leaveReqCalendarDay.setGray(true); } else { // This is for the div id of the days on the calendar. // It creates a day id like day_11/01/2011 which will make day parsing easier in the javascript. leaveReqCalendarDay.setDayNumberDelta(dayNumber); List<LeaveRequestDocument> reqDocs = leaveReqDocsMap .get(currentDisplayDateTime.toLocalDate().toString()); List<LeaveBlock> leaveBlocks = leaveBlocksMap.get(currentDisplayDateTime.toLocalDate().toString()); List<LeaveBlockHistory> disapprovedBlocks = disapprovedLBMap .get(currentDisplayDateTime.toLocalDate().toString()); List<LeaveRequestApprovalRow> rowList = new ArrayList<LeaveRequestApprovalRow>(); if (reqDocs == null) { reqDocs = Collections.emptyList(); } if (leaveBlocks == null) { leaveBlocks = Collections.emptyList(); } List<String> leaveBlockIds = new ArrayList<String>(); if (!reqDocs.isEmpty()) { for (LeaveRequestDocument lrd : reqDocs) { LeaveBlock lb = lrd.getLeaveBlock(); leaveBlockIds.add(lb.getLmLeaveBlockId()); String principalId = lb.getPrincipalId(); LeaveRequestApprovalRow aRow = new LeaveRequestApprovalRow(); // Set Employee Name EntityNamePrincipalName entityNamePrincipalName = KimApiServiceLocator.getIdentityService() .getDefaultNamesForPrincipalId(principalId); if (entityNamePrincipalName != null) { aRow.setPrincipalId(principalId); aRow.setEmployeeName( entityNamePrincipalName.getDefaultName() == null ? StringUtils.EMPTY : entityNamePrincipalName.getDefaultName().getCompositeName()); } aRow.setLeaveRequestDocId(lrd.getDocumentNumber()); aRow.setLeaveCode(lb.getEarnCode()); aRow.setRequestedDate(TKUtils.formatDate(lb.getLeaveLocalDate())); aRow.setRequestedHours(lb.getLeaveAmount().toString()); aRow.setDescription( lrd.getDescription() == null ? lb.getDescription() : lrd.getDescription()); aRow.setAssignmentTitle(lb.getAssignmentTitle()); aRow.setRequestStatus(lb.getRequestStatusString().toLowerCase()); rowList.add(aRow); } } if (!leaveBlocks.isEmpty()) { for (LeaveBlock lb : leaveBlocks) { if (!leaveBlockIds.contains(lb.getLmLeaveBlockId())) { String principalId = lb.getPrincipalId(); LeaveRequestApprovalRow aRow = new LeaveRequestApprovalRow(); // Set Employee Name EntityNamePrincipalName entityNamePrincipalName = KimApiServiceLocator .getIdentityService().getDefaultNamesForPrincipalId(principalId); if (entityNamePrincipalName != null) { aRow.setPrincipalId(principalId); aRow.setEmployeeName( entityNamePrincipalName.getDefaultName() == null ? StringUtils.EMPTY : entityNamePrincipalName.getDefaultName().getCompositeName()); } aRow.setLeaveCode(lb.getEarnCode()); aRow.setRequestedDate(TKUtils.formatDate(lb.getLeaveLocalDate())); aRow.setRequestedHours(lb.getLeaveAmount().toString()); aRow.setRequestStatus(lb.getRequestStatusString().toLowerCase()); aRow.setDescription(lb.getDescription()); aRow.setAssignmentTitle(lb.getAssignmentTitle()); rowList.add(aRow); } } } // Adding disapproved blocks. if (disapprovedBlocks != null && !disapprovedBlocks.isEmpty()) { for (LeaveBlockHistory lb : disapprovedBlocks) { String principalId = lb.getPrincipalId(); LeaveRequestApprovalRow aRow = new LeaveRequestApprovalRow(); // Set Employee Name EntityNamePrincipalName entityNamePrincipalName = KimApiServiceLocator.getIdentityService() .getDefaultNamesForPrincipalId(principalId); if (entityNamePrincipalName != null) { aRow.setPrincipalId(principalId); aRow.setEmployeeName( entityNamePrincipalName.getDefaultName() == null ? StringUtils.EMPTY : entityNamePrincipalName.getDefaultName().getCompositeName()); } aRow.setLeaveCode(lb.getEarnCode()); aRow.setRequestedDate(TKUtils.formatDate(lb.getLeaveLocalDate())); aRow.setRequestedHours(lb.getLeaveAmount().toString()); aRow.setRequestStatus(lb.getRequestStatusString().toLowerCase()); aRow.setDescription(lb.getDescription()); aRow.setAssignmentTitle(lb.getAssignmentTitle()); rowList.add(aRow); } } leaveReqCalendarDay.setLeaveReqRows(rowList); if (!rowList.isEmpty() && rowList.size() > 0) { requestList.addAll(rowList); } dayNumber++; } leaveReqCalendarDay.setDayNumberString(currentDisplayDateTime.dayOfMonth().getAsShortText()); leaveReqCalendarDay .setDateString(currentDisplayDateTime.toString(HrConstants.DateTimeFormats.BASIC_DATE_FORMAT)); leaveReqCalendarWeek.getDays().add(leaveReqCalendarDay); if (leaveReqCalendarWeek.getDays().size() == DateTimeConstants.DAYS_PER_WEEK) { getWeeks().add(leaveReqCalendarWeek); leaveReqCalendarWeek = new LeaveRequestCalendarWeek(); } currentDisplayDateTime = currentDisplayDateTime.plusDays(1); } if (!leaveReqCalendarWeek.getDays().isEmpty()) { getWeeks().add(leaveReqCalendarWeek); } }
From source file:org.kuali.kpme.tklm.leave.calendar.validation.LeaveCalendarValidationUtil.java
License:Educational Community License
public static List<String> validateSpanningWeeks(LeaveCalendarWSForm lcf) { List<String> errors = new ArrayList<String>(); boolean spanningWeeks = lcf.getSpanningWeeks().equalsIgnoreCase("y"); if (!spanningWeeks) { EarnCode ec = HrServiceLocator.getEarnCodeService().getEarnCode(lcf.getSelectedEarnCode(), TKUtils.formatDateString(lcf.getStartDate())); DateTime startDate = null; DateTime endDate = null;//w w w. ja va 2 s.c om if (ec != null && !ec.getRecordMethod().equals(HrConstants.RECORD_METHOD.TIME)) { startDate = TKUtils.formatDateString(lcf.getStartDate()).toDateTimeAtStartOfDay(); endDate = TKUtils.formatDateString(lcf.getEndDate()).toDateTimeAtStartOfDay(); } else { startDate = TKUtils.formatDateTimeString(lcf.getStartDate()); endDate = TKUtils.formatDateTimeString(lcf.getEndDate()); } boolean isOnlyWeekendSpan = true; while ((startDate.isBefore(endDate) || startDate.isEqual(endDate)) && isOnlyWeekendSpan) { if (startDate.getDayOfWeek() != DateTimeConstants.SATURDAY && startDate.getDayOfWeek() != DateTimeConstants.SUNDAY) { isOnlyWeekendSpan = false; } startDate = startDate.plusDays(1); } if (isOnlyWeekendSpan) { errors.add("Weekend day is selected, but include weekends checkbox is not checked"); //errorMessages } } return errors; }
From source file:org.kuali.kpme.tklm.time.detail.validation.TimeDetailValidationUtil.java
License:Educational Community License
public static List<String> validateOverlap(Long startTime, Long endTime, boolean acrossDays, String startDateS, String endTimeS, DateTime startTemp, DateTime endTemp, TimesheetDocument timesheetDocument, String timeblockId, boolean isRegularEarnCode) { List<String> errors = new ArrayList<String>(); Interval addedTimeblockInterval = new Interval(startTime, endTime); List<Interval> dayInt = new ArrayList<Interval>(); //if the user is clocked in, check if this time block overlaps with the clock action ClockLog lastClockLog = TkServiceLocator.getClockLogService() .getLastClockLog(HrContext.getTargetPrincipalId()); if (lastClockLog != null && (lastClockLog.getClockAction().equals(TkConstants.CLOCK_IN) || lastClockLog.getClockAction().equals(TkConstants.LUNCH_IN))) { DateTime lastClockDateTime = lastClockLog.getClockDateTime(); String lastClockZone = lastClockLog.getClockTimestampTimezone(); if (StringUtils.isEmpty(lastClockZone)) { lastClockZone = TKUtils.getSystemTimeZone(); }//from ww w. j a va2 s.com DateTimeZone zone = DateTimeZone.forID(lastClockZone); DateTime clockWithZone = lastClockDateTime.withZone(zone); DateTime currentTime = new DateTime(System.currentTimeMillis(), zone); Interval currentClockInInterval = new Interval(clockWithZone.getMillis(), currentTime.getMillis()); if (isRegularEarnCode && addedTimeblockInterval.overlaps(currentClockInInterval)) { errors.add("The time block you are trying to add overlaps with the current clock action."); return errors; } } if (acrossDays) { DateTime start = new DateTime(startTime); DateTime end = TKUtils.convertDateStringToDateTime(startDateS, endTimeS); if (endTemp.getDayOfYear() - startTemp.getDayOfYear() < 1) { end = new DateTime(endTime); } DateTime groupEnd = new DateTime(endTime); Long startLong = start.getMillis(); Long endLong = end.getMillis(); //create interval span if start is before the end and the end is after the start except //for when the end is midnight ..that converts to midnight of next day DateMidnight midNight = new DateMidnight(endLong); while (start.isBefore(groupEnd.getMillis()) && ((endLong >= startLong) || end.isEqual(midNight))) { Interval tempInt = null; if (end.isEqual(midNight)) { tempInt = addedTimeblockInterval; } else { tempInt = new Interval(startLong, endLong); } dayInt.add(tempInt); start = start.plusDays(1); end = end.plusDays(1); startLong = start.getMillis(); endLong = end.getMillis(); } } else { dayInt.add(addedTimeblockInterval); } for (TimeBlock timeBlock : timesheetDocument.getTimeBlocks()) { if (errors.size() == 0 && StringUtils.equals(timeBlock.getEarnCodeType(), HrConstants.EARN_CODE_TIME)) { Interval timeBlockInterval = new Interval(timeBlock.getBeginTimestamp().getTime(), timeBlock.getEndTimestamp().getTime()); for (Interval intv : dayInt) { if (isRegularEarnCode && timeBlockInterval.overlaps(intv) && (timeblockId == null || timeblockId.compareTo(timeBlock.getTkTimeBlockId()) != 0)) { errors.add("The time block you are trying to add overlaps with an existing time block."); } } } } return errors; }
From source file:org.kuali.kpme.tklm.time.detail.validation.TimeDetailValidationUtil.java
License:Educational Community License
public static List<String> validateSpanningWeeks(boolean spanningWeeks, DateTime startTemp, DateTime endTemp) { List<String> errors = new ArrayList<String>(); if (!spanningWeeks) { boolean isOnlyWeekendSpan = true; while ((startTemp.isBefore(endTemp) || startTemp.isEqual(endTemp)) && isOnlyWeekendSpan) { if (startTemp.getDayOfWeek() != DateTimeConstants.SATURDAY && startTemp.getDayOfWeek() != DateTimeConstants.SUNDAY) { isOnlyWeekendSpan = false; }//from ww w.jav a 2 s. c om startTemp = startTemp.plusDays(1); } if (isOnlyWeekendSpan) { errors.add("Weekend day is selected, but include weekends checkbox is not checked"); } } return errors; }
From source file:org.kuali.kpme.tklm.time.missedpunch.validation.MissedPunchDocumentRule.java
License:Educational Community License
/** * Validates whether the MissedPunch has a valid time relative to the last Clock Log. * * @param missedPunch The Missed Punch to check * * @return true if the MissedPunch has a valid time relative to the last Clock Log, false otherwise *///from w w w. j av a2s . co m protected boolean validateClockTime(MissedPunch missedPunch) { boolean valid = true; if (missedPunch.getActionFullDateTime() != null) { DateTime userActionDateTime = missedPunch.getActionFullDateTime(); DateTimeZone userTimeZone = HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback(); DateTime actionDateTime = new DateTime(userActionDateTime, userTimeZone) .withZone(TKUtils.getSystemDateTimeZone()); if (actionDateTime.toLocalDate().isAfter(LocalDate.now())) { GlobalVariables.getMessageMap().putError("document.actionDate", "clock.mp.future.date"); valid = false; } if (actionDateTime.toLocalDate().isEqual(LocalDate.now()) && actionDateTime.isAfterNow()) { GlobalVariables.getMessageMap().putError("document.actionTime", "clock.mp.future.time"); valid = false; } ClockLog lastClockLog = TkServiceLocator.getClockLogService() .getLastClockLog(missedPunch.getPrincipalId()); if (lastClockLog != null) { DateTime clockLogDateTime = lastClockLog.getClockDateTime(); DateTime boundaryMax = clockLogDateTime.plusDays(1); if ((!StringUtils.equals(lastClockLog.getClockAction(), TkConstants.CLOCK_OUT) && actionDateTime.isAfter(boundaryMax)) || actionDateTime.isBefore(clockLogDateTime)) { GlobalVariables.getMessageMap().putError("document.actionTime", "clock.mp.invalid.datetime"); valid = false; } } } return valid; }
From source file:org.kuali.kpme.tklm.time.rules.shiftdifferential.service.ShiftDifferentialRuleServiceImpl.java
License:Educational Community License
@Override public void processShiftDifferentialRules(TimesheetDocument timesheetDocument, TkTimeBlockAggregate aggregate) { DateTimeZone zone = HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback(); List<List<TimeBlock>> blockDays = aggregate.getDayTimeBlockList(); DateTime periodStartDateTime = timesheetDocument.getCalendarEntry().getBeginPeriodLocalDateTime() .toDateTime(zone);// ww w . j av a 2 s. c o m Map<Long, Set<ShiftDifferentialRule>> jobNumberToShifts = getJobNumberToShiftRuleMap(timesheetDocument); // If there are no shift differential rules, we have an early exit. if (jobNumberToShifts.isEmpty()) { return; } // Get the last day of the previous pay period. We need this to determine // if there are hours from the previous pay period that will effect the // shift rule on the first day of the currently-being-processed pay period. // // Will be set to null if not applicable. boolean previousPayPeriodPrevDay = true; Map<Long, List<TimeBlock>> jobNumberToTimeBlocksPreviousDay = getPreviousPayPeriodLastDayJobToTimeBlockMap( timesheetDocument, jobNumberToShifts); // We are going to look at the time blocks grouped by Days. // // This is a very large outer loop. for (int pos = 0; pos < blockDays.size(); pos++) { List<TimeBlock> blocks = blockDays.get(pos); // Timeblocks for this day. if (blocks.isEmpty()) continue; // No Time blocks, no worries. DateTime currentDay = periodStartDateTime.plusDays(pos); Interval virtualDay = new Interval(currentDay, currentDay.plusHours(24)); // Builds our JobNumber to TimeBlock for Current Day List. // // Shift Differential Rules are also grouped by Job number, this // provides a quick way to do the lookup / reference. // We don't need every time block, only the ones that will be // applicable to the shift rules. Map<Long, List<TimeBlock>> jobNumberToTimeBlocks = new HashMap<Long, List<TimeBlock>>(); for (TimeBlock block : blocks) { Long jobNumber = block.getJobNumber(); if (jobNumberToShifts.containsKey(jobNumber)) { List<TimeBlock> jblist = jobNumberToTimeBlocks.get(jobNumber); if (jblist == null) { jblist = new ArrayList<TimeBlock>(); jobNumberToTimeBlocks.put(jobNumber, jblist); } jblist.add(block); } } // Large Outer Loop to look at applying the Shift Rules based on // the current JobNumber. // // This loop will handle previous day boundary time as well as the // current day. // // There is room for refactoring here! for (Map.Entry<Long, Set<ShiftDifferentialRule>> entry : jobNumberToShifts.entrySet()) { Set<ShiftDifferentialRule> shiftDifferentialRules = entry.getValue(); // Obtain and sort our previous and current time blocks. List<TimeBlock> ruleTimeBlocksPrev = null; List<TimeBlock> ruleTimeBlocksCurr = jobNumberToTimeBlocks.get(entry.getKey()); if (ruleTimeBlocksCurr != null && ruleTimeBlocksCurr.size() > 0) { if (jobNumberToTimeBlocksPreviousDay != null) ruleTimeBlocksPrev = jobNumberToTimeBlocksPreviousDay.get(entry.getKey()); if (ruleTimeBlocksPrev != null && ruleTimeBlocksPrev.size() > 0) this.sortTimeBlocksInverse(ruleTimeBlocksPrev); this.sortTimeBlocksNatural(ruleTimeBlocksCurr); } else { // Skip to next job, there is nothing for this job // on this day, and because of this we don't care // about the previous day either. continue; } for (ShiftDifferentialRule rule : shiftDifferentialRules) { Set<String> fromEarnGroup = HrServiceLocator.getEarnCodeGroupService() .getEarnCodeListForEarnCodeGroup(rule.getFromEarnGroup(), timesheetDocument .getCalendarEntry().getBeginPeriodFullDateTime().toLocalDate()); LocalTime ruleStart = new LocalTime(rule.getBeginTime(), zone); LocalTime ruleEnd = new LocalTime(rule.getEndTime(), zone); DateTime shiftEnd = ruleEnd.toDateTime(currentDay); DateTime shiftStart = ruleStart.toDateTime(currentDay); if (shiftEnd.isBefore(shiftStart) || shiftEnd.isEqual(shiftStart)) { shiftEnd = shiftEnd.plusDays(1); } Interval shiftInterval = new Interval(shiftStart, shiftEnd); // Set up buckets to handle previous days time accumulations BigDecimal hoursBeforeVirtualDay = BigDecimal.ZERO; // Check current day first block to see if start time gap from virtual day start is greater than max gap // if so, we can skip the previous day checks. TimeBlock firstBlockOfCurrentDay = null; for (TimeBlock b : ruleTimeBlocksCurr) { if (timeBlockHasEarnCode(fromEarnGroup, b)) { firstBlockOfCurrentDay = b; break; } } // Previous Day :: We have prior block container of nonzero size, and the previous day is active. Interval previousDayShiftInterval = new Interval(shiftStart.minusDays(1), shiftEnd.minusDays(1)); // Blank initialization pointer for picking which interval to pass to applyPremium() Interval evalInterval = null; if (ruleTimeBlocksPrev != null && ruleTimeBlocksPrev.size() > 0 && dayIsRuleActive(currentDay.minusDays(1), rule)) { // Simple heuristic to see if we even need to worry about // the Shift rule for this set of data. if (shiftEnd.isAfter(virtualDay.getEnd())) { // Compare first block of previous day with first block of current day for max gaptitude. TimeBlock firstBlockOfPreviousDay = null; for (TimeBlock b : ruleTimeBlocksPrev) { if (timeBlockHasEarnCode(fromEarnGroup, b)) { firstBlockOfPreviousDay = b; break; } } // Only if we actually have at least one block. // Adding Assumption: We must have both a valid current and previous block. Max Gap can not be more than a virtual day. // If this assumption does not hold, additional logic will be needed to iteratively go back in time to figure out which // blocks are valid. if ((firstBlockOfPreviousDay != null) && (firstBlockOfCurrentDay != null)) { Interval previousBlockInterval = new Interval( firstBlockOfPreviousDay.getEndDateTime().withZone(zone), firstBlockOfCurrentDay.getBeginDateTime().withZone(zone)); Duration blockGapDuration = previousBlockInterval.toDuration(); BigDecimal bgdHours = TKUtils.convertMillisToHours(blockGapDuration.getMillis()); // if maxGap is 0, ignore gaps and assign shift to time blocks within the hours if (rule.getMaxGap().compareTo(BigDecimal.ZERO) == 0 || bgdHours.compareTo(rule.getMaxGap()) <= 0) { // If we are here, we know we have at least one valid time block to pull some hours forward from. // These are inversely sorted. for (int i = 0; i < ruleTimeBlocksPrev.size(); i++) { TimeBlock b = ruleTimeBlocksPrev.get(i); if (timeBlockHasEarnCode(fromEarnGroup, b)) { Interval blockInterval = new Interval( b.getBeginDateTime().withZone(zone), b.getEndDateTime().withZone(zone)); // Calculate Block Gap, the duration between clock outs and clock ins of adjacent time blocks. if (previousBlockInterval != null) { blockGapDuration = new Duration(b.getEndDateTime().withZone(zone), previousBlockInterval.getStart()); bgdHours = TKUtils .convertMillisToHours(blockGapDuration.getMillis()); } // Check Gap, if good, sum hours, if maxGap is 0, ignore gaps if (rule.getMaxGap().compareTo(BigDecimal.ZERO) == 0 || bgdHours.compareTo(rule.getMaxGap()) <= 0) { // Calculate Overlap and add it to hours before virtual day bucket. if (blockInterval.overlaps(previousDayShiftInterval)) { BigDecimal hrs = TKUtils.convertMillisToHours(blockInterval .overlap(previousDayShiftInterval).toDurationMillis()); hoursBeforeVirtualDay = hoursBeforeVirtualDay.add(hrs); } } else { // Time blocks are reverse sorted, we can jump out as soon as the max gap is exceeded. break; } previousBlockInterval = blockInterval; } } } else { // DO NOTHING! } } } } BigDecimal hoursToApply = BigDecimal.ZERO; BigDecimal hoursToApplyPrevious = BigDecimal.ZERO; // If the hours before virtual day are less than or equal to // min hours, we have already applied the time, so we don't // set hoursToApplyPrevious if (hoursBeforeVirtualDay.compareTo(rule.getMinHours()) <= 0) { // we need to apply these hours. hoursToApplyPrevious = hoursBeforeVirtualDay; } // Current Day TimeBlock previous = null; // Previous Time Block List<TimeBlock> accumulatedBlocks = new ArrayList<TimeBlock>(); // TimeBlocks we MAY or MAY NOT apply Shift Premium to. List<Interval> accumulatedBlockIntervals = new ArrayList<Interval>(); // To save recompute time when checking timeblocks for application we store them as we create them. // Iterate over sorted list, checking time boundaries vs Shift Intervals. long accumulatedMillis = TKUtils.convertHoursToMillis(hoursBeforeVirtualDay); boolean previousDayOnly = false; // IF the rule is not active today, but was on the previous day, we need to still look at time blocks. if (!dayIsRuleActive(currentDay, rule)) { if (dayIsRuleActive(currentDay.minusDays(1), rule)) { previousDayOnly = true; } else { // Nothing to see here, move to next rule. continue; } } /* * We will touch each time block and accumulate time blocks that are applicable to * the current rule we are on. */ // These blocks are only used for detail application // We don't want to pass along the previous pay period, // because we don't want to modify the time blocks on that // period. If null is passed, time will be placed on the // first block of the first period if the previous period // block had influence. List<TimeBlock> previousBlocksFiltered = (previousPayPeriodPrevDay) ? null : filterBlocksByApplicableEarnGroup(fromEarnGroup, ruleTimeBlocksPrev); for (TimeBlock current : ruleTimeBlocksCurr) { if (!timeBlockHasEarnCode(fromEarnGroup, current)) { // TODO: WorkSchedule considerations somewhere in here? continue; } Interval blockInterval = new Interval(current.getBeginDateTime().withZone(zone), current.getEndDateTime().withZone(zone)); // Check both Intervals, since the time blocks could still // be applicable to the previous day. These two intervals should // not have any overlap. if (previousDayShiftInterval.overlaps(shiftInterval)) { LOG.error("Interval of greater than 24 hours created in the rules processing."); return; // throw new RuntimeException("Interval of greater than 24 hours created in the rules processing."); } // This block of code handles cases where you have time // that spills to multiple days and a shift rule that // has a valid window on multiple consecutive days. Time // must be applied with the correct shift interval. Interval overlap = previousDayShiftInterval.overlap(blockInterval); evalInterval = previousDayShiftInterval; if (overlap == null) { if (hoursToApplyPrevious.compareTo(BigDecimal.ZERO) > 0) { // we have hours from previous day, and the shift // window is going to move to current day. // Need to apply this now, and move window forward // for current time block. BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis); this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule); accumulatedMillis = 0L; // reset accumulated hours.. hoursToApply = BigDecimal.ZERO; hoursToApplyPrevious = BigDecimal.ZERO; } // Because of our position in the loop, when we are at this point, // we know we've passed any previous day shift intervals, so we can // determine if we should skip the current day based on the boolean // we set earlier. if (previousDayOnly) { continue; } overlap = shiftInterval.overlap(blockInterval); evalInterval = shiftInterval; } // Time bucketing and application as normal: // if (overlap != null) { // There IS overlap. if (previous != null) { // only check max gap if max gap of rule is not 0 if (rule.getMaxGap().compareTo(BigDecimal.ZERO) != 0 && exceedsMaxGap(previous, current, rule.getMaxGap())) { BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis); this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule); accumulatedMillis = 0L; // reset accumulated hours.. hoursToApply = BigDecimal.ZERO; hoursToApplyPrevious = BigDecimal.ZERO; } else { long millis = overlap.toDurationMillis(); accumulatedMillis += millis; hoursToApply = hoursToApply.add(TKUtils.convertMillisToHours(millis)); } } else { // Overlap shift at first time block. long millis = overlap.toDurationMillis(); accumulatedMillis += millis; hoursToApply = hoursToApply.add(TKUtils.convertMillisToHours(millis)); } accumulatedBlocks.add(current); accumulatedBlockIntervals.add(blockInterval); previous = current; // current can still apply to next. } else { // No Overlap / Outside of Rule if (previous != null) { BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis); this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule); accumulatedMillis = 0L; // reset accumulated hours.. hoursToApply = BigDecimal.ZERO; hoursToApplyPrevious = BigDecimal.ZERO; } } } // All time blocks are iterated over, check for remainders. // Check containers for time, and apply if needed. BigDecimal accumHours = TKUtils.convertMillisToHours(accumulatedMillis); this.applyAccumulatedWrapper(accumHours, evalInterval, accumulatedBlockIntervals, accumulatedBlocks, previousBlocksFiltered, hoursToApplyPrevious, hoursToApply, rule); } } // Keep track of previous as we move day by day. jobNumberToTimeBlocksPreviousDay = jobNumberToTimeBlocks; previousPayPeriodPrevDay = false; } }
From source file:org.kuali.kpme.tklm.time.rules.shiftdifferential.shift.ShiftCalendarInterval.java
License:Educational Community License
protected List<Shift> createShifts(ShiftDifferentialRule rule, LocalDateTime spanBegin, LocalDateTime spanEnd, DateTimeZone zone) {/*w w w .j a v a2s . c o m*/ DateTime spanBeginDT = spanBegin.toDateTime(zone); DateTime spanEndDT = spanEnd.toDateTime(zone); Interval calendarEntryInterval = new Interval(spanBeginDT, spanEndDT); DateTime shiftEnd = LocalTime.fromDateFields(rule.getEndTime()).toDateTime(spanBeginDT).minusDays(1); DateTime shiftStart = LocalTime.fromDateFields(rule.getBeginTime()).toDateTime(spanBeginDT).minusDays(1); if (shiftEnd.isBefore(shiftStart) || shiftEnd.isEqual(shiftStart)) { shiftEnd = shiftEnd.plusDays(1); } List<Shift> shifts = new ArrayList<Shift>(); Interval shiftInterval = new Interval(shiftStart, shiftEnd); //possible that there is no overlap between 1st interval and cal entry interval... if so, add a day. if (!calendarEntryInterval.overlaps(shiftInterval)) { shiftInterval = incrementShift(shiftInterval); } while (calendarEntryInterval.overlaps(shiftInterval)) { if (ruleIsActiveForDay(shiftInterval.getStart(), rule)) { shifts.add(new Shift(rule, shiftInterval, zone)); } shiftInterval = incrementShift(shiftInterval); } return shifts; }