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.sys.KFSPropertyConstants; 023 import org.kuali.kfs.sys.KfsAuthorizationConstants; 024 import org.kuali.kfs.sys.businessobject.AccountingLine; 025 import org.kuali.kfs.sys.context.SpringContext; 026 import org.kuali.kfs.sys.document.AccountingDocument; 027 import org.kuali.kfs.sys.document.authorization.AccountingLineAuthorizer; 028 import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent; 029 import org.kuali.kfs.sys.document.validation.impl.AccountingLineAccessibleValidation; 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 DisbursementVoucherAccountingLineAccessibleValidation extends AccountingLineAccessibleValidation { 038 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DisbursementVoucherAccountingLineAccessibleValidation.class); 039 protected AccountingLine oldAccountingLineForValidation; 040 041 /** 042 * Validates that the given accounting line is accessible for editing by the current user. <strong>This method expects a 043 * document as the first parameter and an accounting line as the second</strong> 044 * 045 * @see org.kuali.kfs.sys.document.validation.impl.AccountingLineAccessibleValidation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent) 046 */ 047 @Override 048 public boolean validate(AttributedDocumentEvent event) { 049 LOG.debug("validate start"); 050 051 Person financialSystemUser = GlobalVariables.getUserSession().getPerson(); 052 AccountingDocument accountingDocument = this.getAccountingDocumentForValidation(); 053 AccountingLine accountingLineForValidation = this.getAccountingLineForValidation(); 054 055 final AccountingLineAuthorizer accountingLineAuthorizer = lookupAccountingLineAuthorizer(); 056 final boolean lineIsAccessible = accountingLineAuthorizer.hasEditPermissionOnAccountingLine(accountingDocument, accountingLineForValidation, getAccountingLineCollectionProperty(), financialSystemUser, true); 057 boolean isAccessible = accountingLineAuthorizer.hasEditPermissionOnField(accountingDocument, accountingLineForValidation, getAccountingLineCollectionProperty(), KFSPropertyConstants.ACCOUNT_NUMBER, lineIsAccessible, true, financialSystemUser); 058 059 // get the authorizer class to check for special conditions routing and if the user is part of a particular workgroup 060 // but only if the document is enroute 061 KualiWorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument(); 062 if (!isAccessible && workflowDocument.stateIsEnroute()) { 063 064 if (oldAccountingLineForValidation == null || accountUnchanged(accountingLineForValidation, oldAccountingLineForValidation)) { 065 isAccessible = true; 066 } else { 067 // if approval is requested and the user has required edit permission, then the line is accessible 068 List<String> candidateEditModes = this.getCandidateEditModes(); 069 if (workflowDocument.isApprovalRequested() && this.hasRequiredEditMode(accountingDocument, financialSystemUser, candidateEditModes)) { 070 isAccessible = true; 071 } 072 } 073 } 074 075 // report errors if the current user can have no access to the account 076 if (!isAccessible) { 077 String accountNumber = accountingLineForValidation.getAccountNumber(); 078 String principalName = GlobalVariables.getUserSession().getPerson().getPrincipalName(); 079 String errorKey = this.convertEventToMessage(event); 080 081 GlobalVariables.getMessageMap().putError(KFSPropertyConstants.ACCOUNT_NUMBER, errorKey, accountNumber, principalName); 082 } 083 084 return isAccessible; 085 } 086 087 /** 088 * determine whether the give user has permission to any edit mode defined in the given candidate edit modes 089 * 090 * @param accountingDocument the given accounting document 091 * @param financialSystemUser the given user 092 * @param candidateEditEditModes the given candidate edit modes 093 * @return true if the give user has permission to any edit mode defined in the given candidate edit modes; otherwise, false 094 */ 095 protected boolean hasRequiredEditMode(AccountingDocument accountingDocument, Person financialSystemUser, List<String> candidateEditModes) { 096 DocumentHelperService documentHelperService = SpringContext.getBean(DocumentHelperService.class); 097 TransactionalDocumentAuthorizer documentAuthorizer = (TransactionalDocumentAuthorizer) documentHelperService.getDocumentAuthorizer(accountingDocument); 098 TransactionalDocumentPresentationController presentationController = (TransactionalDocumentPresentationController) documentHelperService.getDocumentPresentationController(accountingDocument); 099 100 Set<String> presentationControllerEditModes = presentationController.getEditModes(accountingDocument); 101 Set<String> editModes = documentAuthorizer.getEditModes(accountingDocument, financialSystemUser, presentationControllerEditModes); 102 103 for (String editMode : candidateEditModes) { 104 if (editModes.contains(editMode)) { 105 return true; 106 } 107 } 108 109 return false; 110 } 111 112 /** 113 * define the possibly desired edit modes 114 * 115 * @return the possibly desired edit modes 116 */ 117 protected List<String> getCandidateEditModes() { 118 List<String> candidateEdiModes = new ArrayList<String>(); 119 candidateEdiModes.add(KfsAuthorizationConstants.DisbursementVoucherEditMode.TAX_ENTRY); 120 candidateEdiModes.add(KfsAuthorizationConstants.DisbursementVoucherEditMode.FRN_ENTRY); 121 candidateEdiModes.add(KfsAuthorizationConstants.DisbursementVoucherEditMode.TRAVEL_ENTRY); 122 candidateEdiModes.add(KfsAuthorizationConstants.DisbursementVoucherEditMode.WIRE_ENTRY); 123 124 return candidateEdiModes; 125 } 126 127 /** 128 * Determines if the two given accounting lines have not have their account changed 129 * @param pollux the first accounting line to check 130 * @param castor the second accounting line to check 131 * @return true if the account is the same for the two, false otherwise 132 */ 133 protected boolean accountUnchanged(AccountingLine pollux, AccountingLine castor) { 134 return ((pollux.getChartOfAccountsCode() == null && castor.getChartOfAccountsCode() == null) || (pollux.getChartOfAccountsCode() != null && pollux.getChartOfAccountsCode().equals(castor.getChartOfAccountsCode()))) && ((pollux.getAccountNumber() == null && castor.getAccountNumber() == null) || (pollux.getAccountNumber() != null && pollux.getAccountNumber().equals(castor.getAccountNumber()))); 135 } 136 137 /** 138 * Sets the oldAccountingLineForValidation attribute value. 139 * @param oldAccountingLineForValidation The oldAccountingLineForValidation to set. 140 */ 141 public void setOldAccountingLineForValidation(AccountingLine oldAccountingLineForValidation) { 142 this.oldAccountingLineForValidation = oldAccountingLineForValidation; 143 } 144 }