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