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.assignment.validation;
17  
18  import java.sql.Date;
19  import java.util.Calendar;
20  import java.util.Collection;
21  import java.util.HashMap;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import org.apache.commons.lang.StringUtils;
29  import org.apache.commons.lang.time.DateUtils;
30  import org.kuali.hr.job.Job;
31  import org.kuali.hr.time.assignment.Assignment;
32  import org.kuali.hr.time.assignment.AssignmentAccount;
33  import org.kuali.hr.time.earncode.EarnCode;
34  import org.kuali.hr.time.paytype.PayType;
35  import org.kuali.hr.time.service.base.TkServiceLocator;
36  import org.kuali.hr.time.task.Task;
37  import org.kuali.hr.time.timeblock.TimeBlock;
38  import org.kuali.hr.time.util.TKUtils;
39  import org.kuali.hr.time.util.ValidationUtils;
40  import org.kuali.kfs.coa.businessobject.Account;
41  import org.kuali.kfs.coa.businessobject.ObjectCode;
42  import org.kuali.kfs.coa.businessobject.SubObjectCode;
43  import org.kuali.rice.kns.document.MaintenanceDocument;
44  import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
45  import org.kuali.rice.krad.bo.PersistableBusinessObject;
46  import org.kuali.rice.krad.service.KRADServiceLocator;
47  import org.kuali.rice.krad.util.GlobalVariables;
48  
49  public class AssignmentRule extends MaintenanceDocumentRuleBase {
50  
51  	protected boolean validateWorkArea(Assignment assignment) {
52  		boolean valid = true;
53  		if (assignment.getWorkArea() != null) {
54  			if (!ValidationUtils.validateWorkArea(assignment.getWorkArea(),
55  					assignment.getEffectiveDate())) {
56  				this.putFieldError("workArea", "error.existence", "workArea '"
57  						+ assignment.getWorkArea() + "'");
58  				valid = false;
59  			} else {
60  				int count = TkServiceLocator.getWorkAreaService().getWorkAreaCount(assignment.getDept(), assignment.getWorkArea());
61  				valid = (count > 0);
62  				if (!valid) {
63  					this.putFieldError("workArea", "dept.workarea.invalid.sync");
64  				}
65  			}
66  		}
67  		return valid;
68  	}
69  	
70  	protected boolean validateTask(Assignment assignment) {
71  		boolean valid = true;
72  		//task by default is zero so if non zero validate against existing taskss
73  		if (assignment.getTask() != null && !assignment.getTask().equals(0L)) {
74  			Task task = TkServiceLocator.getTaskService().getTask(assignment.getTask(), assignment.getEffectiveDate());
75  			if(task != null) {
76  				if(task.getWorkArea() == null || !task.getWorkArea().equals(assignment.getWorkArea())) {
77  					this.putFieldError("task", "task.workarea.invalid.sync");
78  					valid = false;
79  				}
80  			} 
81  		}
82  		return valid;
83  	}
84  
85  	protected boolean validateDepartment(Assignment assignment) {
86  		boolean valid = true;
87  		if (assignment.getDept() != null) {
88  				int count = TkServiceLocator.getJobService().getJobCount(null, assignment.getJobNumber(), assignment.getDept());
89  				valid = (count > 0);
90  				if (!valid) {
91  					this.putFieldError("dept", "dept.jobnumber.invalid.sync");
92  				}
93  			 
94  		}
95  		return valid;
96  	}
97  
98  	protected boolean validateJob(Assignment assignment) {
99  		boolean valid = false;
100 		LOG.debug("Validating job: " + assignment.getPrincipalId() +" Job number: "+assignment.getJobNumber());
101 		Job job = TkServiceLocator.getJobService().getJob(
102 				assignment.getPrincipalId(), assignment.getJobNumber(),
103 				assignment.getEffectiveDate(), false);
104 		// Job job =
105 		// KNSServiceLocator.getBusinessObjectService().findBySinglePrimaryKey(Job.class,
106 		// assignment.getJob().getHrJobId());
107 		if (job != null) {
108 			valid = true;
109 
110 			LOG.debug("found job.");
111 		} else {
112 			this.putFieldError("jobNumber", "error.existence", "jobNumber '"
113 					+ assignment.getJobNumber() + "'");
114 		}
115 		return valid;
116 	}
117 
118 	protected boolean validatePercentagePerEarnCode(Assignment assignment) {
119 		boolean valid = true;
120 		LOG.debug("Validating PercentagePerEarnCode: ");
121 		List<AssignmentAccount> assignmentAccounts = assignment
122 				.getAssignmentAccounts();
123 		Set<String> invalidEarnCodes = null;
124 		if (assignmentAccounts != null && assignment.isActive()) {
125 			Map<String, Integer> earnCodePercent = new HashMap<String, Integer>();
126 			for (AssignmentAccount account : assignmentAccounts) {
127 				if (account.getPercent() != null && account.isActive()) {
128 					int percent = 0;
129 					if (earnCodePercent.containsKey(account.getEarnCode())) {
130 						percent = earnCodePercent.get(account.getEarnCode());
131 					}
132 					percent += account.getPercent().toBigInteger().intValue();
133 					earnCodePercent.put(account.getEarnCode(), percent);
134 				}
135 			}
136 			//Iterator<String> itr = earnCodePercent.keySet().iterator();
137             for (Map.Entry<String, Integer> entry : earnCodePercent.entrySet()) {
138 			//while (itr.hasNext()) {
139 				String earnCode = entry.getKey();
140 				if (entry.getValue() != 100) {
141 					if (invalidEarnCodes == null) {
142 						invalidEarnCodes = new HashSet<String>();
143 					}
144 					invalidEarnCodes.add(earnCode);
145 					valid = false;
146 				}
147 			}
148 			if (!valid) {
149 				int index = 0;
150 				for (AssignmentAccount account : assignmentAccounts) {
151 					if (invalidEarnCodes.contains(account.getEarnCode())) {
152 						this.putFieldError("assignmentAccounts[" + index
153 								+ "].percent", "error.percentage.earncode");
154 					}
155 					index++;
156 				}
157 			}
158 		}
159 		return valid;
160 	}
161 
162 	protected boolean validateEarnCode(AssignmentAccount assignmentAccount) {
163 		boolean valid = false;
164 		LOG.debug("Validating EarnCode: " + assignmentAccount.getEarnCode());
165 		Date date = new Date(Calendar.getInstance().getTimeInMillis());
166 		EarnCode earnCode = TkServiceLocator.getEarnCodeService().getEarnCode(
167 				assignmentAccount.getEarnCode(), date);
168 		if (earnCode != null) {
169 
170 			valid = true;
171 			LOG.debug("found earnCode.");
172 		} else {
173 			this.putGlobalError("error.existence", "earn code '"
174 					+ assignmentAccount.getEarnCode() + "'");
175 		}
176 		return valid;
177 	}
178 	
179 	protected boolean validateRegPayEarnCode(Assignment assignment) {
180 		boolean valid = false;
181 		int index = 0;
182 		LOG.debug("Validating Regular pay EarnCodes: " + assignment.getAssignmentAccounts().size());
183 		for(AssignmentAccount assignmentAccount : assignment.getAssignmentAccounts()){
184 			if(assignment.getJobNumber()!=null && assignment.getPrincipalId()!=null){
185 				Job job = TkServiceLocator.getJobService().getJob(assignment.getPrincipalId(), assignment.getJobNumber(), assignment.getEffectiveDate(), false);
186 				if(job !=null){
187 					PayType payType = TkServiceLocator.getPayTypeService().getPayType(job.getHrPayType(), assignment.getEffectiveDate());
188 					if(StringUtils.equals(assignmentAccount.getEarnCode(), payType.getRegEarnCode())){
189 						valid = true;
190 						break;
191 					}
192 					
193 				}
194 			}
195 			index++;
196 		}
197 		if(!valid) {
198 			this.putFieldError("assignmentAccounts", "earncode.regular.pay.required");
199 		}
200 		return valid;
201 	}
202 
203 	protected boolean validateAccount(AssignmentAccount assignmentAccount) {
204 		boolean valid = false;
205 		LOG.debug("Validating Account: " + assignmentAccount.getAccountNbr());
206 		Map<String, String> fields = new HashMap<String, String>();
207 		fields.put("accountNumber", assignmentAccount.getAccountNbr());
208 		Collection account = KRADServiceLocator.getBusinessObjectService()
209 				.findMatching(Account.class, fields);
210 		valid = account.size() > 0;
211 		if (!valid) {
212 			this.putGlobalError("error.existence", "Account Number '"
213 					+ assignmentAccount.getAccountNbr() + "'");
214 		}
215 		return valid;
216 	}
217 
218 	protected boolean validateObjectCode(AssignmentAccount assignmentAccount) {
219 		boolean valid = false;
220 		LOG.debug("Validating ObjectCode: "
221 				+ assignmentAccount.getFinObjectCd());
222 		Map<String, String> fields = new HashMap<String, String>();
223 		fields.put("financialObjectCode", assignmentAccount.getFinObjectCd());
224 		Collection objectCode = KRADServiceLocator.getBusinessObjectService()
225 				.findMatching(ObjectCode.class, fields);
226 		valid = objectCode.size() > 0;
227 		if (!valid) {
228 			this.putGlobalError("error.existence", "Object Code '"
229 					+ assignmentAccount.getFinObjectCd() + "'");
230 		}
231 		return valid;
232 	}
233 
234 	protected boolean validateSubObjectCode(AssignmentAccount assignmentAccount) {
235 		boolean valid = false;
236 		LOG.debug("Validating SubObjectCode: "
237 				+ assignmentAccount.getFinSubObjCd());
238 		if (assignmentAccount.getFinSubObjCd() != null) {
239 			Map<String, String> fields = new HashMap<String, String>();
240 			fields.put("financialSubObjectCode", assignmentAccount
241 					.getFinSubObjCd());
242 			Collection subObjectCode = KRADServiceLocator.getBusinessObjectService()
243 					.findMatching(SubObjectCode.class, fields);
244 			valid = subObjectCode.size() > 0;
245 			if (!valid) {
246 				this.putGlobalError("error.existence", "SubObject Code '"
247 						+ assignmentAccount.getFinSubObjCd() + "'");
248 			}
249 		} else {
250 			valid = true;
251 		}
252 		return valid;
253 	}
254 	
255 	protected boolean validateHasAccounts(Assignment assign){
256 		if(assign.getAssignmentAccounts().isEmpty()){
257 			this.putGlobalError("error.assign.must.have.one.or.more.account");
258 			return false;
259 		}
260 		return true;
261 	}
262 	
263 	protected boolean validateActiveFlag(Assignment assign){
264 		if(!assign.isActive()) {
265 			List<TimeBlock> tbList = TkServiceLocator.getTimeBlockService().getTimeBlocksForAssignment(assign);
266 			if(!tbList.isEmpty()) {
267 				Date tbEndDate = tbList.get(0).getEndDate();
268 				for(TimeBlock tb : tbList) {
269 					if(tb.getEndDate().after(tbEndDate)) {
270 						tbEndDate = tb.getEndDate();			// get the max end date
271 					}
272 				}
273 				if(tbEndDate.equals(assign.getEffectiveDate()) || tbEndDate.after(assign.getEffectiveDate())) {
274 					this.putFieldError("active", "error.assignment.timeblock.existence", tbEndDate.toString());
275 					return false;
276 				}
277 			}
278 		}
279 		return true;
280 	}
281 
282 	/**
283 	 * It looks like the method that calls this class doesn't actually care
284 	 * about the return type.
285 	 */
286 	@Override
287 	protected boolean processCustomRouteDocumentBusinessRules(
288 			MaintenanceDocument document) {
289 		boolean valid = false;
290 		LOG.debug("entering custom validation for DeptLunchRule");
291 		PersistableBusinessObject pbo = (PersistableBusinessObject) this.getNewBo();
292 		if (pbo instanceof Assignment) {
293 			Assignment assignment = (Assignment) pbo;
294 			if (assignment != null) {
295 				valid = true;
296 				valid &= this.validateWorkArea(assignment);
297 				valid &= this.validateTask(assignment);
298 				valid &= this.validateJob(assignment);
299 				valid &= this.validateDepartment(assignment);
300 				valid &= this.validatePercentagePerEarnCode(assignment);
301 				valid &= this.validateHasAccounts(assignment);
302 				valid &= this.validateActiveFlag(assignment);
303 				if(!assignment.getAssignmentAccounts().isEmpty()) {
304 					valid &= this.validateRegPayEarnCode(assignment);	
305 				}
306 			}
307 		}
308 
309 		return valid;
310 	}
311 
312 	@Override
313 	public boolean processCustomAddCollectionLineBusinessRules(
314 			MaintenanceDocument document, String collectionName,
315 			PersistableBusinessObject line) {
316 		boolean valid = false;
317 		LOG.debug("entering custom validation for DeptLunchRule");
318 		PersistableBusinessObject pbo = line;
319 		if (pbo instanceof AssignmentAccount) {
320 
321 			AssignmentAccount assignmentAccount = (AssignmentAccount) pbo;
322 			if (assignmentAccount != null) {
323 				valid = true;
324 				valid &= this.validateEarnCode(assignmentAccount);
325 				valid &= this.validateAccount(assignmentAccount);
326 				valid &= this.validateObjectCode(assignmentAccount);
327 				valid &= this.validateSubObjectCode(assignmentAccount);
328 			}
329 		}
330 		return valid;
331 	}
332 
333 }