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 }