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 org.apache.commons.lang.StringUtils;
019    import org.kuali.kfs.fp.document.authorization.ServiceBillingDocumentAuthorizer;
020    import org.kuali.kfs.sys.KFSKeyConstants;
021    import org.kuali.kfs.sys.KFSPropertyConstants;
022    import org.kuali.kfs.sys.businessobject.AccountingLine;
023    import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader;
024    import org.kuali.kfs.sys.document.AccountingDocument;
025    import org.kuali.kfs.sys.document.Correctable;
026    import org.kuali.kfs.sys.document.validation.GenericValidation;
027    import org.kuali.kfs.sys.document.validation.event.AddAccountingLineEvent;
028    import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent;
029    import org.kuali.kfs.sys.document.validation.event.DeleteAccountingLineEvent;
030    import org.kuali.kfs.sys.document.validation.event.UpdateAccountingLineEvent;
031    import org.kuali.rice.kim.bo.Person;
032    import org.kuali.rice.kns.rule.event.KualiDocumentEvent;
033    import org.kuali.rice.kns.service.DataDictionaryService;
034    import org.kuali.rice.kns.util.GlobalVariables;
035    import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
036    
037    /**
038     * A validation that checks whether the given accounting line is accessible to the given user or not
039     */
040    public class ServiceBillingAccountingLineAccessibleValidation extends GenericValidation {
041        private DataDictionaryService dataDictionaryService;
042        private AccountingDocument accountingDocumentForValidation;
043        private AccountingLine accountingLineForValidation;
044        
045        /**
046         * Indicates what is being done to an accounting line. This allows the same method to be used for different actions.
047         */
048        public enum AccountingLineAction {
049            ADD(KFSKeyConstants.ERROR_ACCOUNTINGLINE_INACCESSIBLE_ADD), DELETE(KFSKeyConstants.ERROR_ACCOUNTINGLINE_INACCESSIBLE_DELETE), UPDATE(KFSKeyConstants.ERROR_ACCOUNTINGLINE_INACCESSIBLE_UPDATE);
050    
051            public final String accessibilityErrorKey;
052    
053            AccountingLineAction(String accessabilityErrorKey) {
054                this.accessibilityErrorKey = accessabilityErrorKey;
055            }
056        }
057    
058        /**
059         * Validates that the given accounting line is accessible for editing by the current user.
060         * <strong>This method expects a document as the first parameter and an accounting line as the second</strong>
061         * @see org.kuali.kfs.sys.document.validation.Validation#validate(java.lang.Object[])
062         */
063        public boolean validate(AttributedDocumentEvent event) {        
064            final Person currentUser = GlobalVariables.getUserSession().getPerson();
065            
066            if (accountingDocumentForValidation instanceof Correctable) {
067                final String errorDocumentNumber = ((FinancialSystemDocumentHeader)accountingDocumentForValidation.getDocumentHeader()).getFinancialDocumentInErrorNumber();
068                if (StringUtils.isNotBlank(errorDocumentNumber))
069                    return true;
070            }
071            
072            final KualiWorkflowDocument workflowDocument = accountingDocumentForValidation.getDocumentHeader().getWorkflowDocument();
073            if (accountingLineForValidation.isTargetAccountingLine() && (workflowDocument.stateIsInitiated() || workflowDocument.stateIsSaved())) {
074                return true; // all target lines are accessible PreRoute, no matter the account
075            }
076            
077            final boolean isAccessible = new ServiceBillingDocumentAuthorizer().canModifyAccountingLine(accountingDocumentForValidation, accountingLineForValidation,  currentUser);
078    
079            // report errors
080            if (!isAccessible) {
081                final String principalName = currentUser.getPrincipalName();
082                
083                final String[] chartErrorParams = new String[] { getDataDictionaryService().getAttributeLabel(accountingLineForValidation.getClass(), KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE), accountingLineForValidation.getChartOfAccountsCode(),  principalName};
084                GlobalVariables.getMessageMap().putError(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, convertEventToMessage(event), chartErrorParams);
085                
086                final String[] accountErrorParams = new String[] { getDataDictionaryService().getAttributeLabel(accountingLineForValidation.getClass(), KFSPropertyConstants.ACCOUNT_NUMBER), accountingLineForValidation.getAccountNumber(), principalName };
087                GlobalVariables.getMessageMap().putError(KFSPropertyConstants.ACCOUNT_NUMBER, convertEventToMessage(event), accountErrorParams);
088            }
089    
090            return isAccessible;
091        }
092        
093        
094        /**
095         * Determines what error message should be shown based on the event that required this validation
096         * @param event the event to use to determine the error message
097         * @return the key of the error message to display
098         */
099        protected String convertEventToMessage(KualiDocumentEvent event) {
100            if (event instanceof AddAccountingLineEvent) {
101                return AccountingLineAction.ADD.accessibilityErrorKey;
102            } else if (event instanceof UpdateAccountingLineEvent) {
103                return AccountingLineAction.UPDATE.accessibilityErrorKey;
104            } else if (event instanceof DeleteAccountingLineEvent) {
105                return AccountingLineAction.DELETE.accessibilityErrorKey;
106            } else {
107                return "";
108            }
109        }
110    
111        /**
112         * Gets the accountingDocumentForValidation attribute. 
113         * @return Returns the accountingDocumentForValidation.
114         */
115        public AccountingDocument getAccountingDocumentForValidation() {
116            return accountingDocumentForValidation;
117        }
118    
119        /**
120         * Sets the accountingDocumentForValidation attribute value.
121         * @param accountingDocumentForValidation The accountingDocumentForValidation to set.
122         */
123        public void setAccountingDocumentForValidation(AccountingDocument accountingDocumentForValidation) {
124            this.accountingDocumentForValidation = accountingDocumentForValidation;
125        }
126    
127        /**
128         * Gets the accountingLineForValidation attribute. 
129         * @return Returns the accountingLineForValidation.
130         */
131        public AccountingLine getAccountingLineForValidation() {
132            return accountingLineForValidation;
133        }
134    
135        /**
136         * Sets the accountingLineForValidation attribute value.
137         * @param accountingLineForValidation The accountingLineForValidation to set.
138         */
139        public void setAccountingLineForValidation(AccountingLine accountingLineForValidation) {
140            this.accountingLineForValidation = accountingLineForValidation;
141        }
142    
143        /**
144         * Gets the dataDictionaryService attribute. 
145         * @return Returns the dataDictionaryService.
146         */
147        public DataDictionaryService getDataDictionaryService() {
148            return dataDictionaryService;
149        }
150    
151        /**
152         * Sets the dataDictionaryService attribute value.
153         * @param dataDictionaryService The dataDictionaryService to set.
154         */
155        public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
156            this.dataDictionaryService = dataDictionaryService;
157        }
158        
159    }
160