001 /**
002 * Copyright 2004-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.hr.time.assignment.validation;
017
018 import java.sql.Date;
019 import java.util.Calendar;
020 import java.util.Collection;
021 import java.util.HashMap;
022 import java.util.HashSet;
023 import java.util.Iterator;
024 import java.util.List;
025 import java.util.Map;
026 import java.util.Set;
027
028 import org.apache.commons.lang.StringUtils;
029 import org.kuali.hr.job.Job;
030 import org.kuali.hr.time.assignment.Assignment;
031 import org.kuali.hr.time.assignment.AssignmentAccount;
032 import org.kuali.hr.time.earncode.EarnCode;
033 import org.kuali.hr.time.paytype.PayType;
034 import org.kuali.hr.time.service.base.TkServiceLocator;
035 import org.kuali.hr.time.task.Task;
036 import org.kuali.hr.time.timeblock.TimeBlock;
037 import org.kuali.hr.time.util.ValidationUtils;
038 import org.kuali.kfs.coa.businessobject.Account;
039 import org.kuali.kfs.coa.businessobject.ObjectCode;
040 import org.kuali.kfs.coa.businessobject.SubObjectCode;
041 import org.kuali.rice.kns.document.MaintenanceDocument;
042 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
043 import org.kuali.rice.krad.bo.PersistableBusinessObject;
044 import org.kuali.rice.krad.service.KRADServiceLocator;
045
046 public class AssignmentRule extends MaintenanceDocumentRuleBase {
047
048 protected boolean validateWorkArea(Assignment assignment) {
049 boolean valid = true;
050 if (assignment.getWorkArea() != null) {
051 if (!ValidationUtils.validateWorkArea(assignment.getWorkArea(),
052 assignment.getEffectiveDate())) {
053 this.putFieldError("workArea", "error.existence", "workArea '"
054 + assignment.getWorkArea() + "'");
055 valid = false;
056 } else {
057 int count = TkServiceLocator.getWorkAreaService().getWorkAreaCount(assignment.getDept(), assignment.getWorkArea());
058 valid = (count > 0);
059 if (!valid) {
060 this.putFieldError("workArea", "dept.workarea.invalid.sync");
061 }
062 }
063 }
064 return valid;
065 }
066
067 protected boolean validateTask(Assignment assignment) {
068 boolean valid = true;
069 //task by default is zero so if non zero validate against existing taskss
070 if (assignment.getTask() != null && !assignment.getTask().equals(0L)) {
071 Task task = TkServiceLocator.getTaskService().getTask(assignment.getTask(), assignment.getEffectiveDate());
072 if(task != null) {
073 if(task.getWorkArea() == null || !task.getWorkArea().equals(assignment.getWorkArea())) {
074 this.putFieldError("task", "task.workarea.invalid.sync");
075 valid = false;
076 }
077 }
078 }
079 return valid;
080 }
081
082 protected boolean validateDepartment(Assignment assignment) {
083 boolean valid = true;
084 if (assignment.getDept() != null) {
085 int count = TkServiceLocator.getJobService().getJobCount(null, assignment.getJobNumber(), assignment.getDept());
086 valid = (count > 0);
087 if (!valid) {
088 this.putFieldError("dept", "dept.jobnumber.invalid.sync");
089 }
090
091 }
092 return valid;
093 }
094
095 protected boolean validateJob(Assignment assignment) {
096 boolean valid = false;
097 LOG.debug("Validating job: " + assignment.getPrincipalId() +" Job number: "+assignment.getJobNumber());
098 Job job = TkServiceLocator.getJobService().getJob(
099 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 }