001    /**
002     * Copyright 2004-2013 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     */
016    package org.kuali.hr.lm.leavecalendar.validation;
017    
018    import org.apache.commons.collections.CollectionUtils;
019    import org.apache.commons.lang.StringUtils;
020    import org.joda.time.DateMidnight;
021    import org.joda.time.DateTime;
022    import org.joda.time.DateTimeConstants;
023    import org.joda.time.DateTimeZone;
024    import org.joda.time.Hours;
025    import org.joda.time.Interval;
026    import org.joda.time.LocalDateTime;
027    import org.kuali.hr.lm.LMConstants;
028    import org.kuali.hr.lm.accrual.AccrualCategory;
029    import org.kuali.hr.lm.employeeoverride.EmployeeOverride;
030    import org.kuali.hr.lm.leave.web.LeaveCalendarWSForm;
031    import org.kuali.hr.lm.leaveSummary.LeaveSummary;
032    import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
033    import org.kuali.hr.lm.leaveblock.LeaveBlock;
034    import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
035    import org.kuali.hr.time.assignment.Assignment;
036    import org.kuali.hr.time.assignment.AssignmentDescriptionKey;
037    import org.kuali.hr.time.base.web.TkCommonCalendarForm;
038    import org.kuali.hr.time.calendar.CalendarEntries;
039    import org.kuali.hr.time.earncode.EarnCode;
040    import org.kuali.hr.time.earncodegroup.EarnCodeGroup;
041    import org.kuali.hr.time.service.base.TkServiceLocator;
042    import org.kuali.hr.time.util.TKContext;
043    import org.kuali.hr.time.util.TKUser;
044    import org.kuali.hr.time.util.TKUtils;
045    import org.kuali.hr.time.util.TkConstants;
046    
047    import java.math.BigDecimal;
048    import java.sql.Date;
049    import java.sql.Timestamp;
050    import java.util.*;
051    
052    import org.kuali.rice.kew.api.KewApiServiceLocator;
053    import org.kuali.rice.kew.api.document.DocumentStatus;
054    import org.kuali.rice.krad.util.ObjectUtils;
055    
056    public class LeaveCalendarValidationUtil {
057        
058        //begin KPME-1263
059        public static List<String> validateLeaveAccrualRuleMaxUsage(LeaveCalendarWSForm lcf) {
060            LeaveBlock updatedLeaveBlock = null;
061            if(lcf.getLeaveBlockId() != null) {
062                    updatedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lcf.getLeaveBlockId());
063            }
064            return validateLeaveAccrualRuleMaxUsage(lcf.getLeaveSummary(), lcf.getSelectedEarnCode(), lcf.getStartDate(),
065                            lcf.getEndDate(), lcf.getLeaveAmount(), updatedLeaveBlock);
066        }
067    
068            public static List<String> validateLeaveAccrualRuleMaxUsage(LeaveSummary ls, String selectedEarnCode, String leaveStartDateString,
069                            String leaveEndDateString, BigDecimal leaveAmount, LeaveBlock updatedLeaveBlock) {
070            List<String> errors = new ArrayList<String>();
071            String principalId = TKContext.getTargetPrincipalId();
072            long daysSpan = TKUtils.getDaysBetween(TKUtils.formatDateString(leaveStartDateString), TKUtils.formatDateString(leaveEndDateString));
073            if(leaveAmount == null) {
074                    leaveAmount  = TKUtils.getHoursBetween(TKUtils.formatDateString(leaveStartDateString).getTime(), TKUtils.formatDateString(leaveEndDateString).getTime());
075            }
076            if(ls != null && CollectionUtils.isNotEmpty(ls.getLeaveSummaryRows())) {
077                    BigDecimal oldLeaveAmount = null;
078                    boolean earnCodeChanged = false;
079                    if(updatedLeaveBlock != null) {
080                            if(!updatedLeaveBlock.getEarnCode().equals(selectedEarnCode)) {
081                                    earnCodeChanged = true;
082                            }
083                            if(!updatedLeaveBlock.getLeaveAmount().equals(leaveAmount)) {
084                                    oldLeaveAmount = updatedLeaveBlock.getLeaveAmount();
085                            }
086                    }
087                    Date aDate = TKUtils.formatDateString(leaveEndDateString);
088                    EarnCode earnCodeObj = TkServiceLocator.getEarnCodeService().getEarnCode(selectedEarnCode, aDate);
089                    if(earnCodeObj != null) {
090                            AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(earnCodeObj.getAccrualCategory(), aDate);
091                            if(accrualCategory != null) {
092                                    List<LeaveSummaryRow> rows = ls.getLeaveSummaryRows();
093                                    for(LeaveSummaryRow aRow : rows) {
094                                            if(aRow.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
095                                                    //Does employee have overrides in place?
096                                                    List<EmployeeOverride> employeeOverrides = TkServiceLocator.getEmployeeOverrideService().getEmployeeOverrides(principalId,TKUtils.formatDateString(leaveEndDateString));
097                                                    String leavePlan = accrualCategory.getLeavePlan();
098                                                    BigDecimal maxUsage = aRow.getUsageLimit();
099                                                    for(EmployeeOverride eo : employeeOverrides) {
100                                                            if(eo.getLeavePlan().equals(leavePlan) && eo.getAccrualCategory().equals(aRow.getAccrualCategory())) {
101                                                                    if(eo.getOverrideType().equals("MU") && eo.isActive()) {
102                                                                            if(eo.getOverrideValue()!=null) {
103                                                                                    maxUsage = new BigDecimal(eo.getOverrideValue());
104                                            } else { // no limit flag
105                                                                                    maxUsage = null;
106                                            }
107                                                                    }
108                                                            }
109                                                    }
110                                                    BigDecimal ytdUsage = aRow.getYtdApprovedUsage();
111                                                    BigDecimal pendingLeaveBalance = aRow.getPendingLeaveRequests();
112                                                    BigDecimal desiredUsage = new BigDecimal(0);
113                                                    if(pendingLeaveBalance!=null) {
114                                                            if(oldLeaveAmount!=null) {
115                                                                    
116                                                                    if(!earnCodeChanged || 
117                                                                                    updatedLeaveBlock.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
118                                                                            pendingLeaveBalance = pendingLeaveBalance.subtract(oldLeaveAmount.abs());
119                                                                    }
120                                                            }
121     
122                                                            desiredUsage = desiredUsage.add(pendingLeaveBalance);
123                                                    }
124                                                            
125                                                    desiredUsage = desiredUsage.add(leaveAmount.multiply(new BigDecimal(daysSpan+1)));
126    
127                                                            if(ytdUsage!=null) {
128                                                            desiredUsage = desiredUsage.add(ytdUsage);
129                                                    }
130                                                    if(maxUsage!=null) {
131                                                            if(desiredUsage.compareTo(maxUsage) > 0 ) {
132                                                                    errors.add("This leave request would exceed the usage limit for " + aRow.getAccrualCategory());                        //errorMessages
133                                                            }
134                                                    }
135                                            }
136                                    }
137                            }
138                    }
139            }
140            return errors;
141        }
142            //End KPME-1263
143    
144            //TODO: Move to WarningService
145            public static Map<String, Set<String>> validatePendingTransactions(String principalId, Date fromDate, Date toDate) {
146                    Map<String, Set<String>> allMessages = new HashMap<String, Set<String>>();
147                    
148            Set<String> actionMessages = new HashSet<String>();
149            Set<String> infoMessages = new HashSet<String>();
150            Set<String> warningMessages = new HashSet<String>();
151            
152            List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(principalId, fromDate, toDate, LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
153            Set<String> workflowDocIds = new HashSet<String>();
154            for(LeaveBlock lb : leaveBlocks) {
155                    if(lb.getTransactionalDocId() != null) {
156                            workflowDocIds.add(lb.getTransactionalDocId());
157                } else {
158                            if(StringUtils.contains(lb.getDescription(), "Forfeited balance transfer amount")) {
159                                    infoMessages.add("A max balance action that forfeited accrued leave occurred on this calendar");
160                    }
161                }
162            }
163            for(String workflowDocId : workflowDocIds) {
164                DocumentStatus status = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(workflowDocId);
165                
166                if(StringUtils.equals(status.getCode(), TkConstants.ROUTE_STATUS.FINAL)) {
167                    infoMessages.add("A transfer action occurred on this calendar");
168                }
169                else if(StringUtils.equals(status.getCode(), TkConstants.ROUTE_STATUS.ENROUTE)) {
170                    actionMessages.add("A pending balance transfer exists on this calendar. It must be finalized before this calendar can be approved");
171                }
172                else {
173                    warningMessages.add("A balance transfer document exists for this calendar with status neither final nor enroute");
174                }
175            }
176            
177            leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(principalId, fromDate, toDate, LMConstants.LEAVE_BLOCK_TYPE.LEAVE_PAYOUT);
178            workflowDocIds = new HashSet<String>();
179            for(LeaveBlock lb : leaveBlocks) {
180                    if(lb.getTransactionalDocId() != null) {
181                            workflowDocIds.add(lb.getTransactionalDocId());
182                }
183            }
184            for(String workflowDocId : workflowDocIds) {
185                DocumentStatus status = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(workflowDocId);
186    
187                if(StringUtils.equals(status.getCode(), TkConstants.ROUTE_STATUS.FINAL)) {
188                    infoMessages.add("A payout action occurred on this calendar");
189                }
190                else if(StringUtils.equals(status.getCode(), TkConstants.ROUTE_STATUS.ENROUTE)) {
191                    actionMessages.add("A pending payout exists on this calendar. It must be finalized before this calendar can be approved");
192                }
193                else {
194                    warningMessages.add("A payout document exists for this calendar with status neither final or enroute");
195                }
196            }
197            allMessages.put("actionMessages", actionMessages);
198            allMessages.put("infoMessages", infoMessages);
199            allMessages.put("warningMessages", warningMessages);
200            
201            return allMessages;
202            }
203            
204        // get warning messages associated with earn codes of leave blocks
205        public static Map<String, Set<String>> getWarningMessagesForLeaveBlocks(List<LeaveBlock> leaveBlocks) {
206    //        List<String> warningMessages = new ArrayList<String>();
207            Map<String, Set<String>> allMessages = new HashMap<String, Set<String>>();
208            
209            Set<String> actionMessages = new HashSet<String>();
210            Set<String> infoMessages = new HashSet<String>();
211            Set<String> warningMessages = new HashSet<String>();
212    
213            if (CollectionUtils.isNotEmpty(leaveBlocks)) {
214                for(LeaveBlock lb : leaveBlocks) {
215                    EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(lb.getEarnCode(), lb.getLeaveDate());
216                    if(ec != null) {
217                        EarnCodeGroup eg = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroupForEarnCode(lb.getEarnCode(), lb.getLeaveDate());
218                        if(eg != null && !StringUtils.isEmpty(eg.getWarningText())) {
219                            warningMessages.add(eg.getWarningText());
220                        }
221                    }
222                }
223            }
224            allMessages.put("actionMessages", actionMessages);
225            allMessages.put("infoMessages", infoMessages);
226            allMessages.put("warningMessages", warningMessages);
227    
228    //        warningMessages.addAll(aSet);
229            return allMessages;
230        }
231    
232        public static List<String> validateAvailableLeaveBalance(LeaveCalendarWSForm lcf) {
233            LeaveBlock updatedLeaveBlock = null;
234            if(lcf.getLeaveBlockId() != null) {
235                            updatedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lcf.getLeaveBlockId());
236            }
237            return validateAvailableLeaveBalanceForUsage(lcf.getSelectedEarnCode(), lcf.getStartDate(), lcf.getEndDate(), lcf.getLeaveAmount(), updatedLeaveBlock);
238        }
239    
240        public static List<String> validateAvailableLeaveBalanceForUsage(String earnCode, String leaveStartDateString, String leaveEndDateString,
241                    BigDecimal leaveAmount, LeaveBlock updatedLeaveBlock) {
242            List<String> errors = new ArrayList<String>();
243            boolean earnCodeChanged = false;
244            BigDecimal oldAmount = null;
245            
246            if(leaveAmount == null) {
247                    leaveAmount  = TKUtils.getHoursBetween(TKUtils.formatDateString(leaveStartDateString).getTime(), TKUtils.formatDateString(leaveEndDateString).getTime());
248            }
249                    if(updatedLeaveBlock != null) {
250                            if(!updatedLeaveBlock.getEarnCode().equals(earnCode)) {
251                                    earnCodeChanged = true;
252                            }
253                            if(!updatedLeaveBlock.getLeaveAmount().equals(leaveAmount)) {
254                                    oldAmount = updatedLeaveBlock.getLeaveAmount();
255                            }
256                    }
257                    Date startDate = TKUtils.formatDateString(leaveStartDateString);
258                    Date endDate = TKUtils.formatDateString(leaveEndDateString);
259                    long daysSpan = TKUtils.getDaysBetween(startDate,endDate);
260            EarnCode earnCodeObj = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, endDate);
261            if(earnCodeObj != null && earnCodeObj.getAllowNegativeAccrualBalance().equals("N")) {
262                    AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(earnCodeObj.getAccrualCategory(), endDate);
263                    if(accrualCategory != null) {
264                                    java.util.Date nextIntervalDate = TkServiceLocator.getAccrualService().getNextAccrualIntervalDate(accrualCategory.getAccrualEarnInterval(), endDate);
265                                    // get the usage checking cut off Date, normally it's the day before the next interval date
266                                    java.util.Date usageEndDate = nextIntervalDate;
267                                    if(nextIntervalDate.compareTo(endDate) > 0) {
268                                            Calendar aCal = Calendar.getInstance();
269                                            aCal.setTime(nextIntervalDate);
270                                            aCal.add(Calendar.DAY_OF_YEAR, -1);
271                                            usageEndDate = aCal.getTime();
272                                    }
273                                    // use the end of the year as the interval date for usage checking of no-accrual hours,
274                                    // normally no-accrual hours are from banked/transferred system scheduled time offs
275                                    if(accrualCategory.getAccrualEarnInterval().equals(LMConstants.ACCRUAL_EARN_INTERVAL_CODE.NO_ACCRUAL)) {
276                                            Calendar aCal = Calendar.getInstance();
277                                            aCal.setTime(endDate);
278                                            aCal.set(Calendar.MONTH, Calendar.DECEMBER);
279                                            aCal.set(Calendar.DAY_OF_MONTH, 31);
280                                            nextIntervalDate = aCal.getTime();
281                                            usageEndDate = nextIntervalDate;
282                                    }
283                                    BigDecimal availableBalance = TkServiceLocator.getLeaveSummaryService()
284                                                            .getLeaveBalanceForAccrCatUpToDate(TKContext.getTargetPrincipalId(), startDate, endDate, accrualCategory.getAccrualCategory(), usageEndDate);
285    
286                                    if(oldAmount!=null) {
287                                            if(!earnCodeChanged ||
288                                                            updatedLeaveBlock.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
289                                                    availableBalance = availableBalance.add(oldAmount.abs());
290                                            }
291                                    }
292                                    //multiply by days in span in case the user has also edited the start/end dates.
293                                    BigDecimal desiredUsage =null;
294                                    if(!TkConstants.EARN_CODE_TIME.equals(earnCodeObj.getRecordMethod())) {
295                                            desiredUsage = leaveAmount.multiply(new BigDecimal(daysSpan+1));
296                                    } else {
297                                            desiredUsage = leaveAmount.multiply(new BigDecimal(daysSpan));
298                                    }
299                                    
300                                    if(desiredUsage.compareTo(availableBalance) >  0 ) {
301                                            errors.add("Requested leave amount " + desiredUsage.toString() + " is greater than available leave balance " + availableBalance.toString());      //errorMessages
302                                    }
303                    }
304            }
305        
306            return errors;
307        }
308        
309        public static List<String> validateDates(String startDateS, String endDateS) {
310            List<String> errors = new ArrayList<String>();
311            if (errors.size() == 0 && StringUtils.isEmpty(startDateS)) errors.add("The start date is blank.");
312            if (errors.size() == 0 && StringUtils.isEmpty(endDateS)) errors.add("The end date is blank.");
313            return errors;
314        }
315    
316        public static List<String> validateTimes(String startTimeS, String endTimeS) {
317            List<String> errors = new ArrayList<String>();
318            if (errors.size() == 0 && startTimeS == null) errors.add("The start time is blank.");
319            if (errors.size() == 0 && endTimeS == null) errors.add("The end time is blank.");
320            return errors;
321        }
322    
323        
324    //    public static List<String> validateAvailableLeaveBalance(LeaveSummary ls, String earnCode, String leaveStartDateString, String leaveEndDateString,
325    //              BigDecimal leaveAmount, LeaveBlock updatedLeaveBlock) {
326    //      List<String> errors = new ArrayList<String>();
327    //      CalendarEntries calendarEntries = new CalendarEntries();
328    //      boolean earnCodeChanged = false;
329    //      BigDecimal oldAmount = null;
330    //      if(ls != null && CollectionUtils.isNotEmpty(ls.getLeaveSummaryRows())) {
331    //              if(updatedLeaveBlock != null) {
332    //                      if(!updatedLeaveBlock.getEarnCode().equals(earnCode)) {
333    //                              earnCodeChanged = true;
334    //                      }
335    //                      if(!updatedLeaveBlock.getLeaveAmount().equals(leaveAmount)) {
336    //                              oldAmount = updatedLeaveBlock.getLeaveAmount();
337    //                      }
338    //              }
339    //                      Date startDate = TKUtils.formatDateString(leaveStartDateString);
340    //                      Date endDate = TKUtils.formatDateString(leaveEndDateString);
341    //                      long daysSpan = TKUtils.getDaysBetween(startDate,endDate);
342    //              EarnCode earnCodeObj = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, endDate);
343    //              if(earnCodeObj != null && earnCodeObj.getAllowNegativeAccrualBalance().equals("N")) {
344    //                      AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(earnCodeObj.getAccrualCategory(), endDate);
345    //                      if(accrualCategory != null) {
346    //                              LeaveSummaryRow validationRow = ls.getLeaveSummaryRowForAccrualCategory(accrualCategory.getLmAccrualCategoryId());
347    //                              if(ObjectUtils.isNotNull(validationRow)) {
348    //                                      BigDecimal availableBalance = validationRow.getLeaveBalance();
349    //                                      LeaveSummary ytdSummary = TkServiceLocator.getLeaveSummaryService().getLeaveSummaryAsOfDateForAccrualCategory(TKContext.getTargetPrincipalId(), startDate, accrualCategory.getAccrualCategory());
350    //                                      if(ytdSummary != null) {
351    //                                              LeaveSummaryRow ytdSummaryRow = ytdSummary.getLeaveSummaryRowForAccrualCategory(accrualCategory.getLmAccrualCategoryId());
352    //                                              if(ytdSummaryRow != null)
353    //                                                      availableBalance = ytdSummaryRow.getLeaveBalance();
354    //                                      }
355    //
356    //                                      if(oldAmount!=null) {
357    //
358    //                                              if(!earnCodeChanged ||
359    //                                                              updatedLeaveBlock.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
360    //                                                              availableBalance = availableBalance.add(oldAmount.abs());
361    //                                              }
362    //
363    //                                              }
364    //                                              //multiply by days in span in case the user has also edited the start/end dates.
365    //                                      BigDecimal desiredUsage = leaveAmount.multiply(new BigDecimal(daysSpan+1));
366    //
367    //                                      if(desiredUsage.compareTo(availableBalance) >  0 ) {
368    //                                              errors.add("Requested leave amount is greater than available leave balance.");      //errorMessages
369    //                                      }
370    //                              }
371    //                      }
372    //              }
373    //      }
374    //      
375    //      return errors;
376    //    }
377        
378    
379        // KPME-2010
380        public static List<String> validateSpanningWeeks(LeaveCalendarWSForm lcf) {
381            boolean spanningWeeks = lcf.getSpanningWeeks().equalsIgnoreCase("y");
382            Date startDate = TKUtils.formatDateString(lcf.getStartDate());
383            EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(lcf.getSelectedEarnCode(), startDate);
384            DateTime startTemp, endTemp;
385    
386            if (ec != null && !ec.getRecordMethod().equals(LMConstants.RECORD_METHOD.TIME)) {
387                startTemp = new DateTime(startDate);
388                endTemp = new DateTime(TKUtils.formatDateString(lcf.getEndDate()));
389            } else {
390                startTemp = new DateTime(TKUtils.convertDateStringToTimestamp(lcf.getStartDate()).getTime());
391                endTemp = new DateTime(TKUtils.convertDateStringToTimestamp(lcf.getEndDate()).getTime());
392            }
393            
394            List<String> errors = new ArrayList<String>();
395            boolean valid = true;
396            while ((startTemp.isBefore(endTemp) || startTemp.isEqual(endTemp)) && valid) {
397                    if (!spanningWeeks && 
398                            (startTemp.getDayOfWeek() == DateTimeConstants.SATURDAY || startTemp.getDayOfWeek() == DateTimeConstants.SUNDAY)) {
399                            valid = false;
400                    }
401                    startTemp = startTemp.plusDays(1);
402            }
403            if (!valid) {
404                    errors.add("Weekend day is selected, but include weekends checkbox is not checked");            //errorMessages
405            }
406            return errors;
407        }
408        
409        public static List<String> validateParametersAccordingToSelectedEarnCodeRecordMethod(LeaveCalendarWSForm lcf) {
410            return validateParametersForLeaveEntry(lcf.getSelectedEarnCode(), lcf.getCalendarEntry(), lcf.getStartDate(), lcf.getEndDate(), lcf.getStartTime(), lcf.getEndTime(), lcf.getSelectedAssignment(), lcf.getLeaveCalendarDocument(), lcf.getLeaveBlockId());
411        }
412        
413        public static List<String> validateParametersForLeaveEntry(String selectedEarnCode, CalendarEntries leaveCalEntry, String startDateS, String endDateS, String startTimeS, String endTimeS, String selectedAssignment, LeaveCalendarDocument leaveCalendarDocument, String leaveBlockId) {
414            
415            java.sql.Date asOfDate = leaveCalEntry.getEndPeriodDate();
416            
417            List<String> errors = new ArrayList<String>();
418            if (StringUtils.isNotBlank(selectedEarnCode)) {
419                    EarnCode  earnCode = TkServiceLocator.getEarnCodeService().getEarnCode(selectedEarnCode, asOfDate);
420                    
421                    if(earnCode != null && earnCode.getRecordMethod().equalsIgnoreCase(TkConstants.EARN_CODE_TIME)) {
422                            
423                            errors.addAll(LeaveCalendarValidationUtil.validateDates(startDateS, endDateS));
424                            errors.addAll(LeaveCalendarValidationUtil.validateTimes(startTimeS, endTimeS));
425                            if (errors.size() > 0) return errors;
426                    
427                            Long startTime;
428                            Long endTime;
429                           
430                            startTime = TKUtils.convertDateStringToTimestampWithoutZone(startDateS, startTimeS).getTime();
431                            endTime = TKUtils.convertDateStringToTimestampWithoutZone(endDateS, endTimeS).getTime();
432                    
433                            errors.addAll(validateInterval(leaveCalEntry, startTime, endTime));
434                            if (errors.size() > 0) return errors;
435                            
436                            if (startTimeS == null) errors.add("The start time is blank.");
437                            if (endTimeS == null) errors.add("The end time is blank.");
438                            if (startTime - endTime == 0) errors.add("Start time and end time cannot be equivalent");
439                            
440                            if (errors.size() > 0) return errors;
441                    
442                            DateTime startTemp = new DateTime(startTime);
443                            DateTime endTemp = new DateTime(endTime);
444                    
445                            if (errors.size() == 0) {
446                                Hours hrs = Hours.hoursBetween(startTemp, endTemp);
447                                if (hrs.getHours() >= 24) errors.add("One leaveblock cannot exceed 24 hours");
448                            }
449                            if (errors.size() > 0) return errors;
450                            
451                            //Check that assignment is valid for both days
452                            AssignmentDescriptionKey assignKey = TkServiceLocator.getAssignmentService().getAssignmentDescriptionKey(selectedAssignment);
453                            Assignment assign = TkServiceLocator.getAssignmentService().getAssignment(assignKey, new Date(startTime));
454                            
455                            if ((startTime.compareTo(endTime) > 0 || endTime.compareTo(startTime) < 0)) {
456                                errors.add("The time or date is not valid.");
457                            }
458                            if (errors.size() > 0) return errors;
459                            
460    //                      boolean isRegularEarnCode = StringUtils.equals(assign.getJob().getPayTypeObj().getRegEarnCode(),selectedEarnCode);
461                            boolean isRegularEarnCode = true;
462                            errors.addAll(validateOverlap(startTime, endTime, startDateS, endTimeS,startTemp, endTemp, leaveCalEntry, leaveBlockId, isRegularEarnCode, earnCode.getRecordMethod()));
463                            if (errors.size() > 0) return errors;
464                    }
465                }
466            return errors;
467        }
468        
469        public static List<String> validateInterval(CalendarEntries payCalEntry, Long startTime, Long endTime) {
470            List<String> errors = new ArrayList<String>();
471            LocalDateTime pcb_ldt = payCalEntry.getBeginLocalDateTime();
472            LocalDateTime pce_ldt = payCalEntry.getEndLocalDateTime();
473            DateTimeZone utz = TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback();
474            DateTime p_cal_b_dt = pcb_ldt.toDateTime(utz);
475            DateTime p_cal_e_dt = pce_ldt.toDateTime(utz);
476    
477            Interval payInterval = new Interval(p_cal_b_dt, p_cal_e_dt);
478            if (errors.size() == 0 && !payInterval.contains(startTime)) {
479                errors.add("The start date/time is outside the pay period");
480            }
481            if (errors.size() == 0 && !payInterval.contains(endTime) && p_cal_e_dt.getMillis() != endTime) {
482                errors.add("The end date/time is outside the pay period");
483            }
484            return errors;
485        }
486        
487        public static List<String> validateOverlap(Long startTime, Long endTime, String startDateS, String endTimeS, DateTime startTemp, DateTime endTemp, CalendarEntries calendarEntry, String lmLeaveBlockId, boolean isRegularEarnCode, String earnCodeType) {
488            List<String> errors = new ArrayList<String>();
489            Interval addedTimeblockInterval = new Interval(startTime, endTime);
490            List<Interval> dayInt = new ArrayList<Interval>();
491            String viewPrincipal = TKUser.getCurrentTargetPersonId();
492            
493            dayInt.add(addedTimeblockInterval);
494            List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(viewPrincipal, calendarEntry);
495                    List<String> assignmentKeys = new ArrayList<String>();
496            for(Assignment assign : assignments) {
497                    assignmentKeys.add(assign.getAssignmentKey());
498            }
499            
500            List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForLeaveCalendar(viewPrincipal, calendarEntry.getBeginPeriodDate(), calendarEntry.getEndPeriodDate(), assignmentKeys);
501            for (LeaveBlock leaveBlock : leaveBlocks) {
502                     if (errors.size() == 0 && StringUtils.equals(earnCodeType, TkConstants.EARN_CODE_TIME) && leaveBlock.getBeginTimestamp() != null && leaveBlock.getEndTimestamp()!= null) {
503                    Interval leaveBlockInterval = new Interval(leaveBlock.getBeginTimestamp().getTime(), leaveBlock.getEndTimestamp().getTime());
504                    for (Interval intv : dayInt) {
505                        if (isRegularEarnCode && leaveBlockInterval.overlaps(intv) && (lmLeaveBlockId == null || lmLeaveBlockId.compareTo(leaveBlock.getLmLeaveBlockId()) != 0)) {
506                            errors.add("The leave block you are trying to add overlaps with an existing time block.");
507                        }
508                    }
509                     }
510            }
511    
512            return errors;
513        }
514    }