View Javadoc

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