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.ArrayList; 019 import java.util.List; 020 import java.util.Set; 021 022 import org.kuali.kfs.fp.document.DisbursementVoucherDocument; 023 import org.kuali.kfs.sys.KFSKeyConstants; 024 import org.kuali.kfs.sys.KFSPropertyConstants; 025 import org.kuali.kfs.sys.KfsAuthorizationConstants.DisbursementVoucherEditMode; 026 import org.kuali.kfs.sys.context.SpringContext; 027 import org.kuali.kfs.sys.document.AccountingDocument; 028 import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent; 029 import org.kuali.kfs.sys.document.validation.impl.AccountingLineGroupTotalsUnchangedValidation; 030 import org.kuali.rice.kim.bo.Person; 031 import org.kuali.rice.kns.document.authorization.TransactionalDocumentAuthorizer; 032 import org.kuali.rice.kns.document.authorization.TransactionalDocumentPresentationController; 033 import org.kuali.rice.kns.service.DocumentHelperService; 034 import org.kuali.rice.kns.util.GlobalVariables; 035 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 036 037 public class DisbursementVoucherAccountingLineTotalsValidation extends AccountingLineGroupTotalsUnchangedValidation { 038 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DisbursementVoucherAccountingLineTotalsValidation.class); 039 040 /** 041 * @see org.kuali.kfs.sys.document.validation.impl.AccountingLineGroupTotalsUnchangedValidation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent) 042 */ 043 @Override 044 public boolean validate(AttributedDocumentEvent event) { 045 if (LOG.isDebugEnabled()) { 046 LOG.debug("validate start"); 047 } 048 049 DisbursementVoucherDocument dvDocument = (DisbursementVoucherDocument) event.getDocument(); 050 051 052 Person financialSystemUser = GlobalVariables.getUserSession().getPerson(); 053 final Set<String> currentEditModes = getEditModesFromDocument(dvDocument, financialSystemUser); 054 055 // amounts can only decrease 056 List<String> candidateEditModes = this.getCandidateEditModes(); 057 if (this.hasRequiredEditMode(currentEditModes, candidateEditModes)) { 058 059 //users in foreign or wire workgroup can increase or decrease amounts because of currency conversion 060 List<String> foreignDraftAndWireTransferEditModes = this.getForeignDraftAndWireTransferEditModes(dvDocument); 061 if (!this.hasRequiredEditMode(currentEditModes, foreignDraftAndWireTransferEditModes)) { 062 DisbursementVoucherDocument persistedDocument = (DisbursementVoucherDocument) retrievePersistedDocument(dvDocument); 063 if (persistedDocument == null) { 064 handleNonExistentDocumentWhenApproving(dvDocument); 065 return true; 066 } 067 // KFSMI- 5183 068 if (persistedDocument.getDocumentHeader().getWorkflowDocument().stateIsSaved() && persistedDocument.getDisbVchrCheckTotalAmount().isZero()) return true; 069 070 // check total cannot decrease 071 if (persistedDocument.getDisbVchrCheckTotalAmount().isLessThan(dvDocument.getDisbVchrCheckTotalAmount())) { 072 GlobalVariables.getMessageMap().putError(KFSPropertyConstants.DOCUMENT + "." + KFSPropertyConstants.DISB_VCHR_CHECK_TOTAL_AMOUNT, KFSKeyConstants.ERROR_DV_CHECK_TOTAL_CHANGE); 073 return false; 074 } 075 } 076 077 return true; 078 } 079 080 return super.validate(event); 081 } 082 083 /** 084 * determine whether the give user has permission to any edit mode defined in the given candidate edit modes 085 * 086 * @param currentEditModes the edit modes currently available to the given user on the document 087 * @param candidateEditEditModes the given candidate edit modes 088 * @return true if the give user has permission to any edit mode defined in the given candidate edit modes; otherwise, false 089 */ 090 protected boolean hasRequiredEditMode(Set<String> currentEditModes, List<String> candidateEditModes) { 091 for (String editMode : candidateEditModes) { 092 if (currentEditModes.contains(editMode)) { 093 return true; 094 } 095 } 096 097 return false; 098 } 099 100 /** 101 * Retrieves the current edit modes from the document 102 * @param accountingDocument the document to find edit modes of 103 * @param financialSystemUser the user requesting the edit modes 104 * @return the Set of current edit modes 105 */ 106 protected Set<String> getEditModesFromDocument(AccountingDocument accountingDocument, Person financialSystemUser) { 107 final DocumentHelperService documentHelperService = SpringContext.getBean(DocumentHelperService.class); 108 final TransactionalDocumentAuthorizer documentAuthorizer = (TransactionalDocumentAuthorizer) documentHelperService.getDocumentAuthorizer(accountingDocument); 109 final TransactionalDocumentPresentationController presentationController = (TransactionalDocumentPresentationController) documentHelperService.getDocumentPresentationController(accountingDocument); 110 111 final Set<String> presentationControllerEditModes = presentationController.getEditModes(accountingDocument); 112 final Set<String> editModes = documentAuthorizer.getEditModes(accountingDocument, financialSystemUser, presentationControllerEditModes); 113 114 return editModes; 115 } 116 117 /** 118 * define the possibly desired edit modes 119 * 120 * @return the possibly desired edit modes 121 */ 122 protected List<String> getCandidateEditModes() { 123 List<String> candidateEdiModes = new ArrayList<String>(); 124 candidateEdiModes.add(DisbursementVoucherEditMode.TAX_ENTRY); 125 candidateEdiModes.add(DisbursementVoucherEditMode.FRN_ENTRY); 126 candidateEdiModes.add(DisbursementVoucherEditMode.TRAVEL_ENTRY); 127 candidateEdiModes.add(DisbursementVoucherEditMode.WIRE_ENTRY); 128 129 return candidateEdiModes; 130 } 131 132 /** 133 * get foreign draft And wire transfer edit mode names, as well as tax if the payee is a non-resident alien 134 * @param dvDocument the document we're validating 135 * @return foreign draft And wire transfer edit mode names 136 */ 137 protected List<String> getForeignDraftAndWireTransferEditModes(DisbursementVoucherDocument dvDocument) { 138 List<String> foreignDraftAndWireTransferEditModes = new ArrayList<String>(); 139 foreignDraftAndWireTransferEditModes.add(DisbursementVoucherEditMode.FRN_ENTRY); 140 foreignDraftAndWireTransferEditModes.add(DisbursementVoucherEditMode.WIRE_ENTRY); 141 142 if (includeTaxAsTotalChangingMode(dvDocument)) { 143 foreignDraftAndWireTransferEditModes.add(DisbursementVoucherEditMode.TAX_ENTRY); 144 } 145 146 return foreignDraftAndWireTransferEditModes; 147 } 148 149 /** 150 * Determines whether the tax edit mode should be allowed to change the accounting line totals, 151 * based on whether the payee is a non-resident alient or not 152 * @param dvDocument the document to check 153 * @return true if the tax entry mode can change accounting line totals, false otherwise 154 */ 155 protected boolean includeTaxAsTotalChangingMode(DisbursementVoucherDocument dvDocument) { 156 return dvDocument.getDvPayeeDetail().isDisbVchrAlienPaymentCode(); 157 } 158 }