View Javadoc

1   /**
2    * Copyright 2004-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.hr.lm.leavecalendar.validation;
17  
18  import java.math.BigDecimal;
19  import java.sql.Date;
20  import java.util.ArrayList;
21  import java.util.Calendar;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import org.apache.commons.collections.CollectionUtils;
29  import org.apache.commons.lang.StringUtils;
30  import org.joda.time.DateTime;
31  import org.joda.time.DateTimeConstants;
32  import org.joda.time.DateTimeZone;
33  import org.joda.time.Hours;
34  import org.joda.time.Interval;
35  import org.joda.time.LocalDateTime;
36  import org.kuali.hr.lm.LMConstants;
37  import org.kuali.hr.lm.accrual.AccrualCategory;
38  import org.kuali.hr.lm.employeeoverride.EmployeeOverride;
39  import org.kuali.hr.lm.leave.web.LeaveCalendarWSForm;
40  import org.kuali.hr.lm.leaveSummary.LeaveSummary;
41  import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
42  import org.kuali.hr.lm.leaveblock.LeaveBlock;
43  import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
44  import org.kuali.hr.time.assignment.Assignment;
45  import org.kuali.hr.time.assignment.AssignmentDescriptionKey;
46  import org.kuali.hr.time.calendar.CalendarEntries;
47  import org.kuali.hr.time.earncode.EarnCode;
48  import org.kuali.hr.time.earncodegroup.EarnCodeGroup;
49  import org.kuali.hr.time.service.base.TkServiceLocator;
50  import org.kuali.hr.time.util.TKContext;
51  import org.kuali.hr.time.util.TKUser;
52  import org.kuali.hr.time.util.TKUtils;
53  import org.kuali.hr.time.util.TkConstants;
54  import org.kuali.rice.kew.api.KewApiServiceLocator;
55  import org.kuali.rice.kew.api.document.DocumentStatus;
56  
57  public class LeaveCalendarValidationUtil {
58      
59      //begin KPME-1263
60      public static List<String> validateLeaveAccrualRuleMaxUsage(LeaveCalendarWSForm lcf) {
61      	LeaveBlock updatedLeaveBlock = null;
62      	if(lcf.getLeaveBlockId() != null) {
63      		updatedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lcf.getLeaveBlockId());
64      	}
65      	return validateLeaveAccrualRuleMaxUsage(lcf.getLeaveSummary(), lcf.getSelectedEarnCode(), lcf.getStartDate(),
66      			lcf.getEndDate(), lcf.getLeaveAmount(), updatedLeaveBlock);
67      }
68  
69  	public static List<String> validateLeaveAccrualRuleMaxUsage(LeaveSummary ls, String selectedEarnCode, String leaveStartDateString,
70  			String leaveEndDateString, BigDecimal leaveAmount, LeaveBlock updatedLeaveBlock) {
71      	List<String> errors = new ArrayList<String>();
72          String principalId = TKContext.getTargetPrincipalId();
73      	long daysSpan = TKUtils.getDaysBetween(TKUtils.formatDateString(leaveStartDateString), TKUtils.formatDateString(leaveEndDateString));
74      	if(leaveAmount == null) {
75      		leaveAmount  = TKUtils.getHoursBetween(TKUtils.formatDateString(leaveStartDateString).getTime(), TKUtils.formatDateString(leaveEndDateString).getTime());
76      	}
77      	if(ls != null && CollectionUtils.isNotEmpty(ls.getLeaveSummaryRows())) {
78  	    	BigDecimal oldLeaveAmount = null;
79  	    	boolean earnCodeChanged = false;
80      		if(updatedLeaveBlock != null) {
81      			if(!updatedLeaveBlock.getEarnCode().equals(selectedEarnCode)) {
82      				earnCodeChanged = true;
83      			}
84      			if(!updatedLeaveBlock.getLeaveAmount().equals(leaveAmount)) {
85      				oldLeaveAmount = updatedLeaveBlock.getLeaveAmount();
86      			}
87      		}
88      		Date aDate = TKUtils.formatDateString(leaveEndDateString);
89  	    	EarnCode earnCodeObj = TkServiceLocator.getEarnCodeService().getEarnCode(selectedEarnCode, aDate);
90  	    	if(earnCodeObj != null && StringUtils.equals(earnCodeObj.getAccrualBalanceAction(),LMConstants.ACCRUAL_BALANCE_ACTION.USAGE)
91  	    			|| StringUtils.equals(earnCodeObj.getUsageLimit(), "I")) {
92  	    		AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(earnCodeObj.getAccrualCategory(), aDate);
93  	    		if(accrualCategory != null) {
94  	    			List<LeaveSummaryRow> rows = ls.getLeaveSummaryRows();
95  	    			for(LeaveSummaryRow aRow : rows) {
96  	    				if(aRow.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
97  	    					//Does employee have overrides in place?
98  	    					List<EmployeeOverride> employeeOverrides = TkServiceLocator.getEmployeeOverrideService().getEmployeeOverrides(principalId,TKUtils.formatDateString(leaveEndDateString));
99  	    					String leavePlan = accrualCategory.getLeavePlan();
100 	    					BigDecimal maxUsage = aRow.getUsageLimit();
101 	    					for(EmployeeOverride eo : employeeOverrides) {
102 	    						if(eo.getLeavePlan().equals(leavePlan) && eo.getAccrualCategory().equals(aRow.getAccrualCategory())) {
103 	    							if(eo.getOverrideType().equals("MU") && eo.isActive()) {
104 	    								if(eo.getOverrideValue()!=null) {
105 	    									maxUsage = new BigDecimal(eo.getOverrideValue());
106                                         } else { // no limit flag
107 	    									maxUsage = null;
108                                         }
109 	    							}
110 	    						}
111 	    					}
112 	    					BigDecimal ytdUsage = aRow.getYtdApprovedUsage();
113 	    					BigDecimal pendingLeaveBalance = aRow.getPendingLeaveRequests();
114 	    					BigDecimal desiredUsage = new BigDecimal(0);
115 	    					if(pendingLeaveBalance!=null) {
116 	    						if(oldLeaveAmount!=null) {
117 	    							
118 	    							if(!earnCodeChanged || 
119 	    									updatedLeaveBlock.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
120    			    						pendingLeaveBalance = pendingLeaveBalance.subtract(oldLeaveAmount.abs());
121 	    							}
122 	    						}
123  
124     							desiredUsage = desiredUsage.add(pendingLeaveBalance);
125 	    					}
126    							
127 	    					desiredUsage = desiredUsage.add(leaveAmount.multiply(new BigDecimal(daysSpan+1)));
128 
129    							if(ytdUsage!=null) {
130     							desiredUsage = desiredUsage.add(ytdUsage);
131     						}
132 	    					if(maxUsage!=null) {
133 		    					if(desiredUsage.compareTo(maxUsage) > 0 ) {
134 		    						errors.add("This leave request would exceed the usage limit for " + aRow.getAccrualCategory());                        //errorMessages
135 		    					}
136 	    					}
137 	    				}
138 	    			}
139 	    		}
140 	    	}
141     	}
142     	return errors;
143     }
144 	//End KPME-1263
145 
146 	//TODO: Move to WarningService
147 	public static Map<String, Set<String>> validatePendingTransactions(String principalId, Date fromDate, Date toDate) {
148 		Map<String, Set<String>> allMessages = new HashMap<String, Set<String>>();
149 		
150         Set<String> actionMessages = new HashSet<String>();
151         Set<String> infoMessages = new HashSet<String>();
152         Set<String> warningMessages = new HashSet<String>();
153         
154         List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(principalId, fromDate, toDate, LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
155         Set<String> workflowDocIds = new HashSet<String>();
156         for(LeaveBlock lb : leaveBlocks) {
157         	if(lb.getTransactionalDocId() != null) {
158         		workflowDocIds.add(lb.getTransactionalDocId());
159             } else {
160         		if(StringUtils.contains(lb.getDescription(), "Forfeited balance transfer amount")) {
161         			infoMessages.add("A max balance action that forfeited accrued leave occurred on this calendar");
162                 }
163             }
164         }
165         for(String workflowDocId : workflowDocIds) {
166             DocumentStatus status = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(workflowDocId);
167             
168             if(StringUtils.equals(status.getCode(), TkConstants.ROUTE_STATUS.FINAL)) {
169             	infoMessages.add("A transfer action occurred on this calendar");
170             }
171             else if(StringUtils.equals(status.getCode(), TkConstants.ROUTE_STATUS.ENROUTE)) {
172             	actionMessages.add("A pending balance transfer exists on this calendar. It must be finalized before this calendar can be approved");
173             }
174             else {
175             	warningMessages.add("A balance transfer document exists for this calendar with status neither final nor enroute");
176             }
177         }
178         
179         leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(principalId, fromDate, toDate, LMConstants.LEAVE_BLOCK_TYPE.LEAVE_PAYOUT);
180         workflowDocIds = new HashSet<String>();
181         for(LeaveBlock lb : leaveBlocks) {
182         	if(lb.getTransactionalDocId() != null) {
183         		workflowDocIds.add(lb.getTransactionalDocId());
184             }
185         }
186         for(String workflowDocId : workflowDocIds) {
187             DocumentStatus status = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(workflowDocId);
188 
189             if(StringUtils.equals(status.getCode(), TkConstants.ROUTE_STATUS.FINAL)) {
190             	infoMessages.add("A payout action occurred on this calendar");
191             }
192             else if(StringUtils.equals(status.getCode(), TkConstants.ROUTE_STATUS.ENROUTE)) {
193             	actionMessages.add("A pending payout exists on this calendar. It must be finalized before this calendar can be approved");
194             }
195             else {
196             	warningMessages.add("A payout document exists for this calendar with status neither final or enroute");
197             }
198         }
199         allMessages.put("actionMessages", actionMessages);
200         allMessages.put("infoMessages", infoMessages);
201         allMessages.put("warningMessages", warningMessages);
202         
203         return allMessages;
204 	}
205 	
206     // get warning messages associated with earn codes of leave blocks
207     public static Map<String, Set<String>> getWarningMessagesForLeaveBlocks(List<LeaveBlock> leaveBlocks) {
208 //        List<String> warningMessages = new ArrayList<String>();
209         Map<String, Set<String>> allMessages = new HashMap<String, Set<String>>();
210         
211         Set<String> actionMessages = new HashSet<String>();
212         Set<String> infoMessages = new HashSet<String>();
213         Set<String> warningMessages = new HashSet<String>();
214 
215         if (CollectionUtils.isNotEmpty(leaveBlocks)) {
216             for(LeaveBlock lb : leaveBlocks) {
217                 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(lb.getEarnCode(), lb.getLeaveDate());
218                 if(ec != null) {
219                     EarnCodeGroup eg = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroupForEarnCode(lb.getEarnCode(), lb.getLeaveDate());
220                     if(eg != null && !StringUtils.isEmpty(eg.getWarningText())) {
221                         warningMessages.add(eg.getWarningText());
222                     }
223                 }
224             }
225         }
226         allMessages.put("actionMessages", actionMessages);
227         allMessages.put("infoMessages", infoMessages);
228         allMessages.put("warningMessages", warningMessages);
229 
230 //        warningMessages.addAll(aSet);
231         return allMessages;
232     }
233 
234     public static List<String> validateAvailableLeaveBalance(LeaveCalendarWSForm lcf) {
235     	LeaveBlock updatedLeaveBlock = null;
236     	if(lcf.getLeaveBlockId() != null) {
237 			updatedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lcf.getLeaveBlockId());
238     	}
239     	return validateAvailableLeaveBalanceForUsage(lcf.getSelectedEarnCode(), lcf.getStartDate(), lcf.getEndDate(), lcf.getLeaveAmount(), updatedLeaveBlock);
240     }
241 
242     public static List<String> validateAvailableLeaveBalanceForUsage(String earnCode, String leaveStartDateString, String leaveEndDateString,
243     		BigDecimal leaveAmount, LeaveBlock updatedLeaveBlock) {
244     	List<String> errors = new ArrayList<String>();
245     	boolean earnCodeChanged = false;
246     	BigDecimal oldAmount = null;
247     	
248     	if(leaveAmount == null) {
249     		leaveAmount  = TKUtils.getHoursBetween(TKUtils.formatDateString(leaveStartDateString).getTime(), TKUtils.formatDateString(leaveEndDateString).getTime());
250     	}
251 		if(updatedLeaveBlock != null) {
252 			if(!updatedLeaveBlock.getEarnCode().equals(earnCode)) {
253 				earnCodeChanged = true;
254 			}
255 			if(!updatedLeaveBlock.getLeaveAmount().equals(leaveAmount)) {
256 				oldAmount = updatedLeaveBlock.getLeaveAmount();
257 			}
258 		}
259 		Date startDate = TKUtils.formatDateString(leaveStartDateString);
260 		Date endDate = TKUtils.formatDateString(leaveEndDateString);
261 		long daysSpan = TKUtils.getDaysBetween(startDate,endDate);
262     	EarnCode earnCodeObj = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, endDate);
263     	if(earnCodeObj != null && earnCodeObj.getAllowNegativeAccrualBalance().equals("N")) {
264     		AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(earnCodeObj.getAccrualCategory(), endDate);
265     		if(accrualCategory != null) {
266 				java.util.Date nextIntervalDate = TkServiceLocator.getAccrualService().getNextAccrualIntervalDate(accrualCategory.getAccrualEarnInterval(), endDate);
267 				// get the usage checking cut off Date, normally it's the day before the next interval date
268 				java.util.Date usageEndDate = nextIntervalDate;
269 				if(nextIntervalDate.compareTo(endDate) > 0) {
270 					Calendar aCal = Calendar.getInstance();
271 					aCal.setTime(nextIntervalDate);
272 					aCal.add(Calendar.DAY_OF_YEAR, -1);
273 					usageEndDate = aCal.getTime();
274 				}
275 				// use the end of the year as the interval date for usage checking of no-accrual hours,
276 				// normally no-accrual hours are from banked/transferred system scheduled time offs
277 				if(accrualCategory.getAccrualEarnInterval().equals(LMConstants.ACCRUAL_EARN_INTERVAL_CODE.NO_ACCRUAL)) {
278 					Calendar aCal = Calendar.getInstance();
279 					aCal.setTime(endDate);
280 					aCal.set(Calendar.MONTH, Calendar.DECEMBER);
281 					aCal.set(Calendar.DAY_OF_MONTH, 31);
282 					nextIntervalDate = aCal.getTime();
283 					usageEndDate = nextIntervalDate;
284 				}
285 				BigDecimal availableBalance = TkServiceLocator.getLeaveSummaryService()
286 							.getLeaveBalanceForAccrCatUpToDate(TKContext.getTargetPrincipalId(), startDate, endDate, accrualCategory.getAccrualCategory(), usageEndDate);
287 
288 				if(oldAmount!=null) {
289 					if(!earnCodeChanged ||
290 							updatedLeaveBlock.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
291 						availableBalance = availableBalance.add(oldAmount.abs());
292 					}
293 				}
294 				//multiply by days in span in case the user has also edited the start/end dates.
295 				// daySpan for the same start/end dates is 0 so we need to add 1 to it
296 				BigDecimal desiredUsage = leaveAmount.multiply(new BigDecimal(daysSpan+1));
297 //				if(!TkConstants.EARN_CODE_TIME.equals(earnCodeObj.getRecordMethod())) {
298 //					desiredUsage = leaveAmount.multiply(new BigDecimal(daysSpan+1));
299 //				} else {
300 //					desiredUsage = leaveAmount.multiply(new BigDecimal(daysSpan));
301 //				}
302 				
303 				if(desiredUsage.compareTo(availableBalance) >  0 ) {
304 					errors.add("Requested leave amount " + desiredUsage.toString() + " is greater than available leave balance " + availableBalance.toString());      //errorMessages
305 				}
306     		}
307     	}
308     
309     	return errors;
310     }
311     
312     public static List<String> validateDates(String startDateS, String endDateS) {
313         List<String> errors = new ArrayList<String>();
314         if (errors.size() == 0 && StringUtils.isEmpty(startDateS)) errors.add("The start date is blank.");
315         if (errors.size() == 0 && StringUtils.isEmpty(endDateS)) errors.add("The end date is blank.");
316         return errors;
317     }
318 
319     public static List<String> validateTimes(String startTimeS, String endTimeS) {
320         List<String> errors = new ArrayList<String>();
321         if (errors.size() == 0 && startTimeS == null) errors.add("The start time is blank.");
322         if (errors.size() == 0 && endTimeS == null) errors.add("The end time is blank.");
323         return errors;
324     }
325 
326     
327 //    public static List<String> validateAvailableLeaveBalance(LeaveSummary ls, String earnCode, String leaveStartDateString, String leaveEndDateString,
328 //    		BigDecimal leaveAmount, LeaveBlock updatedLeaveBlock) {
329 //    	List<String> errors = new ArrayList<String>();
330 //    	CalendarEntries calendarEntries = new CalendarEntries();
331 //    	boolean earnCodeChanged = false;
332 //    	BigDecimal oldAmount = null;
333 //    	if(ls != null && CollectionUtils.isNotEmpty(ls.getLeaveSummaryRows())) {
334 //    		if(updatedLeaveBlock != null) {
335 //    			if(!updatedLeaveBlock.getEarnCode().equals(earnCode)) {
336 //    				earnCodeChanged = true;
337 //    			}
338 //    			if(!updatedLeaveBlock.getLeaveAmount().equals(leaveAmount)) {
339 //    				oldAmount = updatedLeaveBlock.getLeaveAmount();
340 //    			}
341 //    		}
342 //			Date startDate = TKUtils.formatDateString(leaveStartDateString);
343 //			Date endDate = TKUtils.formatDateString(leaveEndDateString);
344 //			long daysSpan = TKUtils.getDaysBetween(startDate,endDate);
345 //	    	EarnCode earnCodeObj = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, endDate);
346 //	    	if(earnCodeObj != null && earnCodeObj.getAllowNegativeAccrualBalance().equals("N")) {
347 //	    		AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(earnCodeObj.getAccrualCategory(), endDate);
348 //	    		if(accrualCategory != null) {
349 //	    			LeaveSummaryRow validationRow = ls.getLeaveSummaryRowForAccrualCategory(accrualCategory.getLmAccrualCategoryId());
350 //    				if(ObjectUtils.isNotNull(validationRow)) {
351 //    					BigDecimal availableBalance = validationRow.getLeaveBalance();
352 //    					LeaveSummary ytdSummary = TkServiceLocator.getLeaveSummaryService().getLeaveSummaryAsOfDateForAccrualCategory(TKContext.getTargetPrincipalId(), startDate, accrualCategory.getAccrualCategory());
353 //    					if(ytdSummary != null) {
354 //    						LeaveSummaryRow ytdSummaryRow = ytdSummary.getLeaveSummaryRowForAccrualCategory(accrualCategory.getLmAccrualCategoryId());
355 //    						if(ytdSummaryRow != null)
356 //    							availableBalance = ytdSummaryRow.getLeaveBalance();
357 //    					}
358 //
359 //    					if(oldAmount!=null) {
360 //
361 //	    					if(!earnCodeChanged ||
362 //	    							updatedLeaveBlock.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
363 //								availableBalance = availableBalance.add(oldAmount.abs());
364 //	    					}
365 //
366 //						}
367 //						//multiply by days in span in case the user has also edited the start/end dates.
368 //    					BigDecimal desiredUsage = leaveAmount.multiply(new BigDecimal(daysSpan+1));
369 //
370 //    					if(desiredUsage.compareTo(availableBalance) >  0 ) {
371 //    						errors.add("Requested leave amount is greater than available leave balance.");      //errorMessages
372 //    					}
373 //    				}
374 //	    		}
375 //	    	}
376 //    	}
377 //    	
378 //    	return errors;
379 //    }
380     
381 
382     // KPME-2010
383     public static List<String> validateSpanningWeeks(LeaveCalendarWSForm lcf) {
384     	List<String> errors = new ArrayList<String>();
385     	
386     	boolean spanningWeeks = lcf.getSpanningWeeks().equalsIgnoreCase("y");
387     	
388     	if (!spanningWeeks) {
389 	        Date startDate = TKUtils.formatDateString(lcf.getStartDate());
390 	        EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(lcf.getSelectedEarnCode(), startDate);
391 	        DateTime startTemp, endTemp;
392 	
393 	        if (ec != null && !ec.getRecordMethod().equals(LMConstants.RECORD_METHOD.TIME)) {
394 	            startTemp = new DateTime(startDate);
395 	            endTemp = new DateTime(TKUtils.formatDateString(lcf.getEndDate()));
396 	        } else {
397 	    	    startTemp = new DateTime(TKUtils.convertDateStringToTimestamp(lcf.getStartDate()).getTime());
398 	            endTemp = new DateTime(TKUtils.convertDateStringToTimestamp(lcf.getEndDate()).getTime());
399 	        }
400 	    	
401 	    	boolean isOnlyWeekendSpan = true;
402 	    	while ((startTemp.isBefore(endTemp) || startTemp.isEqual(endTemp)) && isOnlyWeekendSpan) {
403 	           	if (startTemp.getDayOfWeek() != DateTimeConstants.SATURDAY && startTemp.getDayOfWeek() != DateTimeConstants.SUNDAY) {
404 	           		isOnlyWeekendSpan = false;
405 	        	}
406 	        	startTemp = startTemp.plusDays(1);
407 	        }
408 	        if (isOnlyWeekendSpan) {
409 	        	errors.add("Weekend day is selected, but include weekends checkbox is not checked");            //errorMessages
410 	        }
411     	}
412     	
413     	return errors;
414     }
415     
416     public static List<String> validateParametersAccordingToSelectedEarnCodeRecordMethod(LeaveCalendarWSForm lcf) {
417     	return validateParametersForLeaveEntry(lcf.getSelectedEarnCode(), lcf.getCalendarEntry(), lcf.getStartDate(), lcf.getEndDate(), lcf.getStartTime(), lcf.getEndTime(), lcf.getSelectedAssignment(), lcf.getLeaveCalendarDocument(), lcf.getLeaveBlockId());
418     }
419     
420     public static List<String> validateParametersForLeaveEntry(String selectedEarnCode, CalendarEntries leaveCalEntry, String startDateS, String endDateS, String startTimeS, String endTimeS, String selectedAssignment, LeaveCalendarDocument leaveCalendarDocument, String leaveBlockId) {
421     	
422     	java.sql.Date asOfDate = leaveCalEntry.getEndPeriodDate();
423     	
424     	List<String> errors = new ArrayList<String>();
425     	if (StringUtils.isNotBlank(selectedEarnCode)) {
426     		EarnCode  earnCode = TkServiceLocator.getEarnCodeService().getEarnCode(selectedEarnCode, asOfDate);
427 	    	
428     		if(earnCode != null && earnCode.getRecordMethod().equalsIgnoreCase(TkConstants.EARN_CODE_TIME)) {
429     			
430 		    	errors.addAll(LeaveCalendarValidationUtil.validateDates(startDateS, endDateS));
431 		        errors.addAll(LeaveCalendarValidationUtil.validateTimes(startTimeS, endTimeS));
432 		        if (errors.size() > 0) return errors;
433 		
434 		        Long startTime;
435 		        Long endTime;
436 		       
437 		        startTime = TKUtils.convertDateStringToTimestampWithoutZone(startDateS, startTimeS).getTime();
438 		        endTime = TKUtils.convertDateStringToTimestampWithoutZone(endDateS, endTimeS).getTime();
439 		
440 		        errors.addAll(validateInterval(leaveCalEntry, startTime, endTime));
441 		        if (errors.size() > 0) return errors;
442 		        
443 		        if (startTimeS == null) errors.add("The start time is blank.");
444 		        if (endTimeS == null) errors.add("The end time is blank.");
445 		        if (startTime - endTime == 0) errors.add("Start time and end time cannot be equivalent");
446 		        
447 		        if (errors.size() > 0) return errors;
448 		
449 		        DateTime startTemp = new DateTime(startTime);
450 		        DateTime endTemp = new DateTime(endTime);
451 		
452 		        if (errors.size() == 0) {
453 		            Hours hrs = Hours.hoursBetween(startTemp, endTemp);
454 		            if (hrs.getHours() >= 24) errors.add("One leaveblock cannot exceed 24 hours");
455 		        }
456 		        if (errors.size() > 0) return errors;
457 		        
458 		        //Check that assignment is valid for both days
459 		        AssignmentDescriptionKey assignKey = TkServiceLocator.getAssignmentService().getAssignmentDescriptionKey(selectedAssignment);
460 		        Assignment assign = TkServiceLocator.getAssignmentService().getAssignment(assignKey, new Date(startTime));
461 		        
462 		        if ((startTime.compareTo(endTime) > 0 || endTime.compareTo(startTime) < 0)) {
463 		            errors.add("The time or date is not valid.");
464 		        }
465 		        if (errors.size() > 0) return errors;
466 		        
467 //		        boolean isRegularEarnCode = StringUtils.equals(assign.getJob().getPayTypeObj().getRegEarnCode(),selectedEarnCode);
468 		        boolean isRegularEarnCode = true;
469 	        	errors.addAll(validateOverlap(startTime, endTime, startDateS, endTimeS,startTemp, endTemp, leaveCalEntry, leaveBlockId, isRegularEarnCode, earnCode.getRecordMethod()));
470 		        if (errors.size() > 0) return errors;
471     		}
472 	    }
473         return errors;
474     }
475     
476     public static List<String> validateInterval(CalendarEntries payCalEntry, Long startTime, Long endTime) {
477         List<String> errors = new ArrayList<String>();
478         LocalDateTime pcb_ldt = payCalEntry.getBeginLocalDateTime();
479         LocalDateTime pce_ldt = payCalEntry.getEndLocalDateTime();
480         DateTimeZone utz = TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback();
481         DateTime p_cal_b_dt = pcb_ldt.toDateTime(utz);
482         DateTime p_cal_e_dt = pce_ldt.toDateTime(utz);
483 
484         Interval payInterval = new Interval(p_cal_b_dt, p_cal_e_dt);
485         if (errors.size() == 0 && !payInterval.contains(startTime)) {
486             errors.add("The start date/time is outside the pay period");
487         }
488         if (errors.size() == 0 && !payInterval.contains(endTime) && p_cal_e_dt.getMillis() != endTime) {
489             errors.add("The end date/time is outside the pay period");
490         }
491         return errors;
492     }
493     
494     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) {
495         List<String> errors = new ArrayList<String>();
496         Interval addedTimeblockInterval = new Interval(startTime, endTime);
497         List<Interval> dayInt = new ArrayList<Interval>();
498         String viewPrincipal = TKUser.getCurrentTargetPersonId();
499         
500         dayInt.add(addedTimeblockInterval);
501         List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(viewPrincipal, calendarEntry);
502 		List<String> assignmentKeys = new ArrayList<String>();
503         for(Assignment assign : assignments) {
504         	assignmentKeys.add(assign.getAssignmentKey());
505         }
506         
507         List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForLeaveCalendar(viewPrincipal, calendarEntry.getBeginPeriodDate(), calendarEntry.getEndPeriodDate(), assignmentKeys);
508         for (LeaveBlock leaveBlock : leaveBlocks) {
509         	 if (errors.size() == 0 && StringUtils.equals(earnCodeType, TkConstants.EARN_CODE_TIME) && leaveBlock.getBeginTimestamp() != null && leaveBlock.getEndTimestamp()!= null) {
510                 Interval leaveBlockInterval = new Interval(leaveBlock.getBeginTimestamp().getTime(), leaveBlock.getEndTimestamp().getTime());
511                 for (Interval intv : dayInt) {
512                     if (isRegularEarnCode && leaveBlockInterval.overlaps(intv) && (lmLeaveBlockId == null || lmLeaveBlockId.compareTo(leaveBlock.getLmLeaveBlockId()) != 0)) {
513                         errors.add("The leave block you are trying to add overlaps with an existing time block.");
514                     }
515                 }
516         	 }
517         }
518 
519         return errors;
520     }
521 }