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 }