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.time.util;
17  
18  import java.math.BigDecimal;
19  import java.sql.Date;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.commons.lang.StringUtils;
25  import org.kuali.hr.lm.LMConstants;
26  import org.kuali.hr.lm.accrual.AccrualCategory;
27  import org.kuali.hr.lm.earncodesec.EarnCodeSecurity;
28  import org.kuali.hr.lm.leavecode.LeaveCode;
29  import org.kuali.hr.lm.leaveplan.LeavePlan;
30  import org.kuali.hr.location.Location;
31  import org.kuali.hr.paygrade.PayGrade;
32  import org.kuali.hr.time.accrual.TimeOffAccrual;
33  import org.kuali.hr.time.authorization.DepartmentalRule;
34  import org.kuali.hr.time.calendar.Calendar;
35  import org.kuali.hr.time.department.Department;
36  import org.kuali.hr.time.earncode.EarnCode;
37  import org.kuali.hr.time.earncodegroup.EarnCodeGroup;
38  import org.kuali.hr.time.earncodegroup.EarnCodeGroupDefinition;
39  import org.kuali.hr.time.paytype.PayType;
40  import org.kuali.hr.time.principal.PrincipalHRAttributes;
41  import org.kuali.hr.time.salgroup.SalGroup;
42  import org.kuali.hr.time.service.base.TkServiceLocator;
43  import org.kuali.hr.time.task.Task;
44  import org.kuali.hr.time.workarea.WorkArea;
45  import org.kuali.kfs.coa.businessobject.Chart;
46  import org.kuali.rice.kim.api.identity.Person;
47  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
48  import org.kuali.rice.krad.service.KRADServiceLocator;
49  
50  /**
51   * A few methods to assist with various validation tasks.
52   */
53  public class ValidationUtils {
54  
55      /**
56       * For DepartmentalRule objects, if a work area is defined, you can not
57       * leave the department field with a wildcard. Permission for wildcarding
58       * will be checked with other methods.
59       *
60       * @param dr The DepartmentalRule to examine.
61       * @return true if valid, false otherwise.
62       */
63      public static boolean validateWorkAreaDeptWildcarding(DepartmentalRule dr) {
64          boolean ret = true;
65  
66          if (StringUtils.equals(dr.getDept(), TkConstants.WILDCARD_CHARACTER)) {
67              ret = dr.getWorkArea().equals(TkConstants.WILDCARD_LONG);
68          }
69  
70          return ret;
71      }
72  
73  	/**
74  	 * Most basic validation: Only checks for presence in the database.
75  	 */
76  	public static boolean validateWorkArea(Long workArea) {
77  		return validateWorkArea(workArea, null);
78  	}
79  
80  	/**
81  	 * Most basic validation: Only checks for presence in the database.
82  	 */
83  	public static boolean validateDepartment(String department) {
84  		return validateDepartment(department, null);
85  	}
86  
87  	/**
88  	 * Most basic validation: Only checks for presence in the database.
89  	 */
90  	public static boolean validateAccrualCategory(String accrualCategory) {
91  		return validateAccrualCategory(accrualCategory, null);
92  	}
93  
94  
95  	public static boolean validateSalGroup(String salGroup, Date asOfDate) {
96  		boolean valid = false;
97  
98  		if (StringUtils.equals(salGroup, TkConstants.WILDCARD_CHARACTER)) {
99  			valid = true;
100 		} else if (asOfDate != null) {
101 			SalGroup sg = TkServiceLocator.getSalGroupService().getSalGroup(salGroup, asOfDate);
102 			valid = (sg != null);
103 		} else {
104 			int count = TkServiceLocator.getSalGroupService().getSalGroupCount(salGroup);
105 			valid = (count > 0);
106 		}
107 
108 		return valid;
109 	}
110 
111 	public static boolean validateEarnCode(String earnCode, Date asOfDate) {
112 		boolean valid = false;
113 
114 		if (asOfDate != null) {
115 			EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
116 			valid = (ec != null);
117 		} else {
118 			int count = TkServiceLocator.getEarnCodeService().getEarnCodeCount(earnCode);
119 			valid = (count > 0);
120 		}
121 
122 		return valid;
123 	}
124 	
125 	public static boolean validateLeaveCode(String leaveCode, Date asOfDate) {
126 		boolean valid = false;
127 		
128 		if (asOfDate != null) {
129 			LeaveCode lc = TkServiceLocator.getLeaveCodeService().getLeaveCode(leaveCode, asOfDate);
130 			valid = (lc != null);
131 		} else {
132 			Map<String, String> fieldValues = new HashMap<String, String>();
133 			fieldValues.put("leaveCode", leaveCode);
134 			int matches = KRADServiceLocator.getBusinessObjectService().countMatching(LeaveCode.class, fieldValues);
135 			
136 			valid = matches > 0;
137 		}
138 		
139 		return valid;
140 	}
141 	
142 	public static boolean validateLeavePlan(String leavePlan, Date asOfDate) {
143 		boolean valid = false;
144 		
145 		if (asOfDate != null) {
146 			LeavePlan lp = TkServiceLocator.getLeavePlanService().getLeavePlan(leavePlan, asOfDate);
147 			valid = (lp != null);
148 		} else {
149 			// chen, moved the code that access db to service and dao
150 			valid = TkServiceLocator.getLeavePlanService().isValidLeavePlan(leavePlan);
151 		}
152 		
153 		return valid;
154 	}
155 
156 	public static boolean validateLeaveCode(String leaveCode, String principalId, Date asOfDate) {
157 		boolean valid = false;
158 		
159 		if (asOfDate != null) {
160 			List<LeaveCode> leaveCodes = TkServiceLocator.getLeaveCodeService().getLeaveCodes(principalId, asOfDate);
161 			if(leaveCodes != null && !leaveCodes.isEmpty()) {
162 				for(LeaveCode leaveCodeObj : leaveCodes) {
163 					if(leaveCodeObj.getLeaveCode() != null) {
164 						if(StringUtils.equals(leaveCodeObj.getLeaveCode().trim(), leaveCode.trim())){
165 							valid = true;
166 							break;
167 						}
168 					}
169 				}
170 			}
171 //			valid = (leaveCodes != null);
172 		} else {
173 			Map<String, String> fieldValues = new HashMap<String, String>();
174 			fieldValues.put("leaveCode", leaveCode);
175 			int matches = KRADServiceLocator.getBusinessObjectService().countMatching(LeaveCode.class, fieldValues);
176 			
177 			valid = matches > 0;
178 		}
179 		
180 		return valid;
181 	}
182 	
183 	public static boolean validateEarnCodeOfAccrualCategory(String earnCode, String accrualCategory, Date asOfDate) {
184 		boolean valid = false;
185 		
186 		if (asOfDate != null) {
187 			AccrualCategory accrualCategoryObj = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
188 			if (accrualCategoryObj != null) {
189 				if (StringUtils.equals(earnCode, accrualCategoryObj.getEarnCode())) {
190 					valid = true;
191 				}
192 			}
193 		} else {
194 			Map<String, String> fieldValues = new HashMap<String, String>();
195 			fieldValues.put("earnCode", earnCode);
196 			int matches = KRADServiceLocator.getBusinessObjectService().countMatching(EarnCode.class, fieldValues);
197 			
198 			valid = matches > 0;
199 		}
200 		
201 		return valid;
202 	}
203 	
204 	public static boolean validateAccCategory(String accrualCategory, Date asOfDate) {
205 		boolean valid = false;
206 		
207 		if (asOfDate != null) {
208 			AccrualCategory ac = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
209 			valid = (ac != null);
210 		} else {
211 			Map<String, String> fieldValues = new HashMap<String, String>();
212 			fieldValues.put("accrualCategory", accrualCategory);
213 			int matches = KRADServiceLocator.getBusinessObjectService().countMatching(AccrualCategory.class, fieldValues);
214 			
215 			valid = matches > 0;
216 		}
217 		
218 		return valid;
219 	}
220 	
221 	public static boolean validateAccCategory(String accrualCategory, String principalId, Date asOfDate) {
222 		boolean valid = false;
223 		
224 		if (asOfDate != null) {
225 			AccrualCategory ac = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
226 			if(ac != null && ac.getLeavePlan() != null) {
227 				// fetch leave plan users
228 				if(principalId != null) {
229 					PrincipalHRAttributes principalHRAttributes = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId, asOfDate);
230 					if(principalHRAttributes != null && principalHRAttributes.getLeavePlan() != null) {
231 						valid = StringUtils.equals(ac.getLeavePlan().trim(), principalHRAttributes.getLeavePlan().trim());
232 					}
233 				} else {
234 					valid = true;
235 				}
236 			} 
237 		} else {
238 			Map<String, String> fieldValues = new HashMap<String, String>();
239 			fieldValues.put("accrualCategory", accrualCategory);
240 			int matches = KRADServiceLocator.getBusinessObjectService().countMatching(AccrualCategory.class, fieldValues);
241 			
242 			valid = matches > 0;
243 		}
244 		return valid;
245 	}
246 	
247 	public static boolean validateLocation(String location, Date asOfDate) {
248 		boolean valid = false;
249 
250 		if (asOfDate != null) {
251 			Location l = TkServiceLocator.getLocationService().getLocation(location, asOfDate);
252 			valid = (l != null);
253 		} else {
254 			int count = TkServiceLocator.getLocationService().getLocationCount(location);
255 			valid = (count > 0);
256 		}
257 
258 		return valid;
259 	}
260 
261 	public static boolean validatePayType(String payType, Date asOfDate) {
262 		boolean valid = false;
263 
264 		if (asOfDate != null) {
265 			PayType pt = TkServiceLocator.getPayTypeService().getPayType(payType, asOfDate);
266 			valid = (pt != null);
267 		} else {
268 			int count = TkServiceLocator.getPayTypeService().getPayTypeCount(payType);
269 			valid = (count > 0);
270 		}
271 
272 		return valid;
273 	}
274 
275 
276 	public static boolean validatePayGrade(String payGrade, Date asOfDate) {
277 		boolean valid = false;
278 
279 		if (asOfDate != null) {
280 			PayGrade pg = TkServiceLocator.getPayGradeService().getPayGrade(payGrade, asOfDate);
281 			valid = (pg != null);
282 		} else {
283 			int count = TkServiceLocator.getPayGradeService().getPayGradeCount(payGrade);
284 			valid = (count > 0);
285 		}
286 
287 		return valid;
288 	}
289 
290     /**
291      *
292      * @param earnCode
293      * @param otEarnCode If true, earn code is valid ONLY if it is an overtime earn code.
294      * @param asOfDate
295      * @return
296      */
297     public static boolean validateEarnCode(String earnCode, boolean otEarnCode, Date asOfDate) {
298         boolean valid = false;
299 
300         if (asOfDate != null) {
301             EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
302             valid = (ec != null) && (otEarnCode ? ec.getOvtEarnCode().booleanValue() : true);
303         }
304 
305         return valid;
306     }
307 
308 	/**
309 	 * Checks for row presence of a department, and optionally whether or not
310 	 * it is active as of the specified date.
311 	 */
312 	public static boolean validateDepartment(String department, Date asOfDate) {
313 		boolean valid = false;
314 
315         if (StringUtils.isEmpty(department)) {
316           // do nothing, let false be returned.
317         } else if (asOfDate != null) {
318 			Department d = TkServiceLocator.getDepartmentService().getDepartment(department, asOfDate);
319 		    valid = (d != null);
320 		} else {
321 			int count = TkServiceLocator.getDepartmentService().getDepartmentCount(department);
322 			valid = (count > 0);
323 		}
324 
325 		return valid;
326 	}
327 
328     public static boolean validateChart(String chart) {
329         boolean valid = false;
330 
331         if (!StringUtils.isEmpty(chart)) {
332             Object o = KRADServiceLocator.getBusinessObjectService().findBySinglePrimaryKey(Chart.class, chart);
333             valid = (o instanceof Chart);
334         }
335 
336         return valid;
337     }
338 
339 	/**
340 	 * Checks for row presence of a work area, and optionally whether or not
341 	 * it is active as of the specified date.
342 	 */
343     public static boolean validateWorkArea(Long workArea, Date asOfDate) {
344         return ValidationUtils.validateWorkArea(workArea, null, asOfDate);
345     }
346 
347 	public static boolean validateWorkArea(Long workArea, String dept, Date asOfDate) {
348 		boolean valid = false;
349 
350 		if (workArea == null) {
351 			valid = false;
352 		} else if (workArea.equals(TkConstants.WILDCARD_LONG)) {
353 			valid = true;
354 		} else if (asOfDate != null) {
355 			WorkArea wa = TkServiceLocator.getWorkAreaService().getWorkArea(workArea, asOfDate);
356             if (wa != null && dept != null) {
357                 valid = StringUtils.equalsIgnoreCase(dept, wa.getDept());
358             } else {
359 			    valid = (wa != null);
360             }
361 		} else {
362             // Not valid if no date is passed.
363 		}
364 
365 		return valid;
366 	}
367 	/**
368 	 * Checks for row presence of a Accrual Category, and optionally whether or not
369 	 * it is active as of the specified date.
370 	 */
371 	public static boolean validateAccrualCategory(String accrualCategory, Date asOfDate) {
372 		boolean valid = false;
373 
374 		if (StringUtils.equals(accrualCategory, TkConstants.WILDCARD_CHARACTER)) {
375 			valid = true;
376 		} else if (asOfDate != null) {
377 			AccrualCategory ac = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
378 			valid = (ac != null);
379 		}
380 
381 		return valid;
382 	}
383 
384 	/**
385 	 * Checks for row presence of a principal Id, and optionally whether or not
386 	 * it is active as of the specified date.
387 	 */
388 	public static boolean validatePrincipalId(String principalId) {
389 		boolean valid = false;
390 		if (principalId != null) {
391 			Person p = KimApiServiceLocator.getPersonService().getPerson(principalId);
392 		    valid = (p != null);
393 		}
394 		return valid;
395 	}
396 
397     /**
398      * No wildcarding is accounted for in this method.
399      * @param task Task "Long Name"
400      * @param asOfDate Can be null, if we just want to look for the general case.
401      * @return True if the task is present / valid.
402      */
403     public static boolean validateTask(Long task, Date asOfDate) {
404         boolean valid = false;
405 
406         if (task != null && asOfDate != null) {
407             Task t = TkServiceLocator.getTaskService().getTask(task, asOfDate);
408             valid = (t != null);
409         } else if (task != null) {
410         	int count = TkServiceLocator.getTaskService().getTaskCount(task);
411             valid = (count > 0);
412         }
413 
414         return valid;
415     }
416 
417     /**
418      * No wildcarding is accounted for in this method.
419      * @param earnGroup EarnCodeGroup
420      * @param asOfDate Can be null, if we just want to look for the general case.
421      * @return True if the EarnCodeGroup is present / valid.
422      */
423     public static boolean validateEarnGroup(String earnGroup, Date asOfDate) {
424         boolean valid = false;
425 
426         if (earnGroup != null && asOfDate != null) {
427             EarnCodeGroup eg = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroup(earnGroup, asOfDate);
428             valid = (eg != null);
429         } else if (earnGroup != null) {
430         	int count = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroupCount(earnGroup);
431             valid = (count > 0);
432         }
433 
434         return valid;
435     }
436     
437     /**
438      * @param earnGroup EarnCodeGroup
439      * @param asOfDate
440      * @return True if the EarnCodeGroup has overtime earn codes
441      */
442     public static boolean earnGroupHasOvertimeEarnCodes(String earnGroup, Date asOfDate) {
443          if (earnGroup != null && asOfDate != null) {
444              EarnCodeGroup eg = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroup(earnGroup, asOfDate);
445              if(eg != null) {
446             	for(EarnCodeGroupDefinition egd : eg.getEarnCodeGroups()) {
447             		if(egd.getEarnCode() != null) {
448             			EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(egd.getEarnCode(), asOfDate);
449             			if(ec != null && ec.getOvtEarnCode()) {
450             				return true;
451             			}
452             		}
453             	}
454              }
455          }
456 
457         return false;
458     }
459 
460 
461 	/**
462 	 * Checks for row presence of a pay calendar
463 	 */
464 	public static boolean validateCalendar(String calendarName) {
465 		Map<String, String> fieldValues = new HashMap<String, String>();
466 		fieldValues.put("calendarName", calendarName);
467 		int matches = KRADServiceLocator.getBusinessObjectService().countMatching(Calendar.class, fieldValues);
468 
469         return matches > 0;
470 	}
471 
472    public static boolean duplicateDeptEarnCodeExists(EarnCodeSecurity deptEarnCode) {
473 	   boolean valid = false;
474 	   int count = TkServiceLocator.getEarnCodeSecurityService().getEarnCodeSecurityCount
475                (deptEarnCode.getDept(), deptEarnCode.getHrSalGroup(), deptEarnCode.getEarnCode(), deptEarnCode.isEmployee() ? "1" : "0",
476                        deptEarnCode.isApprover() ? "1" : "0", deptEarnCode.getLocation(), deptEarnCode.isActive() ? "Y" : "N", deptEarnCode.getEffectiveDate(), null);
477        if(count == 1) {
478     	   valid = true;
479     	   count = TkServiceLocator.getEarnCodeSecurityService().getEarnCodeSecurityCount
480                    (deptEarnCode.getDept(), deptEarnCode.getHrSalGroup(), deptEarnCode.getEarnCode(), deptEarnCode.isEmployee() ? "1" : "0",
481                            deptEarnCode.isApprover() ? "1" : "0", deptEarnCode.getLocation(), deptEarnCode.isActive() ? "Y" : "N", deptEarnCode.getEffectiveDate(), deptEarnCode.getHrEarnCodeSecurityId());
482     	   if(count == 1) {
483     		   valid = false;
484     	   }
485        } else if(count > 1) {
486     	   valid = true;
487        }
488 
489 	   return valid;
490    }
491    
492    public static boolean duplicateTimeOffAccrual (TimeOffAccrual timeOffAccrual) {
493 	   boolean valid = false;
494 	   int count = TkServiceLocator.getTimeOffAccrualService().getTimeOffAccrualCount
495                (timeOffAccrual.getAccrualCategory(), timeOffAccrual.getEffectiveDate(), timeOffAccrual.getPrincipalId(), null);
496 	   if(count == 1) {
497     	   valid = true;
498     	   count = TkServiceLocator.getTimeOffAccrualService().getTimeOffAccrualCount
499                    (timeOffAccrual.getAccrualCategory(), timeOffAccrual.getEffectiveDate(), timeOffAccrual.getPrincipalId(), timeOffAccrual.getLmAccrualId());
500     	   if(count == 1) {
501     		   valid = false;
502     	   }
503        } else if(count > 1) {
504     	   valid = true;
505        }
506 	   return valid;
507    }
508 
509    /**
510     * Checks for date not more than one year in the future from accrualDAte
511     * 
512     */
513 
514    public static boolean validateOneYearFutureDateFromAccrualDate(Date date, Date accrualDate){
515 	   java.util.Calendar startDate = java.util.Calendar.getInstance();
516 	   startDate.setTime(accrualDate);
517 	   startDate.add(java.util.Calendar.DATE, -1);
518 	   startDate.set(java.util.Calendar.SECOND, 0);
519 	   startDate.set(java.util.Calendar.MINUTE, 0);
520 	   startDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
521 	   java.util.Calendar endDate = java.util.Calendar.getInstance();
522 	   endDate.setTime(accrualDate);
523 	   endDate.add(java.util.Calendar.YEAR, 1); // One year after the current date
524 	   return date.compareTo(startDate.getTime()) * date.compareTo(endDate.getTime()) <= 0;
525    }
526    
527    
528    /**
529     * Checks for date not more than one year in the future or current date
530     * 
531     */
532 
533    public static boolean validateOneYearFutureDate(Date date){
534 	   java.util.Calendar startDate = java.util.Calendar.getInstance();
535 	   startDate.add(java.util.Calendar.DATE, -1);
536 	   startDate.set(java.util.Calendar.SECOND, 0);
537 	   startDate.set(java.util.Calendar.MINUTE, 0);
538 	   startDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
539 	   java.util.Calendar endDate = java.util.Calendar.getInstance();
540 	   endDate.add(java.util.Calendar.YEAR, 1); // One year after the current date
541 	   return date.compareTo(startDate.getTime()) * date.compareTo(endDate.getTime()) <= 0;
542    }
543    
544    /**
545     * Checks for date not more than one year in the future and does not consider past date
546     * 
547     */
548 
549    public static boolean validateOneYearFutureEffectiveDate(Date date){
550 	   java.util.Calendar startDate = java.util.Calendar.getInstance();
551 	   startDate.set(java.util.Calendar.MILLISECOND, 0);
552 	   startDate.set(java.util.Calendar.SECOND, 0);
553 	   startDate.set(java.util.Calendar.MINUTE, 0);
554 	   startDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
555 	   startDate.add(java.util.Calendar.YEAR, 1); // One year after the current date
556 	   return date.compareTo(startDate.getTime()) <= 0;
557    }
558    
559    /**
560     * Checks for date in the future
561     * 
562     */
563    
564    public static boolean validateFutureDate(Date date){
565 	   java.util.Calendar startDate = java.util.Calendar.getInstance();
566 	   startDate.add(java.util.Calendar.DATE, 0);
567 	   startDate.set(java.util.Calendar.SECOND, 0);
568 	   startDate.set(java.util.Calendar.MINUTE, 0);
569 	   startDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
570 	   return date.compareTo(startDate.getTime()) > 0;
571    }
572 
573 	/**
574 	 * Checks for row presence of a pay calendar by calendar type
575 	 */
576 	public static boolean validateCalendarByType(String calendarName, String calendarType) {
577 		Map<String, String> fieldValues = new HashMap<String, String>();
578 		fieldValues.put("calendarName", calendarName);
579 		fieldValues.put("calendarTypes", calendarType);
580 		int matches = KRADServiceLocator.getBusinessObjectService().countMatching(Calendar.class, fieldValues);
581 		
582 		return matches > 0;
583 	}
584 	
585 	public static boolean validateRecordMethod(String recordMethod, String accrualCategory, Date asOfDate) {
586 		boolean valid = false;
587 		if (asOfDate != null) {
588 			AccrualCategory ac = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
589 			if (ac != null
590                     && ac.getUnitOfTime() != null) {
591                 if (LMConstants.RECORD_METHOD.HOUR.equals(ac.getUnitOfTime())
592                         && (LMConstants.RECORD_METHOD.HOUR.equals(recordMethod))
593                             || LMConstants.RECORD_METHOD.TIME.equals(recordMethod)) {
594                     valid = true;
595                 } else {
596                     valid = StringUtils.equalsIgnoreCase(ac.getUnitOfTime(), recordMethod);
597                 }
598 
599             }
600 		}
601 		return valid;
602 	}
603 	
604 	public static boolean validateEarnCodeFraction(String earnCode, BigDecimal amount, Date asOfDate) {
605 		boolean valid = true;
606 		 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
607 		 if(ec != null && ec.getFractionalTimeAllowed() != null) {
608 			 BigDecimal fracAllowed = new BigDecimal(ec.getFractionalTimeAllowed());
609 			 if(amount.scale() > fracAllowed.scale()) {
610 				 valid = false;
611 			 }
612 		 }
613 		return valid;
614 	}
615 }