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.time.util;
017
018 import java.math.BigDecimal;
019 import java.sql.Date;
020 import java.util.HashMap;
021 import java.util.List;
022 import java.util.Map;
023
024 import org.apache.commons.lang.StringUtils;
025 import org.kuali.hr.lm.LMConstants;
026 import org.kuali.hr.lm.accrual.AccrualCategory;
027 import org.kuali.hr.lm.earncodesec.EarnCodeSecurity;
028 import org.kuali.hr.lm.leavecode.LeaveCode;
029 import org.kuali.hr.lm.leaveplan.LeavePlan;
030 import org.kuali.hr.location.Location;
031 import org.kuali.hr.paygrade.PayGrade;
032 import org.kuali.hr.time.accrual.TimeOffAccrual;
033 import org.kuali.hr.time.authorization.DepartmentalRule;
034 import org.kuali.hr.time.calendar.Calendar;
035 import org.kuali.hr.time.department.Department;
036 import org.kuali.hr.time.earncode.EarnCode;
037 import org.kuali.hr.time.earncodegroup.EarnCodeGroup;
038 import org.kuali.hr.time.earncodegroup.EarnCodeGroupDefinition;
039 import org.kuali.hr.time.paytype.PayType;
040 import org.kuali.hr.time.principal.PrincipalHRAttributes;
041 import org.kuali.hr.time.salgroup.SalGroup;
042 import org.kuali.hr.time.service.base.TkServiceLocator;
043 import org.kuali.hr.time.task.Task;
044 import org.kuali.hr.time.workarea.WorkArea;
045 import org.kuali.kfs.coa.businessobject.Chart;
046 import org.kuali.rice.kim.api.identity.Person;
047 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
048 import org.kuali.rice.krad.service.KRADServiceLocator;
049
050 /**
051 * A few methods to assist with various validation tasks.
052 */
053 public class ValidationUtils {
054
055 /**
056 * For DepartmentalRule objects, if a work area is defined, you can not
057 * leave the department field with a wildcard. Permission for wildcarding
058 * will be checked with other methods.
059 *
060 * @param dr The DepartmentalRule to examine.
061 * @return true if valid, false otherwise.
062 */
063 public static boolean validateWorkAreaDeptWildcarding(DepartmentalRule dr) {
064 boolean ret = true;
065
066 if (StringUtils.equals(dr.getDept(), TkConstants.WILDCARD_CHARACTER)) {
067 ret = dr.getWorkArea().equals(TkConstants.WILDCARD_LONG);
068 }
069
070 return ret;
071 }
072
073 /**
074 * Most basic validation: Only checks for presence in the database.
075 */
076 public static boolean validateWorkArea(Long workArea) {
077 return validateWorkArea(workArea, null);
078 }
079
080 /**
081 * Most basic validation: Only checks for presence in the database.
082 */
083 public static boolean validateDepartment(String department) {
084 return validateDepartment(department, null);
085 }
086
087 /**
088 * Most basic validation: Only checks for presence in the database.
089 */
090 public static boolean validateAccrualCategory(String accrualCategory) {
091 return validateAccrualCategory(accrualCategory, null);
092 }
093
094
095 public static boolean validateSalGroup(String salGroup, Date asOfDate) {
096 boolean valid = false;
097
098 if (StringUtils.equals(salGroup, TkConstants.WILDCARD_CHARACTER)) {
099 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 }