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 org.apache.commons.lang.StringUtils;
019    import org.kuali.hr.lm.LMConstants;
020    import org.kuali.hr.lm.accrual.AccrualCategory;
021    import org.kuali.hr.lm.earncodesec.EarnCodeSecurity;
022    import org.kuali.hr.lm.leaveplan.LeavePlan;
023    import org.kuali.hr.location.Location;
024    import org.kuali.hr.paygrade.PayGrade;
025    import org.kuali.hr.time.authorization.DepartmentalRule;
026    import org.kuali.hr.time.calendar.Calendar;
027    import org.kuali.hr.time.department.Department;
028    import org.kuali.hr.time.earncode.EarnCode;
029    import org.kuali.hr.time.earncodegroup.EarnCodeGroup;
030    import org.kuali.hr.time.earncodegroup.EarnCodeGroupDefinition;
031    import org.kuali.hr.time.paytype.PayType;
032    import org.kuali.hr.time.principal.PrincipalHRAttributes;
033    import org.kuali.hr.time.salgroup.SalGroup;
034    import org.kuali.hr.time.service.base.TkServiceLocator;
035    import org.kuali.hr.time.task.Task;
036    import org.kuali.hr.time.workarea.WorkArea;
037    import org.kuali.kfs.coa.businessobject.Chart;
038    import org.kuali.rice.kim.api.identity.principal.Principal;
039    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
040    import org.kuali.rice.krad.service.KRADServiceLocator;
041    
042    import java.math.BigDecimal;
043    import java.sql.Date;
044    import java.util.HashMap;
045    import java.util.List;
046    import java.util.Map;
047    
048    /**
049     * A few methods to assist with various validation tasks.
050     */
051    public class ValidationUtils {
052    
053        /**
054         * For DepartmentalRule objects, if a work area is defined, you can not
055         * leave the department field with a wildcard. Permission for wildcarding
056         * will be checked with other methods.
057         *
058         * @param dr The DepartmentalRule to examine.
059         * @return true if valid, false otherwise.
060         */
061        public static boolean validateWorkAreaDeptWildcarding(DepartmentalRule dr) {
062            boolean ret = true;
063    
064            if (StringUtils.equals(dr.getDept(), TkConstants.WILDCARD_CHARACTER)) {
065                ret = dr.getWorkArea().equals(TkConstants.WILDCARD_LONG);
066            }
067    
068            return ret;
069        }
070    
071            /**
072             * Most basic validation: Only checks for presence in the database.
073             */
074            public static boolean validateWorkArea(Long workArea) {
075                    return validateWorkArea(workArea, null);
076            }
077    
078            /**
079             * Most basic validation: Only checks for presence in the database.
080             */
081            public static boolean validateDepartment(String department) {
082                    return validateDepartment(department, null);
083            }
084    
085            /**
086             * Most basic validation: Only checks for presence in the database.
087             */
088            public static boolean validateAccrualCategory(String accrualCategory) {
089                    return validateAccrualCategory(accrualCategory, null);
090            }
091    
092    
093            public static boolean validateSalGroup(String salGroup, Date asOfDate) {
094                    boolean valid = false;
095    
096                    if (StringUtils.equals(salGroup, TkConstants.WILDCARD_CHARACTER)) {
097                            valid = true;
098                    } else if (asOfDate != null) {
099                            SalGroup sg = TkServiceLocator.getSalGroupService().getSalGroup(salGroup, asOfDate);
100                            valid = (sg != null);
101                    } else {
102                            int count = TkServiceLocator.getSalGroupService().getSalGroupCount(salGroup);
103                            valid = (count > 0);
104                    }
105    
106                    return valid;
107            }
108    
109            public static boolean validateEarnCode(String earnCode, Date asOfDate) {
110                    boolean valid = false;
111    
112                    if (asOfDate != null) {
113                            EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
114                            valid = (ec != null);
115                    } else {
116                            int count = TkServiceLocator.getEarnCodeService().getEarnCodeCount(earnCode);
117                            valid = (count > 0);
118                    }
119    
120                    return valid;
121            }
122            
123            public static boolean validateLeavePlan(String leavePlan, Date asOfDate) {
124                    boolean valid = false;
125                    
126                    if (asOfDate != null) {
127                            LeavePlan lp = TkServiceLocator.getLeavePlanService().getLeavePlan(leavePlan, asOfDate);
128                            valid = (lp != null);
129                    } else {
130                            // chen, moved the code that access db to service and dao
131                            valid = TkServiceLocator.getLeavePlanService().isValidLeavePlan(leavePlan);
132                    }
133                    
134                    return valid;
135            }
136    
137            public static boolean validateEarnCodeOfAccrualCategory(String earnCode, String accrualCategory, Date asOfDate) {
138                    boolean valid = false;
139                    
140                    if (asOfDate != null) {
141                            AccrualCategory accrualCategoryObj = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
142                            if (accrualCategoryObj != null) {
143                                    if (StringUtils.equals(earnCode, accrualCategoryObj.getEarnCode())) {
144                                            valid = true;
145                                    }
146                            }
147                    } else {
148                            Map<String, String> fieldValues = new HashMap<String, String>();
149                            fieldValues.put("earnCode", earnCode);
150                            int matches = KRADServiceLocator.getBusinessObjectService().countMatching(EarnCode.class, fieldValues);
151                            
152                            valid = matches > 0;
153                    }
154                    
155                    return valid;
156            }
157            
158            public static boolean validateAccCategory(String accrualCategory, Date asOfDate) {
159                    boolean valid = false;
160                    
161                    if (asOfDate != null) {
162                            AccrualCategory ac = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
163                            valid = (ac != null);
164                    } else {
165                            Map<String, String> fieldValues = new HashMap<String, String>();
166                            fieldValues.put("accrualCategory", accrualCategory);
167                            int matches = KRADServiceLocator.getBusinessObjectService().countMatching(AccrualCategory.class, fieldValues);
168                            
169                            valid = matches > 0;
170                    }
171                    
172                    return valid;
173            }
174            
175            public static boolean validateAccCategory(String accrualCategory, String principalId, Date asOfDate) {
176                    boolean valid = false;
177                    
178                    if (asOfDate != null) {
179                            AccrualCategory ac = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
180                            if(ac != null && ac.getLeavePlan() != null) {
181                                    // fetch leave plan users
182                                    if(principalId != null) {
183                                            PrincipalHRAttributes principalHRAttributes = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId, asOfDate);
184                                            if(principalHRAttributes != null && principalHRAttributes.getLeavePlan() != null) {
185                                                    valid = StringUtils.equals(ac.getLeavePlan().trim(), principalHRAttributes.getLeavePlan().trim());
186                                            }
187                                    } else {
188                                            valid = true;
189                                    }
190                            } 
191                    } else {
192                            Map<String, String> fieldValues = new HashMap<String, String>();
193                            fieldValues.put("accrualCategory", accrualCategory);
194                            int matches = KRADServiceLocator.getBusinessObjectService().countMatching(AccrualCategory.class, fieldValues);
195                            
196                            valid = matches > 0;
197                    }
198                    return valid;
199            }
200            
201            public static boolean validateLocation(String location, Date asOfDate) {
202                    boolean valid = false;
203    
204                    if (asOfDate != null) {
205                            Location l = TkServiceLocator.getLocationService().getLocation(location, asOfDate);
206                            valid = (l != null);
207                    } else {
208                            int count = TkServiceLocator.getLocationService().getLocationCount(location);
209                            valid = (count > 0);
210                    }
211    
212                    return valid;
213            }
214    
215            public static boolean validatePayType(String payType, Date asOfDate) {
216                    boolean valid = false;
217    
218                    if (asOfDate != null) {
219                            PayType pt = TkServiceLocator.getPayTypeService().getPayType(payType, asOfDate);
220                            valid = (pt != null);
221                    } else {
222                            int count = TkServiceLocator.getPayTypeService().getPayTypeCount(payType);
223                            valid = (count > 0);
224                    }
225    
226                    return valid;
227            }
228    
229    
230            public static boolean validatePayGrade(String payGrade, String salGroup, Date asOfDate) {
231                    boolean valid = false;
232    
233                    if (asOfDate != null) {
234                            PayGrade pg = TkServiceLocator.getPayGradeService().getPayGrade(payGrade, salGroup, asOfDate);
235                            valid = (pg != null);
236                    } else {
237                            int count = TkServiceLocator.getPayGradeService().getPayGradeCount(payGrade);
238                            valid = (count > 0);
239                    }
240    
241                    return valid;
242            }
243    
244        /**
245         *
246         * @param earnCode
247         * @param otEarnCode If true, earn code is valid ONLY if it is an overtime earn code.
248         * @param asOfDate
249         * @return
250         */
251        public static boolean validateEarnCode(String earnCode, boolean otEarnCode, Date asOfDate) {
252            boolean valid = false;
253    
254            if (asOfDate != null) {
255                EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
256                valid = (ec != null) && (otEarnCode ? ec.getOvtEarnCode().booleanValue() : true);
257            }
258    
259            return valid;
260        }
261    
262            /**
263             * Checks for row presence of a department, and optionally whether or not
264             * it is active as of the specified date.
265             */
266            public static boolean validateDepartment(String department, Date asOfDate) {
267                    boolean valid = false;
268    
269            if (StringUtils.isEmpty(department)) {
270              // do nothing, let false be returned.
271            } else if (asOfDate != null) {
272                            Department d = TkServiceLocator.getDepartmentService().getDepartment(department, asOfDate);
273                        valid = (d != null);
274                    } else {
275                            int count = TkServiceLocator.getDepartmentService().getDepartmentCount(department);
276                            valid = (count > 0);
277                    }
278    
279                    return valid;
280            }
281    
282        public static boolean validateChart(String chart) {
283            boolean valid = false;
284    
285            if (!StringUtils.isEmpty(chart)) {
286                Object o = KRADServiceLocator.getBusinessObjectService().findBySinglePrimaryKey(Chart.class, chart);
287                valid = (o instanceof Chart);
288            }
289    
290            return valid;
291        }
292    
293            /**
294             * Checks for row presence of a work area, and optionally whether or not
295             * it is active as of the specified date.
296             */
297        public static boolean validateWorkArea(Long workArea, Date asOfDate) {
298            return ValidationUtils.validateWorkArea(workArea, null, asOfDate);
299        }
300    
301            public static boolean validateWorkArea(Long workArea, String dept, Date asOfDate) {
302                    boolean valid = false;
303    
304                    if (workArea == null) {
305                            valid = false;
306                    } else if (workArea.equals(TkConstants.WILDCARD_LONG)) {
307                            valid = true;
308                    } else if (asOfDate != null) {
309                            WorkArea wa = TkServiceLocator.getWorkAreaService().getWorkArea(workArea, asOfDate);
310                if (wa != null && dept != null) {
311                    valid = StringUtils.equalsIgnoreCase(dept, wa.getDept());
312                } else {
313                                valid = (wa != null);
314                }
315                    } else {
316                // Not valid if no date is passed.
317                    }
318    
319                    return valid;
320            }
321            /**
322             * Checks for row presence of a Accrual Category, and optionally whether or not
323             * it is active as of the specified date.
324             */
325            public static boolean validateAccrualCategory(String accrualCategory, Date asOfDate) {
326                    boolean valid = false;
327    
328                    if (StringUtils.equals(accrualCategory, TkConstants.WILDCARD_CHARACTER)) {
329                            valid = true;
330                    } else if (asOfDate != null) {
331                            AccrualCategory ac = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
332                            valid = (ac != null);
333                    }
334    
335                    return valid;
336            }
337    
338            /**
339             * Checks for row presence of a principal Id, and optionally whether or not
340             * it is active as of the specified date.
341             */
342            public static boolean validatePrincipalId(String principalId) {
343                    boolean valid = false;
344                    if (principalId != null) {
345                            Principal p = KimApiServiceLocator.getIdentityService().getPrincipal(principalId);
346                        valid = (p != null);
347                    }
348                    return valid;
349            }
350    
351        /**
352         * No wildcarding is accounted for in this method.
353         * @param task Task "Long Name"
354         * @param asOfDate Can be null, if we just want to look for the general case.
355         * @return True if the task is present / valid.
356         */
357        public static boolean validateTask(Long task, Date asOfDate) {
358            boolean valid = false;
359    
360            if (task != null && asOfDate != null) {
361                Task t = TkServiceLocator.getTaskService().getTask(task, asOfDate);
362                valid = (t != null);
363            } else if (task != null) {
364                    int count = TkServiceLocator.getTaskService().getTaskCount(task);
365                valid = (count > 0);
366            }
367    
368            return valid;
369        }
370    
371        /**
372         * No wildcarding is accounted for in this method.
373         * @param earnGroup EarnCodeGroup
374         * @param asOfDate Can be null, if we just want to look for the general case.
375         * @return True if the EarnCodeGroup is present / valid.
376         */
377        public static boolean validateEarnGroup(String earnGroup, Date asOfDate) {
378            boolean valid = false;
379    
380            if (earnGroup != null && asOfDate != null) {
381                EarnCodeGroup eg = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroup(earnGroup, asOfDate);
382                valid = (eg != null);
383            } else if (earnGroup != null) {
384                    int count = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroupCount(earnGroup);
385                valid = (count > 0);
386            }
387    
388            return valid;
389        }
390        
391        /**
392         * @param earnGroup EarnCodeGroup
393         * @param asOfDate
394         * @return True if the EarnCodeGroup has overtime earn codes
395         */
396        public static boolean earnGroupHasOvertimeEarnCodes(String earnGroup, Date asOfDate) {
397             if (earnGroup != null && asOfDate != null) {
398                 EarnCodeGroup eg = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroup(earnGroup, asOfDate);
399                 if(eg != null) {
400                    for(EarnCodeGroupDefinition egd : eg.getEarnCodeGroups()) {
401                            if(egd.getEarnCode() != null) {
402                                    EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(egd.getEarnCode(), asOfDate);
403                                    if(ec != null && ec.getOvtEarnCode()) {
404                                            return true;
405                                    }
406                            }
407                    }
408                 }
409             }
410    
411            return false;
412        }
413    
414    
415            /**
416             * Checks for row presence of a pay calendar
417             */
418            public static boolean validateCalendar(String calendarName) {
419                    Map<String, String> fieldValues = new HashMap<String, String>();
420                    fieldValues.put("calendarName", calendarName);
421                    int matches = KRADServiceLocator.getBusinessObjectService().countMatching(Calendar.class, fieldValues);
422    
423            return matches > 0;
424            }
425    
426       public static boolean duplicateDeptEarnCodeExists(EarnCodeSecurity deptEarnCode) {
427               boolean valid = false;
428               int count = TkServiceLocator.getEarnCodeSecurityService().getEarnCodeSecurityCount
429                   (deptEarnCode.getDept(), deptEarnCode.getHrSalGroup(), deptEarnCode.getEarnCode(), deptEarnCode.isEmployee() ? "1" : "0",
430                           deptEarnCode.isApprover() ? "1" : "0", deptEarnCode.getLocation(), deptEarnCode.isActive() ? "Y" : "N", deptEarnCode.getEffectiveDate(), null);
431           if(count == 1) {
432               valid = true;
433               count = TkServiceLocator.getEarnCodeSecurityService().getEarnCodeSecurityCount
434                       (deptEarnCode.getDept(), deptEarnCode.getHrSalGroup(), deptEarnCode.getEarnCode(), deptEarnCode.isEmployee() ? "1" : "0",
435                               deptEarnCode.isApprover() ? "1" : "0", deptEarnCode.getLocation(), deptEarnCode.isActive() ? "Y" : "N", deptEarnCode.getEffectiveDate(), deptEarnCode.getHrEarnCodeSecurityId());
436               if(count == 1) {
437                       valid = false;
438               }
439           } else if(count > 1) {
440               valid = true;
441           }
442    
443               return valid;
444       }
445       
446        /**
447        * Checks for date not more than one year in the future from accrualDAte
448        * 
449        */
450    
451       public static boolean validateOneYearFutureDateFromAccrualDate(Date date, Date accrualDate){
452               java.util.Calendar startDate = java.util.Calendar.getInstance();
453               startDate.setTime(accrualDate);
454               startDate.add(java.util.Calendar.DATE, -1);
455               startDate.set(java.util.Calendar.SECOND, 0);
456               startDate.set(java.util.Calendar.MINUTE, 0);
457               startDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
458               java.util.Calendar endDate = java.util.Calendar.getInstance();
459               endDate.setTime(accrualDate);
460               endDate.add(java.util.Calendar.YEAR, 1); // One year after the current date
461               return date.compareTo(startDate.getTime()) * date.compareTo(endDate.getTime()) <= 0;
462       }
463       
464       
465       /**
466        * Checks for date not more than one year in the future or current date
467        * 
468        */
469    
470       public static boolean validateOneYearFutureDate(Date date){
471               java.util.Calendar startDate = java.util.Calendar.getInstance();
472               startDate.add(java.util.Calendar.DATE, -1);
473               startDate.set(java.util.Calendar.SECOND, 0);
474               startDate.set(java.util.Calendar.MINUTE, 0);
475               startDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
476               java.util.Calendar endDate = java.util.Calendar.getInstance();
477               endDate.add(java.util.Calendar.YEAR, 1); // One year after the current date
478               return date.compareTo(startDate.getTime()) * date.compareTo(endDate.getTime()) <= 0;
479       }
480       
481       /**
482        * Checks for date not more than one year in the future and does not consider past date
483        * 
484        */
485    
486       public static boolean validateOneYearFutureEffectiveDate(Date date){
487               java.util.Calendar startDate = java.util.Calendar.getInstance();
488               startDate.set(java.util.Calendar.MILLISECOND, 0);
489               startDate.set(java.util.Calendar.SECOND, 0);
490               startDate.set(java.util.Calendar.MINUTE, 0);
491               startDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
492               startDate.add(java.util.Calendar.YEAR, 1); // One year after the current date
493               return date.compareTo(startDate.getTime()) <= 0;
494       }
495       
496       /**
497        * Checks for date in the future
498        * 
499        */
500       
501       public static boolean validateFutureDate(Date date){
502               java.util.Calendar startDate = java.util.Calendar.getInstance();
503               startDate.add(java.util.Calendar.DATE, 0);
504               startDate.set(java.util.Calendar.SECOND, 0);
505               startDate.set(java.util.Calendar.MINUTE, 0);
506               startDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
507               return date.compareTo(startDate.getTime()) > 0;
508       }
509    
510            /**
511             * Checks for row presence of a pay calendar by calendar type
512             */
513            public static boolean validateCalendarByType(String calendarName, String calendarType) {
514                    Map<String, String> fieldValues = new HashMap<String, String>();
515                    fieldValues.put("calendarName", calendarName);
516                    fieldValues.put("calendarTypes", calendarType);
517                    int matches = KRADServiceLocator.getBusinessObjectService().countMatching(Calendar.class, fieldValues);
518                    
519                    return matches > 0;
520            }
521            
522            public static boolean validateRecordMethod(String recordMethod, String accrualCategory, Date asOfDate) {
523                    boolean valid = false;
524                    if (asOfDate != null) {
525                            AccrualCategory ac = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualCategory, asOfDate);
526                            if (ac != null
527                        && ac.getUnitOfTime() != null) {
528                    if (LMConstants.RECORD_METHOD.HOUR.equals(ac.getUnitOfTime())
529                            && (LMConstants.RECORD_METHOD.HOUR.equals(recordMethod))
530                                || LMConstants.RECORD_METHOD.TIME.equals(recordMethod)) {
531                        valid = true;
532                    } else {
533                        valid = StringUtils.equalsIgnoreCase(ac.getUnitOfTime(), recordMethod);
534                    }
535    
536                }
537                    }
538                    return valid;
539            }
540            
541            public static boolean validateEarnCodeFraction(String earnCode, BigDecimal amount, Date asOfDate) {
542                    boolean valid = true;
543                     EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
544                     if(ec != null && ec.getFractionalTimeAllowed() != null) {
545                             BigDecimal fracAllowed = new BigDecimal(ec.getFractionalTimeAllowed());
546                             if(amount.scale() > fracAllowed.scale()) {
547                                     valid = false;
548                             }
549                     }
550                    return valid;
551            }
552    }