001: /*
002: * Copyright 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.kra.routingform.rules;
017:
018: import java.util.ArrayList;
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.Map;
023: import java.util.TreeSet;
024:
025: import org.apache.commons.lang.StringUtils;
026: import org.kuali.core.document.Document;
027: import org.kuali.core.service.BusinessObjectService;
028: import org.kuali.core.util.GlobalVariables;
029: import org.kuali.core.util.KualiInteger;
030: import org.kuali.core.util.ObjectUtils;
031: import org.kuali.kfs.KFSPropertyConstants;
032: import org.kuali.kfs.context.SpringContext;
033: import org.kuali.kfs.service.ParameterService;
034: import org.kuali.kfs.service.impl.ParameterConstants;
035: import org.kuali.module.cg.bo.ProjectDirector;
036: import org.kuali.module.kra.KraConstants;
037: import org.kuali.module.kra.KraKeyConstants;
038: import org.kuali.module.kra.routingform.bo.RoutingFormBudget;
039: import org.kuali.module.kra.routingform.bo.RoutingFormOrganizationCreditPercent;
040: import org.kuali.module.kra.routingform.bo.RoutingFormPersonnel;
041: import org.kuali.module.kra.routingform.bo.RoutingFormProjectType;
042: import org.kuali.module.kra.routingform.bo.RoutingFormQuestion;
043: import org.kuali.module.kra.routingform.document.RoutingFormDocument;
044: import org.kuali.module.kra.util.AuditCluster;
045: import org.kuali.module.kra.util.AuditError;
046:
047: public class RoutingFormAuditRule {
048:
049: /**
050: * Runs audit mode business rule checks on a ResearchDocument.
051: *
052: * @param Document document
053: * @return boolean True if the researchDocument is valid, false otherwise.
054: */
055: public static boolean processRunAuditBusinessRules(Document document) {
056: if (!(document instanceof RoutingFormDocument)) {
057: return false;
058: }
059:
060: RoutingFormDocument routingFormDocument = (RoutingFormDocument) document;
061:
062: boolean valid = true;
063:
064: valid &= processRoutingFormMainPageAuditChecks(routingFormDocument);
065: valid &= processRoutingFormProjectDetailsAuditChecks(routingFormDocument);
066:
067: return valid;
068: }
069:
070: private static boolean processRoutingFormProjectDetailsAuditChecks(
071: RoutingFormDocument routingFormDocument) {
072: boolean valid = true;
073:
074: List<AuditError> auditErrors = new ArrayList<AuditError>();
075:
076: for (RoutingFormQuestion routingFormQuestion : routingFormDocument
077: .getRoutingFormQuestions()) {
078: if (routingFormQuestion.getYesNoIndicator() == null) {
079: valid = false;
080: }
081: }
082:
083: if (!valid) {
084: auditErrors
085: .add(new AuditError(
086: "document.projectDetails.otherProjectDetailsQuestions",
087: KraKeyConstants.AUDIT_OTHER_PROJECT_DETAILS_NOT_SELECTED,
088: "projectdetails.anchor1"));
089: GlobalVariables.getAuditErrorMap().put(
090: "projectDetailsAuditErrors",
091: new AuditCluster("Project Details", auditErrors));
092: }
093:
094: return valid;
095: }
096:
097: /**
098: * Runs audit mode business rule checks on a Main Page.
099: *
100: * @param routingFormDocument
101: * @return boolean True if the researchDocument is valid, false otherwise.
102: */
103: private static boolean processRoutingFormMainPageAuditChecks(
104: RoutingFormDocument routingFormDocument) {
105: boolean valid = true;
106: List<AuditError> hardAuditErrors = new ArrayList<AuditError>();
107: List<AuditError> softAuditErrors = new ArrayList<AuditError>();
108:
109: // Perform all validation checks for potential hard audit errors
110:
111: // Agency/Delivery Info
112: valid &= processRoutingFormMainPageAgencyDeliveryAuditChecks(
113: hardAuditErrors, routingFormDocument);
114:
115: // Personnel and Units/Orgs
116: valid &= processRoutingFormMainPagePersonnelUnitsAuditChecks(
117: hardAuditErrors, routingFormDocument);
118:
119: // Submission Details
120: valid &= processRoutingFormMainPageSubmissionDetailsAuditChecks(
121: hardAuditErrors, routingFormDocument);
122:
123: // Done, finish up
124: if (!hardAuditErrors.isEmpty()) {
125: GlobalVariables.getAuditErrorMap().put(
126: "mainPageAuditErrors",
127: new AuditCluster("Main Page", hardAuditErrors));
128: }
129:
130: // Perform all validation checks for potential soft audit errors
131:
132: // Soft audit error check
133: processRoutingFormMainPageSoftErrors(softAuditErrors,
134: routingFormDocument);
135:
136: // Done, finish soft errors
137: if (!softAuditErrors.isEmpty()) {
138: GlobalVariables.getAuditErrorMap()
139: .put(
140: "mainPageAuditErrors",
141: new AuditCluster("Main Page",
142: softAuditErrors, true));
143: }
144:
145: return valid;
146: }
147:
148: /**
149: * Runs audit mode business rule checks on a Main Page, section Agency/Delivery Info.
150: *
151: * @param auditErrors
152: * @param routingFormBudget
153: * @return
154: */
155: private static boolean processRoutingFormMainPageAgencyDeliveryAuditChecks(
156: List<AuditError> auditErrors,
157: RoutingFormDocument routingFormDocument) {
158: boolean valid = true;
159:
160: if (routingFormDocument.isRoutingFormAgencyToBeNamedIndicator()
161: || ObjectUtils.isNull(routingFormDocument
162: .getRoutingFormAgency().getAgencyNumber())) {
163: valid = false;
164: auditErrors.add(new AuditError(
165: "document.routingFormAgency.agencyNumber",
166: KraKeyConstants.AUDIT_MAIN_PAGE_AGENCY_REQUIRED,
167: "mainpage.anchor1"));
168: }
169:
170: if (ObjectUtils
171: .isNull(routingFormDocument.getRoutingFormAgency()
172: .getRoutingFormDueDateTypeCode())) {
173: valid = false;
174: auditErrors
175: .add(new AuditError(
176: "document.routingFormAgency.routingFormDueDateTypeCode",
177: KraKeyConstants.AUDIT_MAIN_PAGE_DUE_DATE_TYPE_REQUIRED,
178: "mainpage.anchor1"));
179: }
180:
181: if (ObjectUtils.isNull(routingFormDocument
182: .getRoutingFormAgency()
183: .getRoutingFormRequiredCopyText())) {
184: valid = false;
185: auditErrors
186: .add(new AuditError(
187: "document.routingFormAgency.routingFormRequiredCopyText",
188: KraKeyConstants.AUDIT_MAIN_PAGE_COPIES_REQUIRED,
189: "mainpage.anchor1"));
190: }
191:
192: if (ObjectUtils.isNull(routingFormDocument
193: .getRoutingFormAgency().getAgencyAddressDescription())) {
194: valid = false;
195: auditErrors
196: .add(new AuditError(
197: "document.routingFormAgency.agencyAddressDescription",
198: KraKeyConstants.AUDIT_MAIN_PAGE_ADDRESS_REQUIRED,
199: "mainpage.anchor1"));
200: }
201:
202: return valid;
203: }
204:
205: /**
206: * Runs audit mode business rule checks on a Main Page, section Personnel and Units/Orgs.
207: *
208: * @param auditErrors
209: * @param routingFormBudget
210: * @return
211: */
212: private static boolean processRoutingFormMainPagePersonnelUnitsAuditChecks(
213: List<AuditError> auditErrors,
214: RoutingFormDocument routingFormDocument) {
215: final String PERSON_ROLE_CODE_OTHER = SpringContext.getBean(
216: ParameterService.class).getParameterValue(
217: RoutingFormDocument.class,
218: KraConstants.PERSON_ROLE_CODE_OTHER);
219:
220: boolean valid = true;
221: int projectDirectorCount = 0;
222:
223: int i = 0;
224: for (RoutingFormPersonnel person : routingFormDocument
225: .getRoutingFormPersonnel()) {
226: if (person.isPersonToBeNamedIndicator()) {
227: valid = false;
228: auditErrors
229: .add(new AuditError(
230: "document.routingFormPersonnel[" + i
231: + "].personUniversalIdentifier",
232: KraKeyConstants.AUDIT_MAIN_PAGE_PERSON_REQUIRED,
233: "mainpage.anchor2"));
234: }
235:
236: if (person.isProjectDirector()) {
237: projectDirectorCount++;
238:
239: Map fieldValues = new HashMap();
240: fieldValues
241: .put(
242: KFSPropertyConstants.PERSON_UNIVERSAL_IDENTIFIER,
243: person.getPersonUniversalIdentifier());
244: ProjectDirector projectDirector = (ProjectDirector) SpringContext
245: .getBean(BusinessObjectService.class)
246: .findByPrimaryKey(ProjectDirector.class,
247: fieldValues);
248: if (projectDirector == null) {
249: valid = false;
250: auditErrors
251: .add(new AuditError(
252: "document.routingFormPersonnel["
253: + i
254: + "].personUniversalIdentifier",
255: KraKeyConstants.AUDIT_MAIN_PAGE_PERSON_NOT_PD,
256: "mainpage.anchor2"));
257: }
258:
259: String INVALID_STATUSES = SpringContext
260: .getBean(ParameterService.class)
261: .getParameterValue(
262: ParameterConstants.RESEARCH_ADMINISTRATION_DOCUMENT.class,
263: KraConstants.PERSONNEL_STATUSES);
264: if (ObjectUtils.isNotNull(person.getUser())
265: && person.getUser().getEmployeeStatusCode() != null
266: && StringUtils.contains(INVALID_STATUSES,
267: person.getUser()
268: .getEmployeeStatusCode())) {
269: valid = false;
270: auditErrors
271: .add(new AuditError(
272: "document.routingFormPersonnel["
273: + i
274: + "].user.personUserIdentifier",
275: KraKeyConstants.AUDIT_PERSONNEL_STATUS,
276: "mainpage.anchor2",
277: new String[] {
278: person.getUser()
279: .getPersonName(),
280: person
281: .getUser()
282: .getEmployeeStatusCode() }));
283: }
284: }
285:
286: if (ObjectUtils.isNull(person.getPersonRoleCode())) {
287: valid = false;
288: auditErrors
289: .add(new AuditError(
290: "document.routingFormPersonnel[" + i
291: + "].personRoleCode",
292: KraKeyConstants.AUDIT_MAIN_PAGE_PERSON_ROLE_CODE_REQUIRED,
293: "mainpage.anchor2"));
294: } else if (PERSON_ROLE_CODE_OTHER.equals(person
295: .getPersonRoleCode())
296: && ObjectUtils.isNull(person.getPersonRoleText())) {
297: valid = false;
298: auditErrors
299: .add(new AuditError(
300: "document.routingFormPersonnel[" + i
301: + "].personRoleText",
302: KraKeyConstants.AUDIT_MAIN_PAGE_PERSON_ROLE_TEXT_REQUIRED,
303: "mainpage.anchor2"));
304: }
305:
306: if (ObjectUtils.isNull(person
307: .getPersonFinancialAidPercent())) {
308: valid = false;
309: auditErrors
310: .add(new AuditError(
311: "document.routingFormPersonnel[" + i
312: + "].personFinancialAidPercent",
313: KraKeyConstants.AUDIT_MAIN_PAGE_PERSON_FA_REQUIRED,
314: "mainpage.anchor2"));
315: }
316:
317: if (ObjectUtils.isNull(person.getPersonCreditPercent())) {
318: valid = false;
319: auditErrors
320: .add(new AuditError(
321: "document.routingFormPersonnel[" + i
322: + "].personCreditPercent",
323: KraKeyConstants.AUDIT_MAIN_PAGE_PERSON_CREDIT_REQUIRED,
324: "mainpage.anchor2"));
325: }
326:
327: i++;
328: }
329:
330: if (projectDirectorCount == 0) {
331: valid = false;
332: auditErrors
333: .add(new AuditError(
334: "document.routingFormPersonnel.personUniversalIdentifier",
335: KraKeyConstants.AUDIT_MAIN_PAGE_PD_REQUIRED,
336: "mainpage.anchor2"));
337: } else if (projectDirectorCount > 1) {
338: valid = false;
339: auditErrors
340: .add(new AuditError(
341: "document.routingFormPersonnel.personUniversalIdentifier",
342: KraKeyConstants.AUDIT_MAIN_PAGE_ONLY_ONE_PD,
343: "mainpage.anchor2"));
344: }
345:
346: i = 0;
347: for (RoutingFormOrganizationCreditPercent org : routingFormDocument
348: .getRoutingFormOrganizationCreditPercents()) {
349: if (ObjectUtils.isNull(org
350: .getOrganizationFinancialAidPercent())) {
351: valid = false;
352: auditErrors
353: .add(new AuditError(
354: "document.routingFormOrganizationCreditPercents["
355: + i
356: + "].personFinancialAidPercent",
357: KraKeyConstants.AUDIT_MAIN_PAGE_ORG_FA_REQUIRED,
358: "mainpage.anchor2"));
359: }
360:
361: if (ObjectUtils.isNull(org.getOrganizationCreditPercent())) {
362: valid = false;
363: auditErrors
364: .add(new AuditError(
365: "document.routingFormOrganizationCreditPercents["
366: + i + "].personCreditPercent",
367: KraKeyConstants.AUDIT_MAIN_PAGE_ORG_CREDIT_REQUIRED,
368: "mainpage.anchor2"));
369: }
370:
371: i++;
372: }
373:
374: if (!new KualiInteger(100).equals(routingFormDocument
375: .getTotalFinancialAidPercent())) {
376: valid = false;
377: auditErrors
378: .add(new AuditError(
379: "document.routingFormPersonnel.personFinancialAidPercent",
380: KraKeyConstants.AUDIT_MAIN_PAGE_TOTAL_FA_PERCENT_NOT_100,
381: "mainpage.anchor2"));
382: }
383:
384: if (!new KualiInteger(100).equals(routingFormDocument
385: .getTotalCreditPercent())) {
386: valid = false;
387: auditErrors
388: .add(new AuditError(
389: "document.routingFormPersonnel.personCreditPercent",
390: KraKeyConstants.AUDIT_MAIN_PAGE_TOTAL_CREDIT_PERCENT_NOT_100,
391: "mainpage.anchor2"));
392: }
393:
394: return valid;
395: }
396:
397: /**
398: * Runs audit mode business rule checks on a Main Page, section Submission Details.
399: *
400: * @param auditErrors
401: * @param routingFormBudget
402: * @return
403: */
404: private static boolean processRoutingFormMainPageSubmissionDetailsAuditChecks(
405: List<AuditError> auditErrors,
406: RoutingFormDocument routingFormDocument) {
407: ParameterService parameterService = SpringContext
408: .getBean(ParameterService.class);
409: final String SUBMISSION_TYPE_CHANGE = parameterService
410: .getParameterValue(RoutingFormDocument.class,
411: KraConstants.SUBMISSION_TYPE_CHANGE);
412: final String PROJECT_TYPE_NEW = parameterService
413: .getParameterValue(RoutingFormDocument.class,
414: KraConstants.PROJECT_TYPE_NEW);
415: final String PROJECT_TYPE_TIME_EXTENTION = parameterService
416: .getParameterValue(RoutingFormDocument.class,
417: KraConstants.PROJECT_TYPE_TIME_EXTENTION);
418: final String PROJECT_TYPE_BUDGET_REVISION_ACTIVE = parameterService
419: .getParameterValue(
420: RoutingFormDocument.class,
421: KraConstants.PROJECT_TYPE_BUDGET_REVISION_ACTIVE);
422: final String PROJECT_TYPE_BUDGET_REVISION_PENDING = parameterService
423: .getParameterValue(
424: RoutingFormDocument.class,
425: KraConstants.PROJECT_TYPE_BUDGET_REVISION_PENDING);
426: final String PROJECT_TYPE_OTHER = parameterService
427: .getParameterValue(RoutingFormDocument.class,
428: KraConstants.PROJECT_TYPE_OTHER);
429: final String PURPOSE_RESEARCH = parameterService
430: .getParameterValue(RoutingFormDocument.class,
431: KraConstants.PURPOSE_RESEARCH);
432: final String PURPOSE_OTHER = parameterService
433: .getParameterValue(RoutingFormDocument.class,
434: KraConstants.PURPOSE_OTHER);
435:
436: boolean valid = true;
437:
438: // Submission type - Grants.gov
439: // if (ObjectUtils.isNull(routingFormDocument.getSubmissionTypeCode())) {
440: // valid = false;
441: // auditErrors.add(new AuditError("document.submissionTypeCode", KraKeyConstants.AUDIT_MAIN_PAGE_SUBMISSION_TYPE_REQUIRED,
442: // "mainpage.anchor3"));
443: // }
444: // if (SUBMISSION_TYPE_CHANGE.equals(routingFormDocument.getSubmissionTypeCode()) &&
445: // ObjectUtils.isNull(routingFormDocument.getPreviousFederalIdentifier())) {
446: // valid = false;
447: // auditErrors.add(new AuditError("document.previousFederalIdentifier",
448: // KraKeyConstants.AUDIT_MAIN_PAGE_SUBMISSION_TYPE_FEDID_REQUIRED, "mainpage.anchor3"));
449: // }
450:
451: // Project Type
452:
453: // TreeSet so that we get the natural order of projectCodes. Important because
454: // KraDevelopmentGroup.KraRoutingFormProjectTypesValid has elements in alphabetic order.
455: TreeSet<String> treeSet = new TreeSet();
456:
457: // Could do asList(projectTypes).contains but that's a bit less efficient since we need to check for quiet a few of them.
458: boolean projectTypeNew = false;
459: boolean projectTypeTimeExtention = false;
460: boolean projectTypeBudgetRevisionActive = false;
461: boolean projectTypeBudgetRevisionPending = false;
462: boolean projectTypeOther = false;
463:
464: if (routingFormDocument.getRoutingFormProjectTypes() == null
465: || routingFormDocument.getRoutingFormProjectTypes()
466: .size() == 0) {
467: valid = false;
468: auditErrors
469: .add(new AuditError(
470: "document.routingFormProjectTypes",
471: KraKeyConstants.AUDIT_MAIN_PAGE_PROJECT_TYPE_REQUIRED,
472: "mainpage.anchor3"));
473: } else if (routingFormDocument.getRoutingFormProjectTypes() != null) {
474: for (RoutingFormProjectType routingFormProjectType : routingFormDocument
475: .getRoutingFormProjectTypes()) {
476: if (routingFormProjectType
477: .isProjectTypeSelectedIndicator()) {
478: treeSet.add(routingFormProjectType
479: .getProjectTypeCode());
480: }
481:
482: if (routingFormProjectType.getProjectTypeCode().equals(
483: PROJECT_TYPE_NEW)
484: && routingFormProjectType
485: .isProjectTypeSelectedIndicator()) {
486: projectTypeNew = true;
487: } else if (routingFormProjectType.getProjectTypeCode()
488: .equals(PROJECT_TYPE_TIME_EXTENTION)
489: && routingFormProjectType
490: .isProjectTypeSelectedIndicator()) {
491: projectTypeTimeExtention = true;
492: } else if (routingFormProjectType.getProjectTypeCode()
493: .equals(PROJECT_TYPE_BUDGET_REVISION_ACTIVE)
494: && routingFormProjectType
495: .isProjectTypeSelectedIndicator()) {
496: projectTypeBudgetRevisionActive = true;
497: } else if (routingFormProjectType.getProjectTypeCode()
498: .equals(PROJECT_TYPE_BUDGET_REVISION_PENDING)
499: && routingFormProjectType
500: .isProjectTypeSelectedIndicator()) {
501: projectTypeBudgetRevisionPending = true;
502: } else if (routingFormProjectType.getProjectTypeCode()
503: .equals(PROJECT_TYPE_OTHER)
504: && routingFormProjectType
505: .isProjectTypeSelectedIndicator()) {
506: projectTypeOther = true;
507:
508: if (ObjectUtils.isNull(routingFormDocument
509: .getProjectTypeOtherDescription())) {
510: valid = false;
511: auditErrors
512: .add(new AuditError(
513: "document.projectTypeOtherDescription",
514: KraKeyConstants.AUDIT_MAIN_PAGE_PROJECT_TYPE_OTHER_REQUIRED,
515: "mainpage.anchor3"));
516: }
517: }
518: }
519:
520: // We could use .toString but rather not rely on the implementation of that.
521: String projectTypesString = "";
522: for (Iterator<String> iter = treeSet.iterator(); iter
523: .hasNext();) {
524: String projectType = iter.next();
525: projectTypesString += projectType;
526: if (iter.hasNext()) {
527: projectTypesString += "$";
528: }
529: }
530:
531: if (!SpringContext.getBean(ParameterService.class)
532: .getParameterEvaluator(RoutingFormDocument.class,
533: KraConstants.PROJECT_TYPES,
534: projectTypesString).evaluationSucceeds()) {
535: valid = false;
536: auditErrors
537: .add(new AuditError(
538: "document.routingFormProjectTypes",
539: KraKeyConstants.AUDIT_MAIN_PAGE_PROJECT_TYPE_INVALID,
540: "mainpage.anchor3"));
541: }
542: }
543:
544: if (ObjectUtils.isNotNull(routingFormDocument
545: .getRoutingFormPriorGrantNumber())
546: && projectTypeNew) {
547: valid = false;
548: auditErrors
549: .add(new AuditError(
550: "document.routingFormPriorGrantNumber",
551: KraKeyConstants.AUDIT_MAIN_PAGE_PROJECT_TYPE_NEW_AND_PRIOR_GRANT,
552: "mainpage.anchor3"));
553: }
554:
555: if (ObjectUtils.isNotNull(routingFormDocument.getGrantNumber())
556: && !(projectTypeTimeExtention
557: || projectTypeBudgetRevisionActive
558: || projectTypeBudgetRevisionPending || projectTypeOther)) {
559: valid = false;
560: auditErrors
561: .add(new AuditError(
562: "document.grantNumber",
563: KraKeyConstants.AUDIT_MAIN_PAGE_PROJECT_TYPE_SELECTION_AND_GRANT,
564: "mainpage.anchor3"));
565: }
566:
567: if (ObjectUtils.isNull(routingFormDocument
568: .getRoutingFormPurposeCode())) {
569: valid = false;
570: auditErrors.add(new AuditError(
571: "document.routingFormPurposeCode",
572: KraKeyConstants.AUDIT_MAIN_PAGE_PURPOSE_REQUIRED,
573: "mainpage.anchor3"));
574: }
575:
576: // Purpose
577: if (PURPOSE_RESEARCH.equals(routingFormDocument
578: .getRoutingFormPurposeCode())
579: && ObjectUtils.isNull(routingFormDocument
580: .getResearchTypeCode())) {
581: valid = false;
582: auditErrors
583: .add(new AuditError(
584: "document.researchTypeCode",
585: KraKeyConstants.AUDIT_MAIN_PAGE_PURPOSE_RESEARCH_TYPE_REQUIRED,
586: "mainpage.anchor3"));
587: }
588:
589: if (PURPOSE_OTHER.equals(routingFormDocument
590: .getRoutingFormPurposeCode())
591: && ObjectUtils.isNull(routingFormDocument
592: .getRoutingFormOtherPurposeDescription())) {
593: valid = false;
594: auditErrors
595: .add(new AuditError(
596: "document.routingFormOtherPurposeDescription",
597: KraKeyConstants.AUDIT_MAIN_PAGE_PURPOSE_OTHER_REQUIRED,
598: "mainpage.anchor3"));
599: }
600:
601: // Title, Lay Description, & Abstract
602: if (ObjectUtils.isNull(routingFormDocument
603: .getRoutingFormProjectTitle())) {
604: valid = false;
605: auditErrors.add(new AuditError(
606: "document.routingFormProjectTitle",
607: KraKeyConstants.AUDIT_MAIN_PAGE_TITLE_REQUIRED,
608: "mainpage.anchor3"));
609: }
610:
611: if (ObjectUtils.isNull(routingFormDocument
612: .getRoutingFormLayDescription())) {
613: valid = false;
614: auditErrors
615: .add(new AuditError(
616: "document.routingFormLayDescription",
617: KraKeyConstants.AUDIT_MAIN_PAGE_LAY_DESCRIPTION_REQUIRED,
618: "mainpage.anchor3"));
619: }
620:
621: if (ObjectUtils
622: .isNull(routingFormDocument.getProjectAbstract())) {
623: valid = false;
624: auditErrors.add(new AuditError("document.projectAbstract",
625: KraKeyConstants.AUDIT_MAIN_PAGE_ABSTRACT_REQUIRED,
626: "mainpage.anchor3"));
627: }
628:
629: // Amounts & Dates
630: if (routingFormDocument.getRoutingFormBudget() != null) {
631: valid &= processRoutingFormMainPageAmountsDateAuditChecks(
632: auditErrors, routingFormDocument);
633: }
634:
635: return valid;
636: }
637:
638: /**
639: * Runs audit mode business rule checks on a Main Page, section Amounts & Dates.
640: *
641: * @param auditErrors
642: * @param routingFormBudget
643: * @return
644: */
645: private static boolean processRoutingFormMainPageAmountsDateAuditChecks(
646: List<AuditError> auditErrors,
647: RoutingFormDocument routingFormDocument) {
648: boolean valid = true;
649:
650: RoutingFormBudget routingFormBudget = routingFormDocument
651: .getRoutingFormBudget();
652:
653: // Required fields
654: if (ObjectUtils.isNull(routingFormBudget
655: .getRoutingFormBudgetDirectAmount())) {
656: valid = false;
657: auditErrors
658: .add(new AuditError(
659: "document.routingFormBudget.routingFormBudgetDirectAmount",
660: KraKeyConstants.AUDIT_MAIN_PAGE_DIRECT_REQUIRED,
661: "mainpage.anchor3"));
662: }
663: if (ObjectUtils.isNull(routingFormBudget
664: .getRoutingFormBudgetIndirectCostAmount())) {
665: valid = false;
666: auditErrors
667: .add(new AuditError(
668: "document.routingFormBudget.routingFormBudgetIndirectCostAmount",
669: KraKeyConstants.AUDIT_MAIN_PAGE_INDIRECT_REQUIRED,
670: "mainpage.anchor3"));
671: }
672: if (ObjectUtils.isNull(routingFormBudget
673: .getRoutingFormBudgetStartDate())) {
674: valid = false;
675: auditErrors
676: .add(new AuditError(
677: "document.routingFormBudget.routingFormBudgetStartDate",
678: KraKeyConstants.AUDIT_MAIN_PAGE_START_DATE_REQUIRED,
679: "mainpage.anchor3"));
680: }
681: if (ObjectUtils.isNull(routingFormBudget
682: .getRoutingFormBudgetEndDate())) {
683: valid = false;
684: auditErrors
685: .add(new AuditError(
686: "document.routingFormBudget.routingFormBudgetEndDate",
687: KraKeyConstants.AUDIT_MAIN_PAGE_END_DATE_REQUIRED,
688: "mainpage.anchor3"));
689: }
690:
691: if (ObjectUtils.isNull(routingFormBudget
692: .getRoutingFormBudgetTotalDirectAmount())) {
693: valid = false;
694: auditErrors
695: .add(new AuditError(
696: "document.routingFormBudget.routingFormBudgetTotalDirectAmount",
697: KraKeyConstants.AUDIT_MAIN_PAGE_TOTAL_DIRECT_REQUIRED,
698: "mainpage.anchor3"));
699: }
700: if (ObjectUtils.isNull(routingFormBudget
701: .getRoutingFormBudgetTotalIndirectCostAmount())) {
702: valid = false;
703: auditErrors
704: .add(new AuditError(
705: "document.routingFormBudget.routingFormBudgetTotalIndirectCostAmount",
706: KraKeyConstants.AUDIT_MAIN_PAGE_TOTAL_INDIRECT_REQUIRED,
707: "mainpage.anchor3"));
708: }
709: if (ObjectUtils.isNull(routingFormBudget
710: .getRoutingFormBudgetTotalStartDate())) {
711: valid = false;
712: auditErrors
713: .add(new AuditError(
714: "document.routingFormBudget.routingFormBudgetTotalStartDate",
715: KraKeyConstants.AUDIT_MAIN_PAGE_TOTAL_START_DATE_REQUIRED,
716: "mainpage.anchor3"));
717: }
718: if (ObjectUtils.isNull(routingFormBudget
719: .getRoutingFormBudgetTotalEndDate())) {
720: valid = false;
721: auditErrors
722: .add(new AuditError(
723: "document.routingFormBudget.routingFormBudgetTotalEndDate",
724: KraKeyConstants.AUDIT_MAIN_PAGE_TOTAL_END_DATE_REQUIRED,
725: "mainpage.anchor3"));
726: }
727:
728: // logic data relation on each row (not relation between the two)
729: if (routingFormBudget.getRoutingFormBudgetStartDate() != null
730: && routingFormBudget.getRoutingFormBudgetEndDate() != null
731: && routingFormBudget.getRoutingFormBudgetStartDate()
732: .compareTo(
733: routingFormBudget
734: .getRoutingFormBudgetEndDate()) >= 0) {
735: valid = false;
736: auditErrors
737: .add(new AuditError(
738: "document.routingFormBudget.routingFormBudgetStartDate",
739: KraKeyConstants.AUDIT_MAIN_PAGE_START_DATE_BEFORE_END_DATE,
740: "mainpage.anchor3"));
741: }
742: if (routingFormBudget.getRoutingFormBudgetTotalStartDate() != null
743: && routingFormBudget.getRoutingFormBudgetTotalEndDate() != null
744: && routingFormBudget
745: .getRoutingFormBudgetTotalStartDate()
746: .compareTo(
747: routingFormBudget
748: .getRoutingFormBudgetTotalEndDate()) >= 0) {
749: valid = false;
750: auditErrors
751: .add(new AuditError(
752: "document.routingFormBudget.routingFormBudgetTotalStartDate",
753: KraKeyConstants.AUDIT_MAIN_PAGE_TOTAL_START_DATE_BEFORE_TOTAL_END_DATE,
754: "mainpage.anchor3"));
755: }
756:
757: // Current / Total row relation establishment (subset logic)
758: if (routingFormBudget.getRoutingFormBudgetDirectAmount() != null
759: && routingFormBudget
760: .getRoutingFormBudgetTotalDirectAmount() != null
761: && routingFormBudget
762: .getRoutingFormBudgetDirectAmount()
763: .isGreaterThan(
764: routingFormBudget
765: .getRoutingFormBudgetTotalDirectAmount())) {
766: valid = false;
767: auditErrors
768: .add(new AuditError(
769: "document.routingFormBudget.routingFormBudgetDirectAmount",
770: KraKeyConstants.AUDIT_MAIN_PAGE_DIRECT_GREATER_TOTAL_DIRECT,
771: "mainpage.anchor3"));
772: }
773: if (routingFormBudget.getRoutingFormBudgetIndirectCostAmount() != null
774: && routingFormBudget
775: .getRoutingFormBudgetTotalIndirectCostAmount() != null
776: && routingFormBudget
777: .getRoutingFormBudgetIndirectCostAmount()
778: .isGreaterThan(
779: routingFormBudget
780: .getRoutingFormBudgetTotalIndirectCostAmount())) {
781: valid = false;
782: auditErrors
783: .add(new AuditError(
784: "document.routingFormBudget.routingFormBudgetIndirectCostAmount",
785: KraKeyConstants.AUDIT_MAIN_PAGE_INDIRECT_GREATER_TOTAL_INDIRECT,
786: "mainpage.anchor3"));
787: }
788: if (routingFormBudget.getRoutingFormBudgetStartDate() != null
789: && routingFormBudget
790: .getRoutingFormBudgetTotalStartDate() != null
791: && routingFormBudget
792: .getRoutingFormBudgetStartDate()
793: .compareTo(
794: routingFormBudget
795: .getRoutingFormBudgetTotalStartDate()) < 0) {
796: valid = false;
797: auditErrors
798: .add(new AuditError(
799: "document.routingFormBudget.routingFormBudgetStartDate",
800: KraKeyConstants.AUDIT_MAIN_PAGE_START_DATE_GREATER_TOTAL_START_DATE,
801: "mainpage.anchor3"));
802: }
803: if (routingFormBudget.getRoutingFormBudgetEndDate() != null
804: && routingFormBudget.getRoutingFormBudgetTotalEndDate() != null
805: && routingFormBudget
806: .getRoutingFormBudgetEndDate()
807: .compareTo(
808: routingFormBudget
809: .getRoutingFormBudgetTotalEndDate()) > 0) {
810: valid = false;
811: auditErrors
812: .add(new AuditError(
813: "document.routingFormBudget.routingFormBudgetStartDate",
814: KraKeyConstants.AUDIT_MAIN_PAGE_END_DATE_LESS_TOTAL_END_DATE,
815: "mainpage.anchor3"));
816: }
817:
818: KualiInteger totalSubcontractorAmountInteger = routingFormDocument
819: .getTotalSubcontractorAmount();
820: if (routingFormBudget.getRoutingFormBudgetDirectAmount() != null
821: && routingFormBudget.getRoutingFormBudgetDirectAmount()
822: .isLessThan(totalSubcontractorAmountInteger)) {
823: valid = false;
824: auditErrors
825: .add(new AuditError(
826: "document.routingFormBudget",
827: KraKeyConstants.AUDIT_MAIN_PAGE_SUBCONTRACTOR_TOTAL_GREATER_DIRECT,
828: "mainpage.anchor3"));
829: }
830:
831: return valid;
832: }
833:
834: /**
835: * This method reviews the provided routing form document and validates it for any potential soft audit errors.
836: *
837: * @param auditErrors Collection of audit errors to be added to the routing form document as soft audit errors.
838: * @param routingFormDocument Instance of the routing form document being validated.
839: */
840: private static void processRoutingFormMainPageSoftErrors(
841: List<AuditError> auditErrors,
842: RoutingFormDocument routingFormDocument) {
843:
844: RoutingFormBudget routingFormBudget = routingFormDocument
845: .getRoutingFormBudget();
846:
847: // Amount validation checks
848: if (routingFormBudget.getRoutingFormBudgetDirectAmount() != null
849: && routingFormBudget
850: .getRoutingFormBudgetIndirectCostAmount() != null
851: && routingFormBudget
852: .getRoutingFormBudgetDirectAmount()
853: .isLessThan(
854: routingFormBudget
855: .getRoutingFormBudgetIndirectCostAmount())) {
856: auditErrors
857: .add(new AuditError(
858: "document.routingFormBudget.routingFormBudgetDirectAmount",
859: KraKeyConstants.AUDIT_MAIN_PAGE_DIRECT_LESS_INDIRECT,
860: "mainpage.anchor3"));
861: }
862:
863: if (routingFormBudget.getRoutingFormBudgetTotalDirectAmount() != null
864: && routingFormBudget
865: .getRoutingFormBudgetTotalIndirectCostAmount() != null
866: && routingFormBudget
867: .getRoutingFormBudgetTotalDirectAmount()
868: .isLessThan(
869: routingFormBudget
870: .getRoutingFormBudgetTotalIndirectCostAmount())) {
871: auditErrors
872: .add(new AuditError(
873: "document.routingFormBudget.routingFormBudgetTotalDirectAmount",
874: KraKeyConstants.AUDIT_MAIN_PAGE_TOTAL_DIRECT_LESS_TOTAL_INDIRECT,
875: "mainpage.anchor3"));
876: }
877:
878: }
879:
880: }
|