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 }