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 org.apache.commons.collections.CollectionUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.joda.time.DateMidnight;
21  import org.joda.time.DateTime;
22  import org.joda.time.DateTimeConstants;
23  import org.joda.time.DateTimeZone;
24  import org.joda.time.Hours;
25  import org.joda.time.Interval;
26  import org.joda.time.LocalDateTime;
27  import org.kuali.hr.lm.LMConstants;
28  import org.kuali.hr.lm.accrual.AccrualCategory;
29  import org.kuali.hr.lm.employeeoverride.EmployeeOverride;
30  import org.kuali.hr.lm.leave.web.LeaveCalendarWSForm;
31  import org.kuali.hr.lm.leaveSummary.LeaveSummary;
32  import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
33  import org.kuali.hr.lm.leaveblock.LeaveBlock;
34  import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
35  import org.kuali.hr.time.assignment.Assignment;
36  import org.kuali.hr.time.assignment.AssignmentDescriptionKey;
37  import org.kuali.hr.time.base.web.TkCommonCalendarForm;
38  import org.kuali.hr.time.calendar.CalendarEntries;
39  import org.kuali.hr.time.earncode.EarnCode;
40  import org.kuali.hr.time.earncodegroup.EarnCodeGroup;
41  import org.kuali.hr.time.service.base.TkServiceLocator;
42  import org.kuali.hr.time.util.TKContext;
43  import org.kuali.hr.time.util.TKUser;
44  import org.kuali.hr.time.util.TKUtils;
45  import org.kuali.hr.time.util.TkConstants;
46  
47  import java.math.BigDecimal;
48  import java.sql.Date;
49  import java.sql.Timestamp;
50  import java.util.*;
51  
52  import org.kuali.rice.kew.api.KewApiServiceLocator;
53  import org.kuali.rice.kew.api.document.DocumentStatus;
54  import org.kuali.rice.krad.util.ObjectUtils;
55  
56  public class LeaveCalendarValidationUtil {
57      
58      //begin KPME-1263
59      public static List<String> validateLeaveAccrualRuleMaxUsage(LeaveCalendarWSForm lcf) {
60      	LeaveBlock updatedLeaveBlock = null;
61      	if(lcf.getLeaveBlockId() != null) {
62      		updatedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lcf.getLeaveBlockId());
63      	}
64      	return validateLeaveAccrualRuleMaxUsage(lcf.getLeaveSummary(), lcf.getSelectedEarnCode(), lcf.getStartDate(),
65      			lcf.getEndDate(), lcf.getLeaveAmount(), updatedLeaveBlock);
66      }
67  
68  	public static List<String> validateLeaveAccrualRuleMaxUsage(LeaveSummary ls, String selectedEarnCode, String leaveStartDateString,
69  			String leaveEndDateString, BigDecimal leaveAmount, LeaveBlock updatedLeaveBlock) {
70      	List<String> errors = new ArrayList<String>();
71          String principalId = TKContext.getTargetPrincipalId();
72      	long daysSpan = TKUtils.getDaysBetween(TKUtils.formatDateString(leaveStartDateString), TKUtils.formatDateString(leaveEndDateString));
73      	if(leaveAmount == null) {
74      		leaveAmount  = TKUtils.getHoursBetween(TKUtils.formatDateString(leaveStartDateString).getTime(), TKUtils.formatDateString(leaveEndDateString).getTime());
75      	}
76      	if(ls != null && CollectionUtils.isNotEmpty(ls.getLeaveSummaryRows())) {
77  	    	BigDecimal oldLeaveAmount = null;
78  	    	boolean earnCodeChanged = false;
79      		if(updatedLeaveBlock != null) {
80      			if(!updatedLeaveBlock.getEarnCode().equals(selectedEarnCode)) {
81      				earnCodeChanged = true;
82      			}
83      			if(!updatedLeaveBlock.getLeaveAmount().equals(leaveAmount)) {
84      				oldLeaveAmount = updatedLeaveBlock.getLeaveAmount();
85      			}
86      		}
87      		Date aDate = TKUtils.formatDateString(leaveEndDateString);
88  	    	EarnCode earnCodeObj = TkServiceLocator.getEarnCodeService().getEarnCode(selectedEarnCode, aDate);
89  	    	if(earnCodeObj != null) {
90  	    		AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(earnCodeObj.getAccrualCategory(), aDate);
91  	    		if(accrualCategory != null) {
92  	    			List<LeaveSummaryRow> rows = ls.getLeaveSummaryRows();
93  	    			for(LeaveSummaryRow aRow : rows) {
94  	    				if(aRow.getAccrualCategory().equals(accrualCategory.getAccrualCategory())) {
95  	    					//Does employee have overrides in place?
96  	    					List<EmployeeOverride> employeeOverrides = TkServiceLocator.getEmployeeOverrideService().getEmployeeOverrides(principalId,TKUtils.formatDateString(leaveEndDateString));
97  	    					String leavePlan = accrualCategory.getLeavePlan();
98  	    					BigDecimal maxUsage = aRow.getUsageLimit();
99  	    					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 }