001: /*
002: * Copyright 2006-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.chart.rules;
017:
018: import java.sql.Date;
019: import java.sql.Timestamp;
020: import java.util.Calendar;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import org.apache.commons.lang.StringUtils;
025: import org.apache.commons.lang.time.DateUtils;
026: import org.kuali.core.bo.user.UniversalUser;
027: import org.kuali.core.document.MaintenanceDocument;
028: import org.kuali.core.maintenance.rules.MaintenanceDocumentRuleBase;
029: import org.kuali.core.util.GlobalVariables;
030: import org.kuali.core.util.ObjectUtils;
031: import org.kuali.kfs.KFSConstants;
032: import org.kuali.kfs.KFSKeyConstants;
033: import org.kuali.kfs.context.SpringContext;
034: import org.kuali.kfs.service.ParameterService;
035: import org.kuali.module.chart.bo.Account;
036: import org.kuali.module.chart.bo.Org;
037: import org.kuali.module.chart.service.OrganizationService;
038:
039: /**
040: *
041: * This class implements the business rules specific to the {@link Org} Maintenance Document.
042: */
043: public class OrgRule extends MaintenanceDocumentRuleBase {
044:
045: protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
046: .getLogger(OrgRule.class);
047:
048: private static OrganizationService orgService;
049:
050: private Org oldOrg;
051: private Org newOrg;
052: private boolean isHrmsOrgActivated;
053:
054: /**
055: *
056: * Constructs a OrgRule and pseudo-injects services
057: */
058: public OrgRule() {
059: super ();
060:
061: // Pseudo-inject some services.
062: //
063: // This approach is being used to make it simpler to convert the Rule classes
064: // to spring-managed with these services injected by Spring at some later date.
065: // When this happens, just remove these calls to the setters with
066: // SpringContext, and configure the bean defs for spring.
067: if (orgService == null) {
068: orgService = SpringContext
069: .getBean(OrganizationService.class);
070: }
071: }
072:
073: /**
074: * This performs the following checks on document approve:
075: * <ul>
076: * <li>{@link OrgRule#checkExistenceAndActive()}</li>
077: * <li>{@link OrgRule#checkOrgClosureRules(MaintenanceDocument)}</li>
078: * <li>{@link OrgRule#checkSimpleRules(MaintenanceDocument)}</li>
079: * <li>{@link OrgRule#checkDefaultAccountNumber(MaintenanceDocument)}</li>
080: * </ul>
081: * This rule fails on rule failure
082: * @see org.kuali.core.maintenance.rules.MaintenanceDocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.core.document.MaintenanceDocument)
083: */
084: protected boolean processCustomApproveDocumentBusinessRules(
085: MaintenanceDocument document) {
086:
087: boolean success = true;
088:
089: LOG
090: .info("Entering processCustomApproveDocumentBusinessRules()");
091:
092: // determine whether HRMS ORG is activated in this app instance
093: isHrmsOrgActivated = isHrmsOrgActivated();
094:
095: // check that all sub-objects whose keys are specified have matching objects in the db
096: success &= checkExistenceAndActive();
097:
098: success &= checkOrgClosureRules(document);
099:
100: // check that end date is greater than begin date and Reports To Chart/Org should not be same as this Chart/Org
101: success &= checkSimpleRules(document);
102:
103: // check that defaultAccount is present unless
104: // ( (orgType = U or C) and ( document is a "create new" ))
105: success &= checkDefaultAccountNumber(document);
106: return success;
107: }
108:
109: /**
110: * This performs the following checks on document route:
111: * <ul>
112: * <li>{@link OrgRule#checkExistenceAndActive()}</li>
113: * <li>{@link OrgRule#checkOrgClosureRules(MaintenanceDocument)}</li>
114: * <li>{@link OrgRule#checkSimpleRules(MaintenanceDocument)}</li>
115: * <li>{@link OrgRule#checkDefaultAccountNumber(MaintenanceDocument)}</li>
116: * </ul>
117: * This rule fails on rule failure
118: * @see org.kuali.core.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.core.document.MaintenanceDocument)
119: */
120: protected boolean processCustomRouteDocumentBusinessRules(
121: MaintenanceDocument document) {
122:
123: boolean success = true;
124:
125: LOG.info("Entering processCustomRouteDocumentBusinessRules()");
126:
127: // determine whether HRMS ORG is activated in this app instance
128: isHrmsOrgActivated = isHrmsOrgActivated();
129:
130: // check that all sub-objects whose keys are specified have matching objects in the db
131: success &= checkExistenceAndActive();
132:
133: // check that end date is greater than begin date and Reports To Chart/Org should not be same as this Chart/Org
134: success &= checkSimpleRules(document);
135:
136: // check that defaultAccount is present unless
137: // ( (orgType = U or C) and ( document is a "create new" ))
138: success &= checkDefaultAccountNumber(document);
139:
140: success &= checkOrgClosureRules(document);
141:
142: return success;
143: }
144:
145: /**
146: * This performs the following checks on document save:
147: * <ul>
148: * <li>{@link OrgRule#checkExistenceAndActive()}</li>
149: * <li>{@link OrgRule#checkOrgClosureRules(MaintenanceDocument)}</li>
150: * <li>{@link OrgRule#checkSimpleRules(MaintenanceDocument)}</li>
151: * <li>{@link OrgRule#checkDefaultAccountNumber(MaintenanceDocument)}</li>
152: * </ul>
153: * This rule does not fail on rule failure
154: * @see org.kuali.core.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.core.document.MaintenanceDocument)
155: */
156: protected boolean processCustomSaveDocumentBusinessRules(
157: MaintenanceDocument document) {
158:
159: LOG.info("Entering processCustomSaveDocumentBusinessRules()");
160:
161: // determine whether HRMS ORG is activated in this app instance
162: isHrmsOrgActivated = isHrmsOrgActivated();
163:
164: // check that all sub-objects whose keys are specified have matching objects in the db
165: checkExistenceAndActive();
166:
167: checkOrgClosureRules(document);
168:
169: // check that end date is greater than begin date and Reports To Chart/Org should not be same as this Chart/Org
170: checkSimpleRules(document);
171:
172: // check that defaultAccount is present unless
173: // ( (orgType = U or C) and ( document is a "create new" ))
174: checkDefaultAccountNumber(document);
175:
176: return true;
177: }
178:
179: /**
180: *
181: * This checks to see if the org is active
182: * @return true if the org is inactive or false otherwise
183: */
184: protected boolean checkExistenceAndActive() {
185:
186: LOG.info("Entering checkExistenceAndActive()");
187: boolean success = true;
188:
189: // shortcut out with no enforcement if this org is closed
190: if (!newOrg.isOrganizationActiveIndicator()) {
191: return success;
192: }
193:
194: success &= checkPlantAttributes();
195:
196: return success;
197: }
198:
199: /**
200: *
201: * This checks to see if a user is authorized for plant fields modification. If not then it returns true (without activating
202: * fields). If the org does not have to report to itself then it checks to see if the
203: * plant fields have been filled out correctly and fails if they haven't
204: * @return false if user can edit plant fields but they have not been filled out correctly
205: */
206: protected boolean checkPlantAttributes() {
207:
208: boolean success = true;
209:
210: /*
211: * KULCOA-1132 - exit if the user is not a member of the plant maintainer work group.
212: */
213:
214: // get user
215: UniversalUser user = GlobalVariables.getUserSession()
216: .getUniversalUser();
217:
218: // if not authroized to edit plant fields, exit with true
219: if (isPlantAuthorized(user) == false) {
220: return true;
221: }
222:
223: // relax this edit for
224: if (!getOrgMustReportToSelf(newOrg)) {
225: // require Org Plant ChartCode
226: success &= checkEmptyBOField("organizationPlantChartCode",
227: newOrg.getOrganizationPlantChartCode(),
228: "Organization Plant Chart of Accounts Code");
229:
230: // require Org Plant AccountNumber
231: success &= checkEmptyBOField(
232: "organizationPlantAccountNumber", newOrg
233: .getOrganizationPlantAccountNumber(),
234: "Organization Plant Account Number");
235:
236: // require Campus Plant ChartCode
237: success &= checkEmptyBOField("campusPlantChartCode", newOrg
238: .getCampusPlantChartCode(),
239: "Campus Plant Chart of Accounts Code");
240:
241: // require Org Plant ChartCode
242: success &= checkEmptyBOField("campusPlantAccountNumber",
243: newOrg.getCampusPlantAccountNumber(),
244: "Campus Plant Account Number");
245:
246: // validate Org Plant Account
247: success &= getDictionaryValidationService()
248: .validateReferenceExistsAndIsActive(
249: newOrg,
250: "organizationPlantAccount",
251: "accountClosedIndicator",
252: true,
253: true,
254: MAINTAINABLE_ERROR_PREFIX
255: + "organizationPlantAccountNumber",
256: "Organization Plant Account");
257:
258: // validate Campus Plant Account
259: success &= getDictionaryValidationService()
260: .validateReferenceExistsAndIsActive(
261: newOrg,
262: "campusPlantAccount",
263: "accountClosedIndicator",
264: true,
265: true,
266: MAINTAINABLE_ERROR_PREFIX
267: + "campusPlantAccountNumber",
268: "Campus Plant Account");
269: }
270:
271: return success;
272: }
273:
274: /**
275: * This method enforces the business rules surrounding when an Org becomes closed/inactive.
276: * If we are editing and switching the org to inactive or if it is a new doc and it is marked as inactive
277: * then we assume we are closing the org. If we are not then we return true. If we are then we
278: * return false if there are still active accounts tied to the org
279: *
280: * @param document
281: * @return false if trying to close org but it still has accounts that are active linked to it
282: */
283: protected boolean checkOrgClosureRules(MaintenanceDocument document) {
284:
285: boolean success = true;
286: boolean orgBeingClosed = false;
287:
288: // if its an edit, and its being closed
289: if (document.isEdit()) {
290: if (oldOrg.isOrganizationActiveIndicator()
291: && !newOrg.isOrganizationActiveIndicator()) {
292: orgBeingClosed = true;
293: }
294: }
295:
296: // if its new, and is being created as closed
297: if (document.isNew()) {
298: if (!newOrg.isOrganizationActiveIndicator()) {
299: orgBeingClosed = true;
300: }
301: }
302:
303: // if the org isnt being closed, stop processing here
304: if (!orgBeingClosed) {
305: return success;
306: }
307:
308: // FROM HERE ON WE'RE ASSUMING THE ORG IS BEING CLOSED
309:
310: // do not allow the org to be closed while there are active accounts tied
311: // to this org
312: List childAccounts = orgService
313: .getActiveAccountsByOrg(
314: newOrg.getChartOfAccountsCode(), newOrg
315: .getOrganizationCode());
316: if (childAccounts.size() > 0) {
317:
318: // get the first three accounts on the list for display
319: StringBuffer childAccountList = new StringBuffer();
320: int count = 0;
321: String delim = "";
322: for (Iterator iter = childAccounts.iterator(); iter
323: .hasNext();) {
324: Account account = (Account) iter.next();
325: childAccountList.append(delim
326: + account.getChartOfAccountsCode() + "-"
327: + account.getAccountNumber());
328: count++;
329: if (count >= 1) {
330: delim = ", ";
331: }
332: if (count >= 3) {
333: break;
334: }
335: }
336: if (childAccounts.size() > count) {
337: childAccountList.append(", ... ("
338: + (childAccounts.size() - count) + " more)");
339: }
340:
341: putGlobalError(
342: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_OPEN_CHILD_ACCOUNTS_ON_ORG_CLOSURE,
343: childAccountList.toString());
344: success &= false;
345: }
346:
347: // do not allow this org to be closed while there are still active orgs
348: // that have this org as their reportsToOrg
349: List childOrgs = orgService
350: .getActiveChildOrgs(newOrg.getChartOfAccountsCode(),
351: newOrg.getOrganizationCode());
352: if (childOrgs.size() > 0) {
353:
354: // get the first three orgs on the list for display
355: StringBuffer childOrgsList = new StringBuffer();
356: int count = 0;
357: String delim = "";
358: for (Iterator iter = childOrgs.iterator(); iter.hasNext();) {
359: Org org = (Org) iter.next();
360: childOrgsList.append(delim
361: + org.getChartOfAccountsCode() + "-"
362: + org.getOrganizationCode());
363: count++;
364: if (count >= 1) {
365: delim = ", ";
366: }
367: if (count >= 3) {
368: break;
369: }
370: }
371: if (childOrgs.size() > count) {
372: childOrgsList.append(", ... ("
373: + (childOrgs.size() - count) + " more)");
374: }
375:
376: putGlobalError(
377: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_OPEN_CHILD_ORGS_ON_ORG_CLOSURE,
378: childOrgsList.toString());
379: success &= false;
380: }
381:
382: // if org is being closed, end-date must be valid and present
383: if (ObjectUtils.isNull(newOrg.getOrganizationEndDate())) {
384: success &= false;
385: putFieldError(
386: "organizationEndDate",
387: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_END_DATE_REQUIRED_ON_ORG_CLOSURE);
388: }
389: return success;
390:
391: }
392:
393: /**
394: * This checks to see if the org is active and if it the HRMS org is active
395: *
396: * @param document
397: * @return true if either the org is inactive or isHrmsOrgActivated is false
398: */
399: protected boolean checkHrmsOrgRules(MaintenanceDocument document) {
400:
401: boolean success = true;
402:
403: // shortcut out with no enforcement if this org is closed
404: if (!newOrg.isOrganizationActiveIndicator()) {
405: return success;
406: }
407:
408: // short circuit and fail if HRMSOrg is turned off
409: if (!isHrmsOrgActivated) {
410: return success;
411: }
412:
413: // if the system has a HRMS Org record attached to this org record, then prompt the
414: // user to fill out the HRMS Org info
415:
416: // HRMS Org Campus == Org Campus
417: // HRMS Org campus code must be the same as Org campus code
418:
419: // if the
420: return success;
421: }
422:
423: /**
424: *
425: * This checks our {@link Parameter} rules to see if this org needs to report to itself
426: * @param organization
427: * @return true if it does
428: */
429: private boolean getOrgMustReportToSelf(Org organization) {
430: return SpringContext
431: .getBean(ParameterService.class)
432: .getParameterEvaluator(
433: Org.class,
434: KFSConstants.ChartApcParms.ORG_MUST_REPORT_TO_SELF_ORG_TYPES,
435: organization.getOrganizationTypeCode())
436: .evaluationSucceeds();
437: }
438:
439: /**
440: *
441: * This checks the following conditions:
442: * <ul>
443: * <li>begin date must be greater than or equal to end date</li>
444: * <li>start date must be greater than or equal to today if new Document</li>
445: * <li>Reports To Chart/Org should not be same as this Chart/Org</li>
446: * </ul>
447: * @param document
448: * @return true if it passes all the rules, false otherwise
449: */
450: protected boolean checkSimpleRules(MaintenanceDocument document) {
451:
452: boolean success = true;
453: String lastReportsToChartOfAccountsCode;
454: String lastReportsToOrganizationCode;
455: boolean continueSearch;
456: Org tempOrg;
457: Integer loopCount;
458: Integer maxLoopCount = 40;
459:
460: // begin date must be greater than or equal to end date
461: if ((ObjectUtils.isNotNull(newOrg.getOrganizationBeginDate()) && (ObjectUtils
462: .isNotNull(newOrg.getOrganizationEndDate())))) {
463:
464: Date beginDate = newOrg.getOrganizationBeginDate();
465: Date endDate = newOrg.getOrganizationEndDate();
466:
467: if (endDate.before(beginDate)) {
468: putFieldError(
469: "organizationEndDate",
470: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_END_DATE_GREATER_THAN_BEGIN_DATE);
471: success &= false;
472: }
473: }
474:
475: // start date must be greater than or equal to today if new Document
476: if ((ObjectUtils.isNotNull(newOrg.getOrganizationBeginDate()) && (document
477: .isNew()))) {
478: Timestamp today = getDateTimeService()
479: .getCurrentTimestamp();
480: today.setTime(DateUtils.truncate(today,
481: Calendar.DAY_OF_MONTH).getTime());
482: if (newOrg.getOrganizationBeginDate().before(today)) {
483: putFieldError(
484: "organizationBeginDate",
485: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_STARTDATE_IN_PAST);
486: success &= false;
487: }
488: }
489:
490: // Reports To Chart/Org should not be same as this Chart/Org
491: // However, allow special case where organization type is listed in the business rules
492: if (ObjectUtils.isNotNull(newOrg
493: .getReportsToChartOfAccountsCode())
494: && ObjectUtils.isNotNull(newOrg
495: .getReportsToOrganizationCode())
496: && ObjectUtils.isNotNull(newOrg
497: .getChartOfAccountsCode())
498: && ObjectUtils.isNotNull(newOrg.getOrganizationCode())) {
499: if (!getOrgMustReportToSelf(newOrg)) {
500:
501: if ((newOrg.getReportsToChartOfAccountsCode()
502: .equals(newOrg.getChartOfAccountsCode()))
503: && (newOrg.getReportsToOrganizationCode()
504: .equals(newOrg.getOrganizationCode()))) {
505: putFieldError(
506: "reportsToOrganizationCode",
507: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_CANNOT_BE_SAME_ORG);
508: success = false;
509: } else {
510: // Don't allow a circular reference on Reports to Chart/Org
511: // terminate the search when a top-level org is found
512: lastReportsToChartOfAccountsCode = newOrg
513: .getReportsToChartOfAccountsCode();
514: lastReportsToOrganizationCode = newOrg
515: .getReportsToOrganizationCode();
516: continueSearch = true;
517: loopCount = 0;
518: do {
519: tempOrg = orgService.getByPrimaryId(
520: lastReportsToChartOfAccountsCode,
521: lastReportsToOrganizationCode);
522: loopCount++;
523: ;
524: if (ObjectUtils.isNull(tempOrg)) {
525: continueSearch = false;
526: // if a null is returned on the first iteration, then the reports-to org does not exist
527: // fail the validation
528: if (loopCount == 1) {
529: putFieldError(
530: "reportsToOrganizationCode",
531: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_MUST_EXIST);
532: success = false;
533: }
534: } else {
535: // on the first iteration, check whether the reports-to organization is active
536: if (loopCount == 1
537: && !tempOrg
538: .isOrganizationActiveIndicator()) {
539: putFieldError(
540: "reportsToOrganizationCode",
541: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_MUST_EXIST);
542: success = false;
543: continueSearch = false;
544: } else {
545: // LOG.info("Found Org = " + lastReportsToChartOfAccountsCode + "/" +
546: // lastReportsToOrganizationCode);
547: lastReportsToChartOfAccountsCode = tempOrg
548: .getReportsToChartOfAccountsCode();
549: lastReportsToOrganizationCode = tempOrg
550: .getReportsToOrganizationCode();
551:
552: if ((tempOrg
553: .getReportsToChartOfAccountsCode()
554: .equals(newOrg
555: .getChartOfAccountsCode()))
556: && (tempOrg
557: .getReportsToOrganizationCode()
558: .equals(newOrg
559: .getOrganizationCode()))) {
560: putFieldError(
561: "reportsToOrganizationCode",
562: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_CANNOT_BE_CIRCULAR_REF_TO_SAME_ORG);
563: success = false;
564: continueSearch = false;
565: }
566: }
567: }
568: if (loopCount > maxLoopCount) {
569: continueSearch = false;
570: }
571: // stop the search if we reach an org that must report to itself
572: if (continueSearch
573: && SpringContext
574: .getBean(ParameterService.class)
575: .getParameterEvaluator(
576: Org.class,
577: KFSConstants.ChartApcParms.ORG_MUST_REPORT_TO_SELF_ORG_TYPES,
578: tempOrg
579: .getOrganizationTypeCode())
580: .evaluationSucceeds()) {
581: continueSearch = false;
582: }
583:
584: } while (continueSearch == true);
585: } // end else (checking for circular ref)
586: } else { // org must report to self (university level organization)
587: if (!(newOrg.getReportsToChartOfAccountsCode().equals(
588: newOrg.getChartOfAccountsCode()) && newOrg
589: .getReportsToOrganizationCode().equals(
590: newOrg.getOrganizationCode()))) {
591: putFieldError(
592: "reportsToOrganizationCode",
593: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_REPORTING_ORG_MUST_BE_SAME_ORG);
594: success = false;
595: }
596: // org must be the only one of that type
597: String topLevelOrgTypeCode = SpringContext
598: .getBean(ParameterService.class)
599: .getParameterValue(
600: Org.class,
601: KFSConstants.ChartApcParms.ORG_MUST_REPORT_TO_SELF_ORG_TYPES);
602: List<Org> topLevelOrgs = orgService
603: .getActiveOrgsByType(topLevelOrgTypeCode);
604: if (!topLevelOrgs.isEmpty()) {
605: // is the new org in the topLevelOrgs list? If not, then there's an error; if so, we're editing the top level
606: // org
607: if (!topLevelOrgs.contains(newOrg)) {
608: putFieldError(
609: "organizationTypeCode",
610: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_ONLY_ONE_TOP_LEVEL_ORG,
611: topLevelOrgs.get(0)
612: .getChartOfAccountsCode()
613: + "-"
614: + topLevelOrgs.get(0)
615: .getOrganizationCode());
616: success = false;
617: }
618: }
619: }
620: }
621:
622: return success;
623: }
624:
625: /**
626: *
627: * This checks that defaultAccount is present unless
628: * ( (orgType = U or C) and ( document is a "create new" or "edit" ))
629: * @param document
630: * @return false if missing default account number and it is not an exempt type code
631: */
632: protected boolean checkDefaultAccountNumber(
633: MaintenanceDocument document) {
634:
635: boolean success = true;
636: boolean missingDefaultAccountNumber;
637: boolean exemptOrganizationTypeCode = false;
638: String organizationTypeCode;
639:
640: missingDefaultAccountNumber = StringUtils.isBlank(newOrg
641: .getOrganizationDefaultAccountNumber());
642:
643: if (ObjectUtils.isNotNull(newOrg.getOrganizationTypeCode())) {
644: organizationTypeCode = newOrg.getOrganizationTypeCode();
645: if (SpringContext
646: .getBean(ParameterService.class)
647: .getParameterEvaluator(
648: Org.class,
649: KFSConstants.ChartApcParms.DEFAULT_ACCOUNT_NOT_REQUIRED_ORG_TYPES,
650: newOrg.getOrganizationTypeCode())
651: .evaluationSucceeds()) {
652: exemptOrganizationTypeCode = true;
653: }
654: }
655: if (missingDefaultAccountNumber
656: && (!exemptOrganizationTypeCode || (!document.isNew() && !document
657: .isEdit()))) {
658: putFieldError(
659: "organizationDefaultAccountNumber",
660: KFSKeyConstants.ERROR_DOCUMENT_ORGMAINT_DEFAULT_ACCOUNT_NUMBER_REQUIRED);
661: success &= false;
662: }
663: return success;
664: }
665:
666: /**
667: * This method compares an old and new value, and determines if they've changed. If the old was null/blank, and the new is not,
668: * return true. If the old had a value, and the new is null/blank, return true. If both old and new had a value, and the values
669: * are different (excluding trailing or leading whitespaces, and excluding case changes), return true. If none of the above,
670: * return false.
671: *
672: * @param oldValue - Old value to test.
673: * @param newValue - New value to test.
674: * @return true or false, based on the algorithm described above.
675: */
676: protected boolean fieldsHaveChanged(String oldValue, String newValue) {
677:
678: // if old was null/blank and new is not
679: if (StringUtils.isBlank(oldValue)
680: && StringUtils.isNotBlank(newValue)) {
681: return true;
682: }
683:
684: // if old had a value, but new is null/blank
685: if (StringUtils.isNotBlank(oldValue)
686: && StringUtils.isBlank(newValue)) {
687: return true;
688: }
689:
690: // at this point, we know that we had a value before, and we have a
691: // value now, so we need to test whether this value has changed
692: if (oldValue != null && newValue != null) {
693: if (!oldValue.trim().equalsIgnoreCase(newValue.trim())) {
694: return true;
695: }
696: }
697:
698: // if we've made it to here, then no changes have happened to the values
699: return false;
700: }
701:
702: /**
703: * This method looks up in the ParameterService whether ther HRMS Org system is turned on.
704: *
705: * @return true or false depending on the app configuration
706: */
707: protected boolean isHrmsOrgActivated() {
708: return SpringContext.getBean(ParameterService.class)
709: .getIndicatorParameter(Org.class,
710: KFSConstants.ChartApcParms.APC_HRMS_ACTIVE_KEY);
711: }
712:
713: /**
714: * This method sets the convenience objects like newOrg and oldOrg, so you have short and easy handles to the new and
715: * old objects contained in the maintenance document. It also calls the BusinessObjectBase.refresh(), which will attempt to load
716: * all sub-objects from the DB by their primary keys, if available.
717: *
718: * @param document - the maintenanceDocument being evaluated
719: */
720: public void setupConvenienceObjects() {
721:
722: // setup oldAccount convenience objects, make sure all possible sub-objects are populated
723: oldOrg = (Org) super .getOldBo();
724:
725: // setup newAccount convenience objects, make sure all possible sub-objects are populated
726: newOrg = (Org) super .getNewBo();
727: }
728:
729: /**
730: * This method tests whether the specified user is part of the group that grants authorization to the Plant fields.
731: *
732: * @param user - the user to test
733: * @return true if user is part of the group, false otherwise
734: */
735: protected boolean isPlantAuthorized(UniversalUser user) {
736:
737: // attempt to get the group name that grants access to the Plant fields
738: String allowedPlantWorkgroup = SpringContext
739: .getBean(ParameterService.class)
740: .getParameterValue(
741: Org.class,
742: KFSConstants.ChartApcParms.ORG_PLANT_WORKGROUP_PARM_NAME);
743:
744: if (user.isMember(allowedPlantWorkgroup)) {
745: LOG
746: .info("User '"
747: + user.getPersonUserIdentifier()
748: + "' is a member of the group '"
749: + allowedPlantWorkgroup
750: + "', which gives them access to the Plant fields.");
751: return true;
752: } else {
753: LOG.info("User '" + user.getPersonUserIdentifier()
754: + "' is not a member of the group '"
755: + allowedPlantWorkgroup
756: + "', so they have no access to the Plant fields.");
757: return false;
758: }
759: }
760: }
|