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.sys.document;
017    
018    import java.util.Iterator;
019    import java.util.Map;
020    
021    import org.apache.log4j.Logger;
022    import org.kuali.kfs.coa.businessobject.Account;
023    import org.kuali.kfs.coa.service.AccountPersistenceStructureService;
024    import org.kuali.kfs.coa.service.AccountService;
025    import org.kuali.kfs.sys.KFSPropertyConstants;
026    import org.kuali.kfs.sys.context.SpringContext;
027    import org.kuali.rice.kns.bo.BusinessObject;
028    import org.kuali.rice.kns.bo.PersistableBusinessObject;
029    import org.kuali.rice.kns.document.MaintenanceDocument;
030    import org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl;
031    import org.kuali.rice.kns.util.ObjectUtils;
032    
033    /**
034     * This class...
035     */
036    public abstract class FinancialSystemGlobalMaintainable extends KualiGlobalMaintainableImpl {
037        private static final Logger LOG = Logger.getLogger(FinancialSystemGlobalMaintainable.class);
038    
039        protected boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
040            throw new UnsupportedOperationException("FinancialSystemGlobalMaintainable does not implement the answerSplitNodeQuestion method. Node name specified was: " + nodeName); 
041        }
042    
043        /**
044         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#refreshReferences(String)
045         */
046        @Override
047        protected void refreshReferences(String referencesToRefresh) {
048            // if accounts can't cross charts, populate chart code fields according to corresponding account number fields
049            if (!SpringContext.getBean(AccountService.class).accountsCanCrossCharts()) {
050                populateChartOfAccountsCodeFields();            
051            }
052            
053            super.refreshReferences(referencesToRefresh);
054        }
055        
056        /**
057         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#processAfterAddLine(String)
058         */
059        @Override
060        public void processBeforeAddLine(String colName, Class colClass, BusinessObject bo) {
061            super.processBeforeAddLine(colName, colClass, bo);
062    
063            // if accounts can't cross charts, populate chart code fields according to corresponding account number fields
064            if (!SpringContext.getBean(AccountService.class).accountsCanCrossCharts()) {
065                populateChartOfAccountsCodeFields();            
066            }
067        }
068    
069        /**
070         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#processAfterPost(String)
071         */
072        @Override
073        public void processAfterPost(MaintenanceDocument document, Map<String, String[]> parameters) {
074            super.processAfterPost(document, parameters);
075    
076            // if accounts can't cross charts, populate chart code fields according to corresponding account number fields
077            if (!SpringContext.getBean(AccountService.class).accountsCanCrossCharts()) {
078                populateChartOfAccountsCodeFields();            
079            }
080        }
081        
082        /**
083         * Populates all chartOfAccountsCode fields according to corresponding accountNumber fields in this BO.  
084         * The chartOfAccountsCode-accountNumber pairs are (part of) the FKs for the reference accounts in this BO.    
085         */
086        protected void populateChartOfAccountsCodeFields() {
087            AccountService acctService = SpringContext.getBean(AccountService.class);
088            AccountPersistenceStructureService apsService = SpringContext.getBean(AccountPersistenceStructureService.class);
089     
090            // non-collection reference accounts 
091            PersistableBusinessObject bo = getBusinessObject();        
092            Iterator<Map.Entry<String, String>> chartAccountPairs = apsService.listChartCodeAccountNumberPairs(bo).entrySet().iterator();        
093            while (chartAccountPairs.hasNext()) {
094                Map.Entry<String, String> entry = (Map.Entry<String, String>)chartAccountPairs.next();
095                String coaCodeName = entry.getKey();            
096                String acctNumName = entry.getValue(); 
097                String accountNumber = (String)ObjectUtils.getPropertyValue(bo, acctNumName);
098                String coaCode = null;
099                Account account = acctService.getUniqueAccountForAccountNumber(accountNumber);            
100                if (ObjectUtils.isNotNull(account)) {
101                    coaCode = account.getChartOfAccountsCode();
102                }
103                try {
104                    ObjectUtils.setObjectProperty(bo, coaCodeName, coaCode); 
105                }
106                catch (Exception e) {
107                    LOG.error("Error in setting property value for " + coaCodeName, e);
108                }
109            }
110            
111            // collection reference accounts         
112            Iterator<Map.Entry<String, Class>> accountColls = apsService.listCollectionAccountFields(bo).entrySet().iterator();        
113            while (accountColls.hasNext()) {
114                Map.Entry<String, Class> entry = (Map.Entry<String, Class>)accountColls.next();
115                String accountCollName = entry.getKey();
116                PersistableBusinessObject newAccount = getNewCollectionLine(accountCollName);
117                
118                // here we can use hard-coded chartOfAccountsCode and accountNumber field name 
119                // since all reference account types do follow the standard naming pattern        
120                String accountNumber = (String)ObjectUtils.getPropertyValue(newAccount, KFSPropertyConstants.ACCOUNT_NUMBER);            
121                String coaCode = null;
122                Account account = acctService.getUniqueAccountForAccountNumber(accountNumber);            
123                if (ObjectUtils.isNotNull(account)) {
124                    coaCode = account.getChartOfAccountsCode();
125                    try {
126                        ObjectUtils.setObjectProperty(newAccount, KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, coaCode); 
127                    }
128                    catch (Exception e) {
129                        LOG.error("Error in setting chartOfAccountsCode property value in account collection " + accountCollName, e);
130                    }
131                }
132            }
133        }
134        
135    }