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 			while (itr.hasNext()) {
138 				String earnCode = itr.next();
139 				if (earnCodePercent.get(earnCode) != 100) {
140 					if (invalidEarnCodes == null) {
141 						invalidEarnCodes = new HashSet<String>();
142 					}
143 					invalidEarnCodes.add(earnCode);
144 					valid = false;
145 				}
146 			}
147 			if (!valid) {
148 				int index = 0;
149 				for (AssignmentAccount account : assignmentAccounts) {
150 					if (invalidEarnCodes.contains(account.getEarnCode())) {
151 						this.putFieldError("assignmentAccounts[" + index
152 								+ "].percent", "error.percentage.earncode");
153 					}
154 					index++;
155 				}
156 			}
157 		}
158 		return valid;
159 	}
160 
161 	protected boolean validateEarnCode(AssignmentAccount assignmentAccount) {
162 		boolean valid = false;
163 		LOG.debug("Validating EarnCode: " + assignmentAccount.getEarnCode());
164 		Date date = new Date(Calendar.getInstance().getTimeInMillis());
165 		EarnCode earnCode = TkServiceLocator.getEarnCodeService().getEarnCode(
166 				assignmentAccount.getEarnCode(), date);
167 		if (earnCode != null) {
168 
169 			valid = true;
170 			LOG.debug("found earnCode.");
171 		} else {
172 			this.putGlobalError("error.existence", "earn code '"
173 					+ assignmentAccount.getEarnCode() + "'");
174 		}
175 		return valid;
176 	}
177 	
178 	protected boolean validateRegPayEarnCode(Assignment assignment) {
179 		boolean valid = false;
180 		int index = 0;
181 		LOG.debug("Validating Regular pay EarnCodes: " + assignment.getAssignmentAccounts().size());
182 		for(AssignmentAccount assignmentAccount : assignment.getAssignmentAccounts()){
183 			if(assignment.getJobNumber()!=null && assignment.getPrincipalId()!=null){
184 				Job job = TkServiceLocator.getJobService().getJob(assignment.getPrincipalId(), assignment.getJobNumber(), assignment.getEffectiveDate(), false);
185 				if(job !=null){
186 					PayType payType = TkServiceLocator.getPayTypeService().getPayType(job.getHrPayType(), assignment.getEffectiveDate());
187 					if(StringUtils.equals(assignmentAccount.getEarnCode(), payType.getRegEarnCode())){
188 						valid = true;
189 						break;
190 					}
191 					
192 				}
193 			}
194 			index++;
195 		}
196 		if(!valid) {
197 			this.putFieldError("assignmentAccounts", "earncode.regular.pay.required");
198 		}
199 		return valid;
200 	}
201 
202 	protected boolean validateAccount(AssignmentAccount assignmentAccount) {
203 		boolean valid = false;
204 		LOG.debug("Validating Account: " + assignmentAccount.getAccountNbr());
205 		Map<String, String> fields = new HashMap<String, String>();
206 		fields.put("accountNumber", assignmentAccount.getAccountNbr());
207 		Collection account = KRADServiceLocator.getBusinessObjectService()
208 				.findMatching(Account.class, fields);
209 		valid = account.size() > 0;
210 		if (!valid) {
211 			this.putGlobalError("error.existence", "Account Number '"
212 					+ assignmentAccount.getAccountNbr() + "'");
213 		}
214 		return valid;
215 	}
216 
217 	protected boolean validateObjectCode(AssignmentAccount assignmentAccount) {
218 		boolean valid = false;
219 		LOG.debug("Validating ObjectCode: "
220 				+ assignmentAccount.getFinObjectCd());
221 		Map<String, String> fields = new HashMap<String, String>();
222 		fields.put("financialObjectCode", assignmentAccount.getFinObjectCd());
223 		Collection objectCode = KRADServiceLocator.getBusinessObjectService()
224 				.findMatching(ObjectCode.class, fields);
225 		valid = objectCode.size() > 0;
226 		if (!valid) {
227 			this.putGlobalError("error.existence", "Object Code '"
228 					+ assignmentAccount.getFinObjectCd() + "'");
229 		}
230 		return valid;
231 	}
232 
233 	protected boolean validateSubObjectCode(AssignmentAccount assignmentAccount) {
234 		boolean valid = false;
235 		LOG.debug("Validating SubObjectCode: "
236 				+ assignmentAccount.getFinSubObjCd());
237 		if (assignmentAccount.getFinSubObjCd() != null) {
238 			Map<String, String> fields = new HashMap<String, String>();
239 			fields.put("financialSubObjectCode", assignmentAccount
240 					.getFinSubObjCd());
241 			Collection subObjectCode = KRADServiceLocator.getBusinessObjectService()
242 					.findMatching(SubObjectCode.class, fields);
243 			valid = subObjectCode.size() > 0;
244 			if (!valid) {
245 				this.putGlobalError("error.existence", "SubObject Code '"
246 						+ assignmentAccount.getFinSubObjCd() + "'");
247 			}
248 		} else {
249 			valid = true;
250 		}
251 		return valid;
252 	}
253 	
254 	protected boolean validateHasAccounts(Assignment assign){
255 		if(assign.getAssignmentAccounts().isEmpty()){
256 			this.putGlobalError("error.assign.must.have.one.or.more.account");
257 			return false;
258 		}
259 		return true;
260 	}
261 	
262 	protected boolean validateActiveFlag(Assignment assign){
263 		if(!assign.isActive()) {
264 			List<TimeBlock> tbList = TkServiceLocator.getTimeBlockService().getTimeBlocksForAssignment(assign);
265 			if(!tbList.isEmpty()) {
266 				Date tbEndDate = tbList.get(0).getEndDate();
267 				for(TimeBlock tb : tbList) {
268 					if(tb.getEndDate().after(tbEndDate)) {
269 						tbEndDate = tb.getEndDate();			// get the max end date
270 					}
271 				}
272 				if(tbEndDate.equals(assign.getEffectiveDate()) || tbEndDate.after(assign.getEffectiveDate())) {
273 					this.putFieldError("active", "error.assignment.timeblock.existence", tbEndDate.toString());
274 					return false;
275 				}
276 			}
277 		}
278 		return true;
279 	}
280 
281 	/**
282 	 * It looks like the method that calls this class doesn't actually care
283 	 * about the return type.
284 	 */
285 	@Override
286 	protected boolean processCustomRouteDocumentBusinessRules(
287 			MaintenanceDocument document) {
288 		boolean valid = false;
289 		LOG.debug("entering custom validation for DeptLunchRule");
290 		PersistableBusinessObject pbo = (PersistableBusinessObject) this.getNewBo();
291 		if (pbo instanceof Assignment) {
292 			Assignment assignment = (Assignment) pbo;
293 			if (assignment != null) {
294 				valid = true;
295 				valid &= this.validateWorkArea(assignment);
296 				valid &= this.validateTask(assignment);
297 				valid &= this.validateJob(assignment);
298 				valid &= this.validateDepartment(assignment);
299 				valid &= this.validatePercentagePerEarnCode(assignment);
300 				valid &= this.validateHasAccounts(assignment);
301 				valid &= this.validateActiveFlag(assignment);
302 				if(!assignment.getAssignmentAccounts().isEmpty()) {
303 					valid &= this.validateRegPayEarnCode(assignment);	
304 				}
305 			}
306 		}
307 
308 		return valid;
309 	}
310 
311 	@Override
312 	public boolean processCustomAddCollectionLineBusinessRules(
313 			MaintenanceDocument document, String collectionName,
314 			PersistableBusinessObject line) {
315 		boolean valid = false;
316 		LOG.debug("entering custom validation for DeptLunchRule");
317 		PersistableBusinessObject pbo = line;
318 		if (pbo instanceof AssignmentAccount) {
319 
320 			AssignmentAccount assignmentAccount = (AssignmentAccount) pbo;
321 			if (assignmentAccount != null) {
322 				valid = true;
323 				valid &= this.validateEarnCode(assignmentAccount);
324 				valid &= this.validateAccount(assignmentAccount);
325 				valid &= this.validateObjectCode(assignmentAccount);
326 				valid &= this.validateSubObjectCode(assignmentAccount);
327 			}
328 		}
329 		return valid;
330 	}
331 
332 }