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.authorization;
017    
018    import java.util.Arrays;
019    import java.util.List;
020    import java.util.Map;
021    
022    import org.kuali.kfs.fp.document.DisbursementVoucherConstants;
023    import org.kuali.kfs.fp.document.DisbursementVoucherDocument;
024    import org.kuali.kfs.sys.businessobject.AccountingLine;
025    import org.kuali.kfs.sys.document.authorization.AccountingDocumentAuthorizerBase;
026    import org.kuali.kfs.sys.identity.KfsKimAttributes;
027    import org.kuali.rice.kew.exception.WorkflowException;
028    import org.kuali.rice.kim.bo.Person;
029    import org.kuali.rice.kns.bo.BusinessObject;
030    import org.kuali.rice.kns.util.GlobalVariables;
031    import org.kuali.rice.kns.util.ObjectUtils;
032    import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
033    
034    /**
035     * Adds extra role qualifiers for funky travel edit mode permission
036     */
037    public class DisbursementVoucherDocumentAuthorizer extends AccountingDocumentAuthorizerBase {
038    
039        /**
040         * Adds chart codes and account numbers for accounting lines if we're at Account level, so that the fiscal officer gets travel edit mode
041         * @see org.kuali.kfs.sys.document.authorization.AccountingDocumentAuthorizerBase#addRoleQualification(org.kuali.rice.kns.bo.BusinessObject, java.util.Map)
042         */
043        @Override
044        protected void addRoleQualification(BusinessObject businessObject, Map<String, String> attributes) {
045            super.addRoleQualification(businessObject, attributes);
046            final DisbursementVoucherDocument disbursementVoucherDocument = (DisbursementVoucherDocument)businessObject;
047            
048            // are we add Account level?  Then let's add our qualifiers
049            if (isAtAccountLevel(disbursementVoucherDocument)) {
050                addAccountQualification(getAccountingLines(disbursementVoucherDocument), attributes);
051            }
052        }
053        
054        /**
055         * Finds the source accounting lines in the given business object
056         * @param disbursementVoucherDocument a document to get accounting lines from
057         * @return a List of accounting lines
058         */
059        protected List getAccountingLines(DisbursementVoucherDocument disbursementVoucherDocument) {  
060            return disbursementVoucherDocument.getSourceAccountingLines();
061        }
062    
063        /**
064         * Goes through the given List of accounting lines and fines one line where the current user is the fiscal officer; it uses that line to put chart of accounts
065         * code and account number qualifications into the given Map of attributes for role qualification
066         * @param accountingLines a List of AccountingLines
067         * @param attributes a Map of role qualification attributes
068         */
069        protected void addAccountQualification(List accountingLines, Map<String, String> attributes) {
070            final Person currentUser = GlobalVariables.getUserSession().getPerson();
071            boolean foundQualification = false;
072            int count = 0;
073            while (!foundQualification && count < accountingLines.size()) {
074                AccountingLine accountingLine = (AccountingLine)accountingLines.get(count);
075                if (ObjectUtils.isNull(accountingLine.getAccount())) {
076                    accountingLine.refreshReferenceObject("account");
077                }
078                if (!ObjectUtils.isNull(accountingLine.getAccount()) && currentUser.getPrincipalId().equalsIgnoreCase(accountingLine.getAccount().getAccountFiscalOfficerSystemIdentifier())) {
079                    attributes.put(KfsKimAttributes.CHART_OF_ACCOUNTS_CODE, accountingLine.getChartOfAccountsCode());
080                    attributes.put(KfsKimAttributes.ACCOUNT_NUMBER, accountingLine.getAccountNumber());
081                    foundQualification = true;
082                }
083                count += 1;
084            }
085        }
086        
087        /**
088         * A helper method for determining the route levels for a given document.
089         * 
090         * @param workflowDocument
091         * @return List
092         */
093        protected List<String> getCurrentRouteLevels(KualiWorkflowDocument workflowDocument) {
094            try {
095                return Arrays.asList(workflowDocument.getNodeNames());
096            }
097            catch (WorkflowException e) {
098                throw new RuntimeException(e);
099            }
100        }
101        
102        /**
103         * Determines if the document is at the Account route level
104         * @param disbursementVoucherDocument the Disbursement Voucher document to determine the account level of
105         * @return true if the document is at the account level, false otherwise
106         */
107        protected boolean isAtAccountLevel(DisbursementVoucherDocument disbursementVoucherDocument) {
108            final KualiWorkflowDocument workflowDocument = disbursementVoucherDocument.getDocumentHeader().getWorkflowDocument();
109            
110            return getCurrentRouteLevels(workflowDocument).contains(DisbursementVoucherConstants.RouteLevelNames.ACCOUNT);
111        }
112    }