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 }