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.coa.document.validation.impl;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.kfs.coa.businessobject.Account;
020    import org.kuali.kfs.coa.service.AccountService;
021    import org.kuali.kfs.sys.KFSKeyConstants;
022    import org.kuali.kfs.sys.context.SpringContext;
023    import org.kuali.rice.kns.document.Document;
024    import org.kuali.rice.kns.document.MaintenanceDocument;
025    import org.kuali.rice.kns.rules.PromptBeforeValidationBase;
026    import org.kuali.rice.kns.service.KualiConfigurationService;
027    import org.kuali.rice.kns.util.ObjectUtils;
028    
029    /**
030     * General PreRules checks for all Maintenance docs that needs to occur while still in the Struts processing.
031     */
032    public class MaintenancePreRulesBase extends PromptBeforeValidationBase {
033    
034        protected KualiConfigurationService configService;
035        protected AccountService accountService;
036    
037        /**
038         * Constructs a MaintenancePreRulesBase class and injects some services through setters
039         * 
040         * @TODO: should be fixed in the future to use Spring to inject these services
041         */
042        public MaintenancePreRulesBase() {
043            // Pseudo-inject some services.
044            //
045            // This approach is being used to make it simpler to convert the Rule classes
046            // to spring-managed with these services injected by Spring at some later date.
047            // When this happens, just remove these calls to the setters with
048            // SpringContext, and configure the bean defs for spring.
049            setAccountService(SpringContext.getBean(AccountService.class));
050            setConfigService(SpringContext.getBean(KualiConfigurationService.class));
051        }
052    
053        public void setAccountService(AccountService accountService) {
054            this.accountService = accountService;
055        }
056    
057        public void setConfigService(KualiConfigurationService configService) {
058            this.configService = configService;
059        }
060    
061        /**
062         * This is called from the rules service to execute our rules A hook is provided here for sub-classes to override the
063         * {@link MaintenancePreRulesBase#doCustomPreRules(MaintenanceDocument)}
064         * 
065         * @see org.kuali.rice.kns.rules.PromptBeforeValidationBase#doRules(org.kuali.rice.kns.document.Document)
066         */
067        @Override
068        public boolean doPrompts(Document document) {
069            MaintenanceDocument maintenanceDocument = (MaintenanceDocument) document;
070            return doCustomPreRules(maintenanceDocument);
071        }
072    
073        /**
074         * This is a hook for sub-classes to implement their own pre-rules. Override to get hooked into main class
075         * 
076         * @param maintenanceDocument
077         * @return true if rules pass
078         */
079        protected boolean doCustomPreRules(MaintenanceDocument maintenanceDocument) {
080            return true;
081        }
082    
083        /**
084         * This method checks for continuation accounts, returns the continuation account if it is found, null otherwise
085         * 
086         * @param accName
087         * @param chart
088         * @param accountNumber
089         * @param accountName
090         * @param allowExpiredAccount
091         * @return the continuation account if it is found, null otherwise
092         */
093        protected Account checkForContinuationAccount(String accName, String chart, String accountNumber, String accountName, boolean allowExpiredAccount) {
094            Account result = checkForContinuationAccount(accName, chart, accountNumber, accountName);
095            if (!allowExpiredAccount) {
096                if (result.isExpired()) {
097                    return null;
098                }
099            }
100            return result;
101        }
102    
103        /**
104         * This method checks for continuation accounts and presents the user with a question regarding their use on this account.
105         * 
106         * @param accName
107         * @param chart
108         * @param accountNumber
109         * @param accountName
110         * @return
111         */
112        protected Account checkForContinuationAccount(String accName, String chart, String accountNumber, String accountName) {
113            if (LOG.isDebugEnabled()) {
114                LOG.debug("entering checkForContinuationAccounts(" + accountNumber + ")");
115            }
116            if (StringUtils.isBlank(accountNumber) || StringUtils.isBlank(chart))
117                return null;
118    
119            Account account = accountService.getByPrimaryId(chart, accountNumber);
120    
121            if (ObjectUtils.isNotNull(account) && !account.isExpired()) { // no need for a continuation account
122                return null;
123            }
124    
125            boolean useContinuationAccount = true;
126    
127            while (ObjectUtils.isNotNull(account) && account.isExpired() && useContinuationAccount) {
128                LOG.debug("Expired account: " + accountNumber);
129                String continuationAccountNumber = account.getContinuationAccountNumber();
130    
131                useContinuationAccount = askOrAnalyzeYesNoQuestion("ContinuationAccount" + accName + accountNumber, buildContinuationConfirmationQuestion(accName, accountNumber, continuationAccountNumber));
132                if (useContinuationAccount) {
133                    String continuationChart = account.getContinuationFinChrtOfAcctCd();
134                    account = accountService.getByPrimaryId(continuationChart, continuationAccountNumber);
135    
136                    if (ObjectUtils.isNotNull(account)) {
137                        accountNumber = account.getAccountNumber();
138                    }
139    
140                    if (LOG.isDebugEnabled()) {
141                        LOG.debug("Selected continuation account: " + account);
142                    }
143                }
144            }
145            return account;
146    
147        }
148    
149    
150        /**
151         * This method builds up the continuation account confirmation question that will be presented to the user
152         * 
153         * @param accName
154         * @param expiredAccount
155         * @param continuationAccount
156         * @return the question to the user about the continuation account
157         */
158        protected String buildContinuationConfirmationQuestion(String accName, String expiredAccount, String continuationAccount) {
159            String result = configService.getPropertyString(KFSKeyConstants.QUESTION_CONTINUATION_ACCOUNT_SELECTION);
160            result = StringUtils.replace(result, "{0}", accName);
161            result = StringUtils.replace(result, "{1}", expiredAccount);
162            result = StringUtils.replace(result, "{2}", continuationAccount);
163            return result;
164        }
165    
166        public AccountService getAccountService() {
167            return accountService;
168        }
169    
170        public KualiConfigurationService getConfigService() {
171            return configService;
172        }
173    
174    }