001 /*
002 * Copyright 2011 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.kfs.fp.document.validation.impl;
017
018 import java.util.Arrays;
019 import java.util.List;
020
021 import org.kuali.kfs.fp.document.DisbursementVoucherConstants;
022 import org.kuali.kfs.fp.document.DisbursementVoucherDocument;
023 import org.kuali.kfs.sys.KFSKeyConstants;
024 import org.kuali.kfs.sys.document.validation.GenericValidation;
025 import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent;
026 import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants;
027 import org.kuali.rice.kew.dto.ActionRequestDTO;
028 import org.kuali.rice.kew.exception.WorkflowException;
029 import org.kuali.rice.kew.service.WorkflowInfo;
030 import org.kuali.rice.kns.bo.Note;
031 import org.kuali.rice.kns.service.DocumentService;
032 import org.kuali.rice.kns.util.GlobalVariables;
033
034 /**
035 * Validates that if a disbursement voucher had special handling turned off at the campus node, an extra note explaining that change has been added.
036 */
037 public class DisbursementVoucherCampusSpecialHandlingValidation extends GenericValidation {
038 private DisbursementVoucherDocument disbursementVoucherDocumentForValidation;
039 private DocumentService documentService;
040 private WorkflowInfo workflowInfo;
041
042 public static final String DOCUMENT_EDITOR_ROLE_NAME = "Document Editor";
043
044 /**
045 * Carries out the validation
046 * @see org.kuali.kfs.sys.document.validation.Validation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent)
047 */
048 public boolean validate(AttributedDocumentEvent event) {
049 boolean result = true;
050
051 if (isAtNodeToCheck()) {
052 final DisbursementVoucherDocument persistedDocument = getPersistedDisbursementVoucherDocument();
053 if (isSpecialHandlingChanged(persistedDocument) && !isNoteAdded()) {
054 result = false;
055 GlobalVariables.getMessageMap().putError(AccountingDocumentRuleBaseConstants.ERROR_PATH.DOCUMENT_ERROR_PREFIX+"disbVchrSpecialHandlingCode", KFSKeyConstants.ERROR_DV_CAMPUS_TURNED_OFF_SPECIAL_HANDLING_WITHOUT_EXPLANATORY_NOTE, new String[] {});
056 }
057 }
058
059 return result;
060 }
061
062 /**
063 * Determines if the DisbursementVoucherDocumentForValidation is at the Campus route node
064 * @return true if the document is at the campus route node, false otherwise
065 */
066 protected boolean isAtNodeToCheck() {
067 try {
068 List<String> currentNodes = Arrays.asList(getDisbursementVoucherDocumentForValidation().getDocumentHeader().getWorkflowDocument().getNodeNames());
069 return (!currentNodes.contains(DisbursementVoucherConstants.RouteLevelNames.PURCHASING));
070 }
071 catch (WorkflowException we) {
072 throw new RuntimeException("Workflow Exception while attempting to check route levels", we);
073 }
074 }
075
076 /**
077 * Retrieves from the persistence store the persisted version of the given document
078 * @param document the document to find the persisted version of
079 * @return the persisted version of that document
080 */
081 protected DisbursementVoucherDocument getPersistedDisbursementVoucherDocument() {
082 try {
083 return (DisbursementVoucherDocument)getDocumentService().getByDocumentHeaderId(getDisbursementVoucherDocumentForValidation().getDocumentNumber());
084 }
085 catch (WorkflowException we) {
086 throw new RuntimeException("Could not retrieve persisted version of document "+getDisbursementVoucherDocumentForValidation().getDocumentNumber()+" for Special Handling validation", we);
087 }
088 }
089
090 /**
091 * Determines if special handling was turned off from the DisbursementVoucherDocumentForValidation
092 * @param persistedDocument the persisted version of the document
093 * @return true if special handling was turned off, false otherwise
094 */
095 protected boolean isSpecialHandlingChanged(DisbursementVoucherDocument persistedDocument) {
096 return persistedDocument.isDisbVchrSpecialHandlingCode() != getDisbursementVoucherDocumentForValidation().isDisbVchrSpecialHandlingCode();
097 }
098
099 /**
100 * Determines if another note was added from the time the DisbursementVoucherDocumentForValidation was persisted
101 * @param persistedDocument the persisted version of the document
102 * @return true if an extra note was added, false otherwise
103 */
104 protected boolean isNoteAdded() {
105 boolean foundNoteByCurrentApprover = false;
106 int count = 0;
107 final int noteCount = getDisbursementVoucherDocumentForValidation().getDocumentHeader().getBoNotes().size();
108 while (!foundNoteByCurrentApprover && count < noteCount) {
109 foundNoteByCurrentApprover |= noteAddedByApproverForCurrentNode(getDisbursementVoucherDocumentForValidation().getDocumentHeader().getBoNote(count));
110 count += 1;
111 }
112 return foundNoteByCurrentApprover;
113 }
114
115 /**
116 * Determines if the given note was added by the current approver
117 * @param note the note to see added
118 * @return true if the note was added by the current approver, false otherwise
119 */
120 protected boolean noteAddedByApproverForCurrentNode(Note note) {
121 ActionRequestDTO[] actionRequests = null;
122 try {
123 actionRequests = getWorkflowInfo().getActionRequests(new Long(getDisbursementVoucherDocumentForValidation().getDocumentNumber()), getDisbursementVoucherDocumentForValidation().getDocumentHeader().getWorkflowDocument().getCurrentRouteNodeNames(), note.getAuthorUniversalIdentifier());
124 }
125 catch (NumberFormatException nfe) {
126 throw new RuntimeException("Could not convert Disbursement Voucher document number "+getDisbursementVoucherDocumentForValidation().getDocumentNumber()+" to long", nfe);
127 }
128 catch (WorkflowException we) {
129 throw new RuntimeException("D'oh! Workflow Exception!", we);
130 }
131 return actionRequests != null && actionRequests.length > 0;
132 }
133
134 /**
135 * Determines the count of notes on the given document
136 * @param dvDoc a document to find the count of notes on
137 * @return the count of notes on the document
138 */
139 protected int getNoteCount(DisbursementVoucherDocument dvDoc) {
140 return dvDoc.getDocumentHeader().getBoNotes().size();
141 }
142
143 /**
144 * Gets the disbursementVoucherDocumentForValidation attribute.
145 * @return Returns the disbursementVoucherDocumentForValidation.
146 */
147 public DisbursementVoucherDocument getDisbursementVoucherDocumentForValidation() {
148 return disbursementVoucherDocumentForValidation;
149 }
150
151 /**
152 * Sets the disbursementVoucherDocumentForValidation attribute value.
153 * @param disbursementVoucherDocumentForValidation The disbursementVoucherDocumentForValidation to set.
154 */
155 public void setDisbursementVoucherDocumentForValidation(DisbursementVoucherDocument disbursementVoucherDocumentForValidation) {
156 this.disbursementVoucherDocumentForValidation = disbursementVoucherDocumentForValidation;
157 }
158
159 /**
160 * Gets the workflowInfo attribute.
161 * @return Returns the workflowInfo.
162 */
163 public WorkflowInfo getWorkflowInfo() {
164 if (workflowInfo == null) {
165 workflowInfo = new WorkflowInfo();
166 }
167 return workflowInfo;
168 }
169
170 /**
171 * Sets the workflowInfo attribute value.
172 * @param workflowInfo The workflowInfo to set.
173 */
174 public void setWorkflowInfo(WorkflowInfo workflowInfo) {
175 this.workflowInfo = workflowInfo;
176 }
177
178 /**
179 * Gets the documentService attribute.
180 * @return Returns the documentService.
181 */
182 public DocumentService getDocumentService() {
183 return documentService;
184 }
185
186 /**
187 * Sets the documentService attribute value.
188 * @param documentService The documentService to set.
189 */
190 public void setDocumentService(DocumentService documentService) {
191 this.documentService = documentService;
192 }
193 }