1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.kpme.pm.position.validation;
17
18 import java.math.BigDecimal;
19 import java.util.List;
20 import java.util.ListIterator;
21 import java.util.Set;
22
23 import org.apache.commons.collections.CollectionUtils;
24 import org.apache.commons.lang.StringUtils;
25 import org.kuali.kpme.core.api.department.Department;
26 import org.kuali.kpme.core.service.HrServiceLocator;
27 import org.kuali.kpme.core.util.HrContext;
28 import org.kuali.kpme.pm.PMConstants;
29 import org.kuali.kpme.pm.api.classification.ClassificationContract;
30 import org.kuali.kpme.pm.classification.ClassificationBo;
31 import org.kuali.kpme.pm.position.PositionBo;
32 import org.kuali.kpme.pm.position.PositionDutyBo;
33 import org.kuali.kpme.pm.position.authorization.PositionDocumentAuthorizer;
34 import org.kuali.kpme.pm.position.funding.PositionFundingBo;
35 import org.kuali.kpme.pm.positiondepartment.PositionDepartmentBo;
36 import org.kuali.kpme.pm.positionresponsibility.PositionResponsibilityBo;
37 import org.kuali.kpme.core.departmentaffiliation.DepartmentAffiliationBo;
38 import org.kuali.kpme.core.util.ValidationUtils;
39 import org.kuali.kpme.pm.service.base.PmServiceLocator;
40 import org.kuali.kpme.pm.util.PmValidationUtils;
41 import org.kuali.rice.krad.document.DocumentAuthorizer;
42 import org.kuali.rice.krad.maintenance.MaintenanceDocument;
43 import org.kuali.rice.krad.rules.MaintenanceDocumentRuleBase;
44 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
45 import org.kuali.rice.krad.util.GlobalVariables;
46
47 public class PositionValidation extends MaintenanceDocumentRuleBase {
48 @Override
49 protected boolean processCustomRouteDocumentBusinessRules(
50 MaintenanceDocument document) {
51 boolean valid = false;
52 LOG.debug("entering custom validation for Position");
53 PositionBo aPosition = (PositionBo) this.getNewDataObject();
54 PositionBo oldPosition = (PositionBo) this.getOldDataObject();
55
56 if (aPosition != null) {
57 valid = true;
58 valid &= this.canEdit(document);
59 valid &= this.validateOverviewPage(aPosition);
60 valid &= this.validateClassificationPage(aPosition);
61 valid &= this.validateDutyListPercentage(aPosition);
62 valid &= this.validateResponsibilityListPercentage(aPosition);
63 valid &= this.validatePrimaryDepartment(aPosition);
64 valid &= this.validatPrimaryDepartmentExistence(aPosition);
65 valid &= this.validateProcess(aPosition, oldPosition);
66 valid &= this.validateFundingLines(aPosition);
67 valid &= this.validateAdditionalDepartments(aPosition);
68
69 }
70 return valid;
71 }
72
73 private boolean validateAdditionalDepartments(PositionBo aPosition) {
74 List<PositionDepartmentBo> posDeptList = aPosition.getDepartmentList();
75 boolean flag = false;
76 int i=0;
77 for (PositionDepartmentBo pd : posDeptList) {
78 if(pd.getGroupKeyCode().equals(aPosition.getGroupKeyCode())){
79 if(aPosition.getEffectiveLocalDate()!=null){
80 Department department = HrServiceLocator.getDepartmentService().getDepartment(pd.getDepartment(), pd.getGroupKeyCode(), aPosition.getEffectiveLocalDate());
81 if(department == null){
82 this.putFieldError("document.newMaintainableObject.dataObject.departmentList[" + i + "].groupKeyCode", "error.existence", "Position Department '" + pd.getDepartment() + "'");
83 return false;
84 }
85 }
86 }else{
87 flag = false;
88 this.putFieldError("document.newMaintainableObject.dataObject.departmentList[" + i + "].groupKeyCode","error.existence", "Position Department '" + pd.getDepartment() + "'");
89 return flag;
90 }
91 i++;
92 }
93 return true;
94 }
95
96 protected boolean canEdit(MaintenanceDocument document) {
97 DocumentAuthorizer auth = KRADServiceLocatorWeb.getDocumentDictionaryService().getDocumentAuthorizer(document);
98 boolean valid = true;
99 if (auth != null) {
100 valid = auth.canEdit(document, GlobalVariables.getUserSession().getActualPerson());
101 }
102 if (!valid) {
103 this.putFieldError("dataObject.primaryDepartment", "error.primaryDepartment.invalid");
104 }
105 return valid;
106
107 }
108
109
110 protected boolean validateDutyListPercentage(PositionBo aPosition) {
111 if (CollectionUtils.isNotEmpty(aPosition.getDutyList())) {
112 BigDecimal sum = BigDecimal.ZERO;
113 for (PositionDutyBo aDuty : aPosition.getDutyList()) {
114 if (aDuty != null && aDuty.getPercentage() != null) {
115 sum = sum.add(aDuty.getPercentage());
116 }
117 }
118 if (sum.compareTo(new BigDecimal(100)) > 0) {
119 String[] parameters = new String[1];
120 parameters[0] = sum.toString();
121 this.putFieldError("dataObject.dutyList",
122 "duty.percentage.exceedsMaximum", parameters);
123 return false;
124 }
125 }
126 return true;
127 }
128
129 protected boolean validateResponsibilityListPercentage(PositionBo aPosition) {
130 if (CollectionUtils.isNotEmpty(aPosition.getPositionResponsibilityList())) {
131 BigDecimal sum = BigDecimal.ZERO;
132 for (PositionResponsibilityBo aResp : aPosition.getPositionResponsibilityList()) {
133 if (aResp != null && aResp.getPercentTime() != null) {
134 sum = sum.add(aResp.getPercentTime());
135 }
136 }
137 if (sum.compareTo(new BigDecimal(100)) > 0) {
138 String[] parameters = new String[1];
139 parameters[0] = sum.toString();
140 this.putFieldError("dataObject.positionResponsibilityList",
141 "responsibility.percenttime.exceedsMaximum", parameters);
142 return false;
143 }
144 }
145 return true;
146 }
147
148
149
150
151 protected boolean validateOverviewPage(PositionBo aPosition) {
152
153
154 if (aPosition.getEffectiveDate() == null
155 || StringUtils.isEmpty(aPosition.getGroupKeyCode())
156 || StringUtils.isEmpty(aPosition.getPrimaryDepartment())
157 || StringUtils.isEmpty(aPosition.getPositionClass())
158 || StringUtils.isEmpty(aPosition.getDescription())
159 || StringUtils.isEmpty(aPosition.getPositionStatus())
160 || StringUtils.isEmpty(aPosition.getAppointmentType())
161 || StringUtils.isEmpty(aPosition.getTemporary())
162 || StringUtils.isEmpty(aPosition.getContract())) {
163
164 this.putGlobalError("error.overview.fields.required");
165 return false;
166 }
167
168
169 if (!StringUtils.isEmpty(aPosition.getAppointmentType())) {
170 List <PositionDepartmentBo> depts = aPosition.getDepartmentList();
171 if (depts != null && depts.size() > 0) {
172 boolean found = false;
173 for (PositionDepartmentBo aPos : depts) {
174 if (PmValidationUtils.validatePositionAppointmentType(aPosition.getAppointmentType(), aPos.getGroupKeyCode(), aPosition.getEffectiveLocalDate())) {
175 found = true;
176 break;
177 }
178 }
179 if (!found) {
180 this.putFieldError("dataObject.appointmentType", "error.existence", "Appointment Type '" + aPosition.getAppointmentType() + "'");
181 return false;
182 }
183 }
184 }
185
186
187 if (StringUtils.equals(aPosition.getContract(), "Y")) {
188 if (StringUtils.isEmpty(aPosition.getContractType())) {
189 this.putFieldError("dataObject.contractType", "error.overview.fields.required");
190 return false;
191 } else {
192 if (!PmValidationUtils.validatePositionContractType(aPosition.getContractType(), aPosition.getInstitution()+"-"+aPosition.getLocation(), aPosition.getEffectiveLocalDate())) {
193 this.putFieldError("dataObject.contractType", "error.existence", "Contract Type '" + aPosition.getContractType() + "'");
194 return false;
195 }
196 }
197 }
198
199
200 if (aPosition.getExpectedEndDate() != null) {
201 if (StringUtils.isEmpty(aPosition.getRenewEligible())) {
202 this.putFieldError("dataObject.renewEligible", "error.overview.fields.required");
203 return false;
204 }
205 }
206
207 return true;
208 }
209
210 protected boolean validatPrimaryDepartmentExistence(PositionBo aPosition) {
211 Department dept = HrServiceLocator.getDepartmentService().getDepartment(aPosition.getPrimaryDepartment(), aPosition.getGroupKeyCode(), aPosition.getEffectiveLocalDate());
212 if (dept == null) {
213 this.putFieldError("dataObject.primaryDepartment","error.existence", "Primary Department '" + aPosition.getPrimaryDepartment() + "'");
214 return false;
215 }
216 return true;
217 }
218
219 protected boolean validateClassificationPage(PositionBo aPosition) {
220
221 if (StringUtils.isEmpty(aPosition.getPmPositionClassId())
222 || StringUtils.isEmpty(aPosition.getTenureEligible())
223 || StringUtils.isEmpty(aPosition.getBenefitsEligible())
224 || StringUtils.isEmpty(aPosition.getLeaveEligible())) {
225
226 this.putFieldError("dataObject.pmPositionClassId", "error.classication.fields.required");
227 return false;
228 }
229
230 if (StringUtils.equals(aPosition.getLeaveEligible(), "Y")) {
231 if (StringUtils.isEmpty(aPosition.getLeavePlan())) {
232 this.putFieldError("dataObject.leavePlan", "error.classication.fields.required");
233 return false;
234 }
235 }
236
237
238 ClassificationContract classification = PmServiceLocator.getClassificationService().getClassificationById(aPosition.getPmPositionClassId());
239 Set<String> groupKeyCodes = classification.getGroupKeyCodeSet();
240 if(!groupKeyCodes.contains(aPosition.getGroupKeyCode())){
241 String[] parameters = new String[2];
242 parameters[0] = classification.getPositionClass();
243 parameters[1] = aPosition.getGroupKeyCode();
244 this.putFieldError("dataObject.pmPositionClassId", "error.classication.groupkey.invalid.sync", parameters);
245 return false;
246 }
247 return true;
248 }
249
250 protected boolean validatePrimaryDepartment(PositionBo aPosition) {
251
252 if (CollectionUtils.isNotEmpty(aPosition.getDepartmentList())) {
253 for (PositionDepartmentBo aDepartment : aPosition.getDepartmentList()) {
254 if(aDepartment != null && aDepartment.getDeptAfflObj() != null) {
255 DepartmentAffiliationBo pda = (DepartmentAffiliationBo)aDepartment.getDeptAfflObj();
256 if (pda.isPrimaryIndicator()) {
257 return true;
258 }
259 }
260 }
261 }
262
263 this.putFieldError("dataObject.primaryDepartment", "error.primaryDepartment.required");
264 return false;
265 }
266
267 protected boolean validateProcess(PositionBo newPosition, PositionBo oldPosition) {
268 String process = newPosition.getProcess();
269 if (StringUtils.equals(process, PMConstants.PSTN_PROCESS_REORG)) {
270
271 if (StringUtils.equals(newPosition.getPrimaryDepartment(),oldPosition.getPrimaryDepartment())
272 && StringUtils.equals(newPosition.getReportsToPositionId(),oldPosition.getReportsToPositionId())) {
273 this.putFieldError("dataObject.primaryDepartment","error.reorganization.noChange");
274 return false;
275 }
276
277 } else if (StringUtils.equals(process,PMConstants.PSTN_PROCESS_RECLASS)) {
278 if(StringUtils.equals(newPosition.getPmPositionClassId(),oldPosition.getPmPositionClassId())) {
279 this.putFieldError("dataObject.positionClass","error.reclassification.noChange");
280 return false;
281 }
282 } else if (StringUtils.equals(process,PMConstants.PSTN_PROCESS_STATUS)) {
283 if(StringUtils.equals(newPosition.getPositionStatus(),oldPosition.getPositionStatus())) {
284 this.putFieldError("dataObject.positionStatus","error.changeStatus.noChange");
285 }
286 }
287
288 return true;
289 }
290
291 protected boolean validateFundingLines(PositionBo aPosition) {
292 boolean valid = true;
293 String prefix = "fundingList";
294 if(CollectionUtils.isNotEmpty(aPosition.getFundingList())) {
295 for (ListIterator<? extends PositionFundingBo> iterator = aPosition.getFundingList().listIterator(); iterator.hasNext(); ) {
296 int index = iterator.nextIndex();
297 PositionFundingBo pf = iterator.next();
298 valid &= validateAddFundingLine(pf, aPosition, prefix, index);
299 }
300 }
301 return valid;
302 }
303
304 protected boolean validateAddFundingLine(PositionFundingBo pf, PositionBo aPosition,String prefix, int index) {
305 boolean valid = true;
306 String propertyNamePrefix = prefix + "[" + index + "].";
307 if(StringUtils.isNotEmpty(pf.getAccount())) {
308 boolean results = ValidationUtils.validateAccount(pf.getChart(), pf.getAccount());
309 if(!results) {
310 this.putFieldError(propertyNamePrefix + "account","error.existence", "Account '" + pf.getAccount() + "'");
311 valid = false;
312 }
313 }
314 if(StringUtils.isNotEmpty(pf.getSubAccount())) {
315 boolean results = ValidationUtils.validateSubAccount(pf.getSubAccount(), pf.getAccount(), pf.getChart());
316 if(!results) {
317 this.putFieldError(propertyNamePrefix + "subAccount","error.existence", "Sub Account '" + pf.getSubAccount() + "'");
318 valid = false;
319 }
320 }
321 if(StringUtils.isNotEmpty(pf.getObjectCode())) {
322 boolean results = ValidationUtils.validateObjectCode(pf.getObjectCode(), pf.getChart(), null);
323 if(!results) {
324 this.putFieldError(propertyNamePrefix + "objectCode","error.existence", "Object Code '" + pf.getObjectCode() + "'");
325 valid = false;
326 }
327 }
328 if(StringUtils.isNotEmpty(pf.getSubObjectCode())) {
329 boolean results = ValidationUtils.validateSubObjectCode(null,
330 pf.getChart(),
331 pf.getAccount(),
332 pf.getObjectCode(),
333 pf.getSubObjectCode());
334 if(!results) {
335 this.putFieldError(propertyNamePrefix + "subObjectCode","error.existence", "Sub Object Code '" + pf.getSubObjectCode() + "'");
336 valid= false;
337 }
338 }
339 return valid;
340
341 }
342
343
344 }