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