1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.coa.document.validation.impl;
17
18 import java.sql.Date;
19 import java.sql.Timestamp;
20 import java.util.Calendar;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.lang.time.DateUtils;
28 import org.kuali.ole.coa.businessobject.Account;
29 import org.kuali.ole.coa.businessobject.Organization;
30 import org.kuali.ole.coa.service.OrganizationService;
31 import org.kuali.ole.sys.OLEConstants;
32 import org.kuali.ole.sys.OLEKeyConstants;
33 import org.kuali.ole.sys.OLEPropertyConstants;
34 import org.kuali.ole.sys.context.SpringContext;
35 import org.kuali.ole.sys.identity.OleKimAttributes;
36 import org.kuali.rice.core.api.parameter.ParameterEvaluatorService;
37 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
38 import org.kuali.rice.kim.api.KimConstants;
39 import org.kuali.rice.kim.api.identity.Person;
40 import org.kuali.rice.kim.api.services.IdentityManagementService;
41 import org.kuali.rice.kns.document.MaintenanceDocument;
42 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
43 import org.kuali.rice.krad.util.GlobalVariables;
44 import org.kuali.rice.krad.util.ObjectUtils;
45
46
47
48
49 public class OrgRule extends MaintenanceDocumentRuleBase {
50
51 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OrgRule.class);
52
53
54 protected static OrganizationService orgService;
55
56 protected Organization oldOrg;
57 protected Organization newOrg;
58 protected boolean isHrmsOrgActivated;
59
60
61
62
63 public OrgRule() {
64 super();
65
66
67
68
69
70
71
72 if (orgService == null) {
73 orgService = SpringContext.getBean(OrganizationService.class);
74 }
75 }
76
77
78
79
80
81
82
83
84
85
86
87
88
89 @Override
90 protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) {
91
92 boolean success = true;
93
94 LOG.debug("Entering processCustomApproveDocumentBusinessRules()");
95
96
97 isHrmsOrgActivated = isHrmsOrgActivated();
98
99
100 success &= checkExistenceAndActive();
101
102 success &= checkOrgClosureRules(document);
103
104
105 success &= checkSimpleRules(document);
106
107
108
109
110
111
112
113 return success;
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128 @Override
129 protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
130
131 boolean success = true;
132
133 LOG.debug("Entering processCustomRouteDocumentBusinessRules()");
134
135
136 isHrmsOrgActivated = isHrmsOrgActivated();
137
138
139 success &= checkExistenceAndActive();
140
141
142 success &= checkSimpleRules(document);
143
144
145
146
147
148
149
150 success &= checkOrgClosureRules(document);
151
152 return success;
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167 @Override
168 protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
169
170 LOG.debug("Entering processCustomSaveDocumentBusinessRules()");
171
172
173 isHrmsOrgActivated = isHrmsOrgActivated();
174
175
176 checkExistenceAndActive();
177
178 checkOrgClosureRules(document);
179
180
181 checkSimpleRules(document);
182
183
184
185
186
187
188
189 return true;
190 }
191
192
193
194
195
196
197 protected boolean checkExistenceAndActive() {
198
199 LOG.debug("Entering checkExistenceAndActive()");
200 boolean success = true;
201
202
203 if (!newOrg.isActive()) {
204 return success;
205 }
206
207
208
209
210 return success;
211 }
212
213
214
215
216
217
218
219
220 protected boolean checkPlantAttributes() {
221
222 boolean success = true;
223
224
225
226
227
228
229 Person user = GlobalVariables.getUserSession().getPerson();
230
231
232 if (isPlantAuthorized(user) == false) {
233 return true;
234 }
235
236
237 if (!getOrgMustReportToSelf(newOrg)) {
238
239 success &= checkEmptyBOField("organizationPlantChartCode", newOrg.getOrganizationPlantChartCode(), "Organization Plant Chart of Accounts Code");
240
241
242 success &= checkEmptyBOField("organizationPlantAccountNumber", newOrg.getOrganizationPlantAccountNumber(), "Organization Plant Account Number");
243
244
245 success &= checkEmptyBOField("campusPlantChartCode", newOrg.getCampusPlantChartCode(), "Campus Plant Chart of Accounts Code");
246
247
248 success &= checkEmptyBOField("campusPlantAccountNumber", newOrg.getCampusPlantAccountNumber(), "Campus Plant Account Number");
249
250
251 success &= getDictionaryValidationService().validateReferenceExistsAndIsActive(newOrg, "organizationPlantAccount", MAINTAINABLE_ERROR_PREFIX + "organizationPlantAccountNumber", "Organization Plant Account");
252
253
254 success &= getDictionaryValidationService().validateReferenceExistsAndIsActive(newOrg, "campusPlantAccount", MAINTAINABLE_ERROR_PREFIX + "campusPlantAccountNumber", "Campus Plant Account");
255 }
256
257 return success;
258 }
259
260
261
262
263
264
265
266
267
268 protected boolean checkOrgClosureRules(MaintenanceDocument document) {
269
270 boolean success = true;
271 boolean orgBeingClosed = false;
272 boolean checkForChildObjects = true;
273
274
275 if (document.isEdit()) {
276 if (oldOrg.isActive() && !newOrg.isActive()) {
277 orgBeingClosed = true;
278 }
279 }
280
281
282 if (document.isNew()) {
283 if (!newOrg.isActive()) {
284 orgBeingClosed = true;
285
286 checkForChildObjects = false;
287 }
288 }
289
290
291 if (!orgBeingClosed) {
292 return success;
293 }
294
295
296
297
298
299 if (checkForChildObjects) {
300 List childAccounts = orgService.getActiveAccountsByOrg(newOrg.getChartOfAccountsCode(),
301 newOrg.getOrganizationCode());
302 if (childAccounts.size() > 0) {
303
304
305 StringBuffer childAccountList = new StringBuffer();
306 int count = 0;
307 String delim = "";
308 for (Iterator iter = childAccounts.iterator(); iter.hasNext();) {
309 Account account = (Account) iter.next();
310 childAccountList
311 .append(delim + account.getChartOfAccountsCode() + "-" + account.getAccountNumber());
312 count++;
313 if (count >= 1) {
314 delim = ", ";
315 }
316 if (count >= 3) {
317 break;
318 }
319 }
320 if (childAccounts.size() > count) {
321 childAccountList.append(", ... (" + (childAccounts.size() - count) + " more)");
322 }
323
324 putGlobalError(OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_OPEN_CHILD_ACCOUNTS_ON_ORG_CLOSURE,
325 childAccountList.toString());
326 success &= false;
327 }
328
329
330
331 List childOrgs = orgService.getActiveChildOrgs(newOrg.getChartOfAccountsCode(),
332 newOrg.getOrganizationCode());
333 if (childOrgs.size() > 0) {
334
335
336 StringBuffer childOrgsList = new StringBuffer();
337 int count = 0;
338 String delim = "";
339 for (Iterator iter = childOrgs.iterator(); iter.hasNext();) {
340 Organization org = (Organization) iter.next();
341 childOrgsList.append(delim + org.getChartOfAccountsCode() + "-" + org.getOrganizationCode());
342 count++;
343 if (count >= 1) {
344 delim = ", ";
345 }
346 if (count >= 3) {
347 break;
348 }
349 }
350 if (childOrgs.size() > count) {
351 childOrgsList.append(", ... (" + (childOrgs.size() - count) + " more)");
352 }
353
354 putGlobalError(OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_OPEN_CHILD_ORGS_ON_ORG_CLOSURE,
355 childOrgsList.toString());
356 success &= false;
357 }
358 }
359
360
361 if (ObjectUtils.isNull(newOrg.getOrganizationEndDate())) {
362 success &= false;
363 putFieldError("organizationEndDate", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_END_DATE_REQUIRED_ON_ORG_CLOSURE);
364 }
365 return success;
366
367 }
368
369
370
371
372
373
374
375 protected boolean checkHrmsOrgRules(MaintenanceDocument document) {
376
377 boolean success = true;
378
379
380 if (!newOrg.isActive()) {
381 return success;
382 }
383
384
385 if (!isHrmsOrgActivated) {
386 return success;
387 }
388
389
390
391
392
393
394
395
396
397 return success;
398 }
399
400
401
402
403
404
405
406 protected boolean getOrgMustReportToSelf(Organization organization) {
407 return SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(Organization.class, OLEConstants.ChartApcParms.ORG_MUST_REPORT_TO_SELF_ORG_TYPES, organization.getOrganizationTypeCode()).evaluationSucceeds();
408 }
409
410
411
412
413
414
415
416
417
418
419
420
421 protected boolean checkSimpleRules(MaintenanceDocument document) {
422
423 boolean success = true;
424 String lastReportsToChartOfAccountsCode;
425 String lastReportsToOrganizationCode;
426 boolean continueSearch;
427 Organization tempOrg;
428 Integer loopCount;
429 Integer maxLoopCount = 40;
430
431
432 if ((ObjectUtils.isNotNull(newOrg.getOrganizationBeginDate()) && (ObjectUtils.isNotNull(newOrg.getOrganizationEndDate())))) {
433
434 Date beginDate = newOrg.getOrganizationBeginDate();
435 Date endDate = newOrg.getOrganizationEndDate();
436
437 if (endDate.before(beginDate)) {
438 putFieldError("organizationEndDate", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_END_DATE_GREATER_THAN_BEGIN_DATE);
439 success &= false;
440 }
441 }
442
443
444 if ((ObjectUtils.isNotNull(newOrg.getOrganizationBeginDate()) && (document.isNew()))) {
445 Timestamp today = getDateTimeService().getCurrentTimestamp();
446 today.setTime(DateUtils.truncate(today, Calendar.DAY_OF_MONTH).getTime());
447 if (newOrg.getOrganizationBeginDate().before(today)) {
448 putFieldError("organizationBeginDate", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_STARTDATE_IN_PAST);
449 success &= false;
450 }
451 }
452
453
454
455 if (ObjectUtils.isNotNull(newOrg.getReportsToChartOfAccountsCode()) && ObjectUtils.isNotNull(newOrg.getReportsToOrganizationCode()) && ObjectUtils.isNotNull(newOrg.getChartOfAccountsCode()) && ObjectUtils.isNotNull(newOrg.getOrganizationCode())) {
456 if (!getOrgMustReportToSelf(newOrg)) {
457
458 if ((newOrg.getReportsToChartOfAccountsCode().equals(newOrg.getChartOfAccountsCode())) && (newOrg.getReportsToOrganizationCode().equals(newOrg.getOrganizationCode()))) {
459 putFieldError("reportsToOrganizationCode", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_CANNOT_BE_SAME_ORG);
460 success = false;
461 }
462 else {
463
464
465 lastReportsToChartOfAccountsCode = newOrg.getReportsToChartOfAccountsCode();
466 lastReportsToOrganizationCode = newOrg.getReportsToOrganizationCode();
467 continueSearch = true;
468 loopCount = 0;
469 do {
470 tempOrg = orgService.getByPrimaryId(lastReportsToChartOfAccountsCode, lastReportsToOrganizationCode);
471 loopCount++;
472 ;
473 if (ObjectUtils.isNull(tempOrg)) {
474 continueSearch = false;
475
476
477 if (loopCount == 1) {
478 putFieldError("reportsToOrganizationCode", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_MUST_EXIST);
479 success = false;
480 }
481 }
482 else {
483
484 if (loopCount == 1 && !tempOrg.isActive()) {
485 putFieldError("reportsToOrganizationCode", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_MUST_EXIST);
486 success = false;
487 continueSearch = false;
488 }
489 else {
490
491
492 lastReportsToChartOfAccountsCode = tempOrg.getReportsToChartOfAccountsCode();
493 lastReportsToOrganizationCode = tempOrg.getReportsToOrganizationCode();
494
495 if ((tempOrg.getReportsToChartOfAccountsCode().equals(newOrg.getChartOfAccountsCode())) && (tempOrg.getReportsToOrganizationCode().equals(newOrg.getOrganizationCode()))) {
496 putFieldError("reportsToOrganizationCode", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_CANNOT_BE_CIRCULAR_REF_TO_SAME_ORG);
497 success = false;
498 continueSearch = false;
499 }
500 }
501 }
502 if (loopCount > maxLoopCount) {
503 continueSearch = false;
504 }
505
506 if (continueSearch && SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(Organization.class, OLEConstants.ChartApcParms.ORG_MUST_REPORT_TO_SELF_ORG_TYPES, tempOrg.getOrganizationTypeCode()).evaluationSucceeds()) {
507 continueSearch = false;
508 }
509
510 } while (continueSearch == true);
511 }
512 }
513 else {
514 if (!(newOrg.getReportsToChartOfAccountsCode().equals(newOrg.getChartOfAccountsCode()) && newOrg.getReportsToOrganizationCode().equals(newOrg.getOrganizationCode()))) {
515 putFieldError("reportsToOrganizationCode", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_MUST_BE_SAME_ORG);
516 success = false;
517 }
518
519 String topLevelOrgTypeCode = SpringContext.getBean(ParameterService.class).getParameterValueAsString(Organization.class, OLEConstants.ChartApcParms.ORG_MUST_REPORT_TO_SELF_ORG_TYPES);
520 List<Organization> topLevelOrgs = orgService.getActiveOrgsByType(topLevelOrgTypeCode);
521 if (!topLevelOrgs.isEmpty()) {
522
523
524 if (!topLevelOrgs.contains(newOrg)) {
525 putFieldError("organizationTypeCode", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_ONLY_ONE_TOP_LEVEL_ORG, topLevelOrgs.get(0).getChartOfAccountsCode() + "-" + topLevelOrgs.get(0).getOrganizationCode());
526 success = false;
527 }
528 }
529 }
530 }
531
532
533 return success;
534 }
535
536
537
538
539
540
541
542
543 protected boolean checkDefaultAccountNumber(MaintenanceDocument document) {
544
545 boolean success = true;
546 boolean exemptOrganizationTypeCode = false;
547 boolean missingDefaultAccountNumber = StringUtils.isBlank(newOrg.getOrganizationDefaultAccountNumber());
548
549 if (ObjectUtils.isNotNull(newOrg.getOrganizationTypeCode())) {
550 String organizationTypeCode = newOrg.getOrganizationTypeCode();
551 if (SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(Organization.class, OLEConstants.ChartApcParms.DEFAULT_ACCOUNT_NOT_REQUIRED_ORG_TYPES, newOrg.getOrganizationTypeCode()).evaluationSucceeds()) {
552 exemptOrganizationTypeCode = true;
553 }
554 }
555
556 if (missingDefaultAccountNumber && (!exemptOrganizationTypeCode || (!document.isNew() && !document.isEdit()))) {
557 putFieldError("organizationDefaultAccountNumber", OLEKeyConstants.ERROR_DOCUMENT_ORGMAINT_DEFAULT_ACCOUNT_NUMBER_REQUIRED);
558 success &= false;
559 }
560
561 return success;
562 }
563
564
565
566
567
568
569
570
571
572
573
574 protected boolean fieldsHaveChanged(String oldValue, String newValue) {
575
576
577 if (StringUtils.isBlank(oldValue) && StringUtils.isNotBlank(newValue)) {
578 return true;
579 }
580
581
582 if (StringUtils.isNotBlank(oldValue) && StringUtils.isBlank(newValue)) {
583 return true;
584 }
585
586
587
588 if (oldValue != null && newValue != null) {
589 if (!oldValue.trim().equalsIgnoreCase(newValue.trim())) {
590 return true;
591 }
592 }
593
594
595 return false;
596 }
597
598
599
600
601
602
603 protected boolean isHrmsOrgActivated() {
604 return SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(Organization.class, OLEConstants.ChartApcParms.APC_HRMS_ACTIVE_KEY);
605 }
606
607
608
609
610
611
612
613
614 @Override
615 public void setupConvenienceObjects() {
616
617
618 oldOrg = (Organization) super.getOldBo();
619
620
621 newOrg = (Organization) super.getNewBo();
622 }
623
624
625
626
627
628
629
630 protected boolean isPlantAuthorized(Person user) {
631 String principalId = user.getPrincipalId();
632 String namespaceCode = OLEConstants.ParameterNamespaces.KNS;
633 String permissionTemplateName = KimConstants.PermissionTemplateNames.MODIFY_FIELD;
634
635 Map<String,String> roleQualifiers = new HashMap<String,String>();
636 roleQualifiers.put(OleKimAttributes.CHART_OF_ACCOUNTS_CODE, newOrg.getChartOfAccountsCode());
637
638 Map<String,String> permissionDetails = new HashMap<String,String>();
639 permissionDetails.put(KimConstants.AttributeConstants.COMPONENT_NAME, Organization.class.getSimpleName());
640 permissionDetails.put(KimConstants.AttributeConstants.PROPERTY_NAME, OLEPropertyConstants.ORGANIZATION_PLANT_CHART_CODE);
641
642 IdentityManagementService identityManagementService = SpringContext.getBean(IdentityManagementService.class);
643 Boolean isAuthorized = identityManagementService.isAuthorizedByTemplateName(principalId, namespaceCode, permissionTemplateName, permissionDetails, roleQualifiers);
644 if (!isAuthorized) {
645 if(LOG.isDebugEnabled()) {
646 LOG.debug("User '" + user.getPrincipalName() + "' has no access to the Plant Chart.");
647 }
648 return false;
649 }
650
651 permissionDetails.put(KimConstants.AttributeConstants.PROPERTY_NAME, OLEPropertyConstants.ORGANIZATION_PLANT_ACCOUNT_NUMBER);
652 isAuthorized = identityManagementService.isAuthorizedByTemplateName(principalId, namespaceCode, permissionTemplateName, permissionDetails, roleQualifiers);
653 if (!isAuthorized) {
654 if(LOG.isDebugEnabled()) {
655 LOG.debug("User '" + user.getPrincipalName() + "' has no access to the Plant account.");
656 }
657 return false;
658 }
659
660 if(LOG.isDebugEnabled()) {
661 LOG.debug("User '" + user.getPrincipalName() + "' has access to the Plant fields.");
662 }
663 return true;
664 }
665 }