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 }