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 java.sql.Date; 019 020 import org.apache.commons.lang.StringUtils; 021 import org.kuali.kfs.coa.businessobject.Account; 022 import org.kuali.kfs.coa.businessobject.SubFundGroup; 023 import org.kuali.kfs.coa.service.AccountService; 024 import org.kuali.kfs.sys.context.SpringContext; 025 import org.kuali.rice.kns.bo.PostalCode; 026 import org.kuali.rice.kns.document.MaintenanceDocument; 027 import org.kuali.rice.kns.service.KualiConfigurationService; 028 import org.kuali.rice.kns.service.PostalCodeService; 029 import org.kuali.rice.kns.util.ObjectUtils; 030 031 /** 032 * PreRules checks for the Account that needs to occur while still in the Struts processing. This includes defaults, confirmations, 033 * etc. 034 */ 035 public class AccountPreRules extends MaintenancePreRulesBase { 036 037 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountPreRules.class); 038 039 protected static final String DEFAULT_STATE_CODE = "Account.Defaults.StateCode"; 040 protected static final String DEFAULT_ACCOUNT_TYPE_CODE = "Account.Defaults.AccountType"; 041 042 protected KualiConfigurationService configService; 043 protected AccountService accountService; 044 protected PostalCodeService postalZipCodeService; 045 protected Account newAccount; 046 047 protected static final String GENERAL_FUND_CD = "GF"; 048 protected static final String RESTRICTED_FUND_CD = "RF"; 049 protected static final String ENDOWMENT_FUND_CD = "EN"; 050 protected static final String PLANT_FUND_CD = "PF"; 051 052 protected static final String RESTRICTED_CD_RESTRICTED = "R"; 053 protected static final String RESTRICTED_CD_UNRESTRICTED = "U"; 054 protected static final String RESTRICTED_CD_TEMPORARILY_RESTRICTED = "T"; 055 protected static final String RESTRICTED_CD_NOT_APPLICABLE = "N"; 056 057 058 public AccountPreRules() { 059 accountService = SpringContext.getBean(AccountService.class); 060 configService = SpringContext.getBean(KualiConfigurationService.class); 061 postalZipCodeService = SpringContext.getBean(PostalCodeService.class); 062 } 063 064 /** 065 * Executes the following pre rules 066 * <ul> 067 * <li>{@link AccountPreRules#checkForContinuationAccount(String, String, String, String)}</li> 068 * <li>{@link AccountPreRules#checkForDefaultSubFundGroupStatus()}</li> 069 * <li>{@link AccountPreRules#newAccountDefaults(MaintenanceDocument)}</li> 070 * <li>{@link AccountPreRules#setStateFromZip}</li> 071 * </ul> 072 * This does not fail on rule failures 073 * @see org.kuali.kfs.coa.document.validation.impl.MaintenancePreRulesBase#doCustomPreRules(org.kuali.rice.kns.document.MaintenanceDocument) 074 */ 075 protected boolean doCustomPreRules(MaintenanceDocument document) { 076 setupConvenienceObjects(document); 077 checkForContinuationAccounts(); // run this first to avoid side effects 078 checkForDefaultSubFundGroupStatus(); 079 080 LOG.debug("done with continuation account, proceeeding with remaining pre rules"); 081 082 newAccountDefaults(document); 083 setStateFromZip(document); 084 085 return true; 086 } 087 088 /** 089 * This method sets a default restricted status on an account if and only if the status code in SubFundGroup has been set and 090 * the user answers in the affirmative that they definitely want to use this SubFundGroup. 091 */ 092 protected void checkForDefaultSubFundGroupStatus() { 093 String restrictedStatusCode = ""; 094 095 // if subFundGroupCode was not entered, then we have nothing 096 // to do here, so exit 097 if (ObjectUtils.isNull(newAccount.getSubFundGroup()) || StringUtils.isBlank(newAccount.getSubFundGroupCode())) { 098 return; 099 } 100 SubFundGroup subFundGroup = newAccount.getSubFundGroup(); 101 102 // KULCOA-1112 : if the sub fund group has a restriction code, override whatever the user selected 103 if (StringUtils.isNotBlank(subFundGroup.getAccountRestrictedStatusCode())) { 104 restrictedStatusCode = subFundGroup.getAccountRestrictedStatusCode().trim(); 105 String subFundGroupCd = subFundGroup.getSubFundGroupCode(); 106 newAccount.setAccountRestrictedStatusCode(restrictedStatusCode); 107 } 108 109 } 110 111 /** 112 * This method checks for continuation accounts and presents the user with a question regarding their use on this account. 113 */ 114 protected void checkForContinuationAccounts() { 115 LOG.debug("entering checkForContinuationAccounts()"); 116 117 if (StringUtils.isNotBlank(newAccount.getReportsToAccountNumber())) { 118 Account account = checkForContinuationAccount("Fringe Benefit Account", newAccount.getReportsToChartOfAccountsCode(), newAccount.getReportsToAccountNumber(), ""); 119 if (ObjectUtils.isNotNull(account)) { // override old user inputs 120 newAccount.setReportsToAccountNumber(account.getAccountNumber()); 121 newAccount.setReportsToChartOfAccountsCode(account.getChartOfAccountsCode()); 122 } 123 } 124 125 if (StringUtils.isNotBlank(newAccount.getEndowmentIncomeAccountNumber())) { 126 Account account = checkForContinuationAccount("Endowment Account", newAccount.getEndowmentIncomeAcctFinCoaCd(), newAccount.getEndowmentIncomeAccountNumber(), ""); 127 if (ObjectUtils.isNotNull(account)) { // override old user inputs 128 newAccount.setEndowmentIncomeAccountNumber(account.getAccountNumber()); 129 newAccount.setEndowmentIncomeAcctFinCoaCd(account.getChartOfAccountsCode()); 130 } 131 } 132 133 if (StringUtils.isNotBlank(newAccount.getIncomeStreamAccountNumber())) { 134 Account account = checkForContinuationAccount("Income Stream Account", newAccount.getIncomeStreamFinancialCoaCode(), newAccount.getIncomeStreamAccountNumber(), ""); 135 if (ObjectUtils.isNotNull(account)) { // override old user inputs 136 newAccount.setIncomeStreamAccountNumber(account.getAccountNumber()); 137 newAccount.setIncomeStreamFinancialCoaCode(account.getChartOfAccountsCode()); 138 } 139 } 140 141 if (StringUtils.isNotBlank(newAccount.getContractControlAccountNumber())) { 142 Account account = checkForContinuationAccount("Contract Control Account", newAccount.getContractControlFinCoaCode(), newAccount.getContractControlAccountNumber(), ""); 143 if (ObjectUtils.isNotNull(account)) { // override old user inputs 144 newAccount.setContractControlAccountNumber(account.getAccountNumber()); 145 newAccount.setContractControlFinCoaCode(account.getChartOfAccountsCode()); 146 } 147 } 148 149 if (StringUtils.isNotBlank(newAccount.getIndirectCostRecoveryAcctNbr())) { 150 Account account = checkForContinuationAccount("Indirect Cost Recovery Account", newAccount.getIndirectCostRcvyFinCoaCode(), newAccount.getIndirectCostRecoveryAcctNbr(), ""); 151 if (ObjectUtils.isNotNull(account)) { // override old user inputs 152 newAccount.setIndirectCostRecoveryAcctNbr(account.getAccountNumber()); 153 newAccount.setIndirectCostRcvyFinCoaCode(account.getChartOfAccountsCode()); 154 } 155 } 156 157 158 } 159 160 /** 161 * This method sets the convenience objects like newAccount and oldAccount, so you have short and easy handles to the new and 162 * old objects contained in the maintenance document. It also calls the BusinessObjectBase.refresh(), which will attempt to load 163 * all sub-objects from the DB by their primary keys, if available. 164 * 165 * @param document - the maintenanceDocument being evaluated 166 */ 167 protected void setupConvenienceObjects(MaintenanceDocument document) { 168 169 // setup newAccount convenience objects, make sure all possible sub-objects are populated 170 newAccount = (Account) document.getNewMaintainableObject().getBusinessObject(); 171 newAccount.refreshNonUpdateableReferences(); 172 } 173 174 /** 175 * This method sets up some defaults for new Account 176 * 177 * @param maintenanceDocument 178 */ 179 protected void newAccountDefaults(MaintenanceDocument maintenanceDocument) { 180 181 182 /* 183 * GlobalVariables.getMessageMap().put("document.newMaintainableObject.accountEffectiveDate" , 184 * "error.document.accountMaintenance.emptyAccountEffectiveDate", "Account Effective Date"); 185 */ 186 187 // TODO: this is not needed any more, is in maintdoc xml defaults 188 Date ts = new Date(maintenanceDocument.getDocumentHeader().getWorkflowDocument().getCreateDate().getTime()); 189 if (ts != null) { 190 // On new Accounts AccountCreateDate is defaulted to the doc creation date 191 if (newAccount.getAccountCreateDate() == null) { 192 newAccount.setAccountCreateDate(ts); 193 } 194 // On new Accounts acct_effect_date is defaulted to the doc creation date 195 if (newAccount.getAccountEffectiveDate() == null) { 196 newAccount.setAccountEffectiveDate(ts); 197 } 198 } 199 } 200 201 /** 202 * This method lookups state and city from populated zip, set the values on the form 203 * 204 * @param maintenanceDocument 205 */ 206 protected void setStateFromZip(MaintenanceDocument maintenanceDocument) { 207 208 // acct_zip_cd, acct_state_cd, acct_city_nm all are populated by looking up 209 // the zip code and getting the state and city from that 210 if (!StringUtils.isBlank(newAccount.getAccountZipCode())) { 211 PostalCode zip = postalZipCodeService.getByPostalCodeInDefaultCountry(newAccount.getAccountZipCode()); 212 213 // If user enters a valid zip code, override city name and state code entered by user 214 if (ObjectUtils.isNotNull(zip)) { // override old user inputs 215 newAccount.setAccountCityName(zip.getPostalCityName()); 216 newAccount.setAccountStateCode(zip.getPostalStateCode()); 217 } 218 } 219 } 220 221 222 }