View Javadoc
1   /**
2    * Copyright 2004-2014 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.kpme.core.earncode.validation;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.joda.time.DateTime;
20  import org.joda.time.LocalDate;
21  import org.kuali.kpme.core.api.accrualcategory.AccrualCategoryContract;
22  import org.kuali.kpme.core.earncode.EarnCodeBo;
23  import org.kuali.kpme.core.service.HrServiceLocator;
24  import org.kuali.kpme.core.util.HrConstants;
25  import org.kuali.kpme.core.util.ValidationUtils;
26  import org.kuali.rice.krad.maintenance.MaintenanceDocument;
27  import org.kuali.rice.krad.rules.MaintenanceDocumentRuleBase;
28  
29  @SuppressWarnings("deprecation")
30  public class EarnCodeValidation extends MaintenanceDocumentRuleBase{
31  	
32  	boolean validateRollupToEarnCode(String earnCode, LocalDate asOfDate) {
33  		boolean valid = true;
34  		if (!StringUtils.isEmpty(earnCode) && !ValidationUtils.validateEarnCode(earnCode, asOfDate)) {
35  			this.putFieldError("dataObject.rollupToEarnCode", "earncode.rollupToEarnCode.notfound", "Roll up to Earn code "
36  					+ earnCode + "'");
37  			valid = false;
38  		}
39  		return valid;
40  	}
41  	
42  	boolean validateDefaultAmountOfTime(Long defaultAmountofTime) {
43  		boolean valid = true;
44  		if ( defaultAmountofTime != null ){
45  			if (defaultAmountofTime.compareTo(24L) > 0  || defaultAmountofTime.compareTo(0L) < 0) {
46  				this.putFieldError("dataObject.defaultAmountofTime", "error.leaveCode.hours", "Default Amount of Time '"
47  						+ defaultAmountofTime + "'");
48  				valid = false;
49  			}
50  		}
51  		return valid;
52  	}
53  	
54  	boolean validateRecordMethod(String recordMethod, String accrualCategory, LocalDate asOfDate){
55  		boolean valid = true;
56  		if(recordMethod != null) {
57  			if(StringUtils.isNotEmpty(accrualCategory)) {
58  				valid = ValidationUtils.validateRecordMethod(recordMethod, accrualCategory, asOfDate);
59  				if(!valid) {
60  					this.putFieldError("dataObject.recordMethod", "earncode.recordMethod.invalid", "Record Method");
61  				}
62  			}
63  		}
64  		return valid;
65  	}
66  	
67  	boolean validateLeavePlan(EarnCodeBo earnCode) {
68  		
69  		boolean valid = true;
70  		
71  		if (StringUtils.isNotBlank(earnCode.getLeavePlan())) {
72  
73  			if (!ValidationUtils.validateLeavePlan(earnCode.getLeavePlan(), earnCode.getEffectiveLocalDate())) {
74  				this.putFieldError("dataObject.leavePlan", "error.existence", "leavePlan '"
75  						+ earnCode.getLeavePlan() + "'");
76  				valid = false;
77  				return valid;
78  			}
79  			
80  			if (earnCode.getEffectiveDate() != null && StringUtils.isNotBlank(earnCode.getAccrualCategory())) {
81  				AccrualCategoryContract myTestAccrualCategoryObj =  HrServiceLocator.getAccrualCategoryService().getAccrualCategory(earnCode.getAccrualCategory(), earnCode.getEffectiveLocalDate());
82  				if(myTestAccrualCategoryObj != null) {
83  					if (!myTestAccrualCategoryObj.getLeavePlan().equals(earnCode.getLeavePlan())) {
84  						this.putFieldError("dataObject.leavePlan", "error.leaveCode.leavePlanMismatch", myTestAccrualCategoryObj.getLeavePlan());
85  						valid = false;
86  						return valid;
87  					}
88  					earnCode.setLeavePlan(myTestAccrualCategoryObj.getLeavePlan());
89  				} 
90  			}
91  		}
92  		return valid;
93  	}
94  	
95  	@Override
96  	protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
97  
98  		EarnCodeBo earnCode = (EarnCodeBo)this.getNewDataObject();
99  		EarnCodeBo oldEarnCode = (EarnCodeBo)this.getOldDataObject();
100 
101 		if ((StringUtils.equals(oldEarnCode.getEarnCode(), HrConstants.LUNCH_EARN_CODE) 
102 				|| StringUtils.equals(oldEarnCode.getEarnCode(), HrConstants.HOLIDAY_EARN_CODE))
103 					&& !earnCode.isActive()) {
104 			this.putFieldError("dataObject.active", "earncode.inactivate.locked", earnCode
105 					.getEarnCode());
106 		}
107 		//if earn code is not designated how to record then throw error
108 		if (earnCode.getHrEarnCodeId() == null) {
109 			if (ValidationUtils.validateEarnCode(earnCode.getEarnCode(), null)) {
110 				// If there IS an earn code, ie, it is valid, we need to report
111 				// an error as earn codes must be unique.			
112 				this.putFieldError("dataObject.earnCode", "earncode.earncode.unique");
113 				return false;
114 			}
115 		}
116 		
117 		 //check if the effective date of the leave plan is prior to effective date of the earn code 
118 		 //accrual category is an optional field
119 		if(StringUtils.isNotEmpty(earnCode.getLeavePlan())){
120 			boolean valid = validateLeavePlan(earnCode);
121 			if(!valid) {
122 				return false;
123 			}
124 		}
125 		//check if the effective date of the accrual category is prior to effective date of the earn code 
126 		//accrual category is an optional field
127 		if(StringUtils.isNotEmpty(earnCode.getAccrualCategory())){
128 			if (!ValidationUtils.validateAccrualCategory(earnCode.getAccrualCategory(), earnCode.getEffectiveLocalDate())) {
129 				this.putFieldError("dataObject.accrualCategory", "earncode.accrualCategory.invalid", new String[]{earnCode.getAccrualCategory(),earnCode.getLeavePlan()});
130 				return false;
131 			}
132 		}
133 		
134 		// check if there's a newer version of the Earn Code
135 		int count = HrServiceLocator.getEarnCodeService().getNewerEarnCodeCount(earnCode.getEarnCode(), earnCode.getEffectiveLocalDate());
136 		if(count > 0) {
137 			this.putFieldError("dataObject.effectiveDate", "earncode.effectiveDate.newer.exists");
138 			return false;
139 		}
140 		
141 		// kpme-937 can not deactivate an earn code if it used in active timeblocks
142 		// kpme-2344: modularity induced changes
143 		DateTime latestEndTimestamp =  HrServiceLocator.getCalendarBlockService().getLatestEndTimestampForEarnCode(earnCode.getEarnCode(), "Time");
144 
145 		if(latestEndTimestamp != null) {
146 			LocalDate earnCodeEffectiveDate = LocalDate.fromDateFields(earnCode.getEffectiveDate());
147 			LocalDate latestEndTimestampLocalDate = latestEndTimestamp.toLocalDate();
148 			 
149 			if ( !earnCode.isActive() && earnCodeEffectiveDate.isBefore(latestEndTimestampLocalDate) ){
150 				this.putFieldError("dataObject.active", "earncode.earncode.inactivate", earnCode.getEarnCode());
151 				return false;
152 			}
153 		}
154 		
155 		if(!(this.validateDefaultAmountOfTime(earnCode.getDefaultAmountofTime()))) {
156 			return false;
157 		}
158 		
159 		if(earnCode.getRollupToEarnCode() != null && !StringUtils.isEmpty(earnCode.getRollupToEarnCode())) {
160 			if(!(this.validateRollupToEarnCode(earnCode.getRollupToEarnCode(), earnCode.getEffectiveLocalDate()))) {
161 				return false;
162 			}
163 		}
164 		
165 		if(!validateRecordMethod(earnCode.getRecordMethod(), earnCode.getAccrualCategory(), earnCode.getEffectiveLocalDate())) {
166 			return false;
167 		}
168 		
169 		// KPME-2628 leave plan is required if accrual category is provided
170 		if(!StringUtils.isBlank(earnCode.getAccrualCategory())){
171 			if (StringUtils.isBlank(earnCode.getLeavePlan())) {
172 				// earncode.leavePlan.required=Leave Plan is required if Accrual Category is provided.
173 				this.putFieldError("dataObject.leavePlan", "earncode.leavePlan.required");
174 				return false;
175 			}
176 			
177 			//	KPME-3093: If an earn code has an accrual category, Accrual Balance Action can not be None.
178 			if (StringUtils.isBlank(earnCode.getAccrualBalanceAction())
179 					|| earnCode.getAccrualBalanceAction().equals(HrConstants.ACCRUAL_BALANCE_ACTION.NONE)) {
180 				this.putFieldError("dataObject.accrualBalanceAction", "earncode.accrualBalanceAction.invalid");
181 				return false;
182 			}
183 		}
184 		
185 		return true;
186 	}
187 
188 }