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.module.external.kc.document.validation.impl;
017    
018    import java.util.Calendar;
019    import java.util.Collection;
020    import java.util.Date;
021    import java.util.HashMap;
022    import java.util.Map;
023    
024    import org.apache.commons.lang.StringUtils;
025    import org.apache.commons.lang.time.DateUtils;
026    import org.kuali.kfs.coa.businessobject.Account;
027    import org.kuali.kfs.coa.businessobject.FundGroup;
028    import org.kuali.kfs.coa.businessobject.IndirectCostRecoveryRateDetail;
029    import org.kuali.kfs.coa.businessobject.SubFundGroup;
030    import org.kuali.kfs.coa.service.AccountService;
031    import org.kuali.kfs.integration.cg.ContractsAndGrantsConstants;
032    import org.kuali.kfs.integration.cg.ContractsAndGrantsModuleService;
033    import org.kuali.kfs.integration.cg.ContractsAndGrantsUnit;
034    import org.kuali.kfs.integration.cg.dto.AccountCreationStatusDTO;
035    import org.kuali.kfs.integration.cg.dto.AccountParametersDTO;
036    import org.kuali.kfs.module.external.kc.KcConstants;
037    import org.kuali.kfs.module.external.kc.businessobject.AccountAutoCreateDefaults;
038    import org.kuali.kfs.module.external.kc.service.impl.AccountCreationServiceImpl;
039    import org.kuali.kfs.sys.KFSConstants;
040    import org.kuali.kfs.sys.KFSKeyConstants;
041    import org.kuali.kfs.sys.KFSPropertyConstants;
042    import org.kuali.kfs.sys.context.SpringContext;
043    import org.kuali.kfs.sys.document.validation.impl.KfsMaintenanceDocumentRuleBase;
044    import org.kuali.kfs.sys.service.UniversityDateService;
045    import org.kuali.rice.kim.bo.Person;
046    import org.kuali.rice.kns.document.MaintenanceDocument;
047    import org.kuali.rice.kns.service.DataDictionaryService;
048    import org.kuali.rice.kns.service.DictionaryValidationService;
049    import org.kuali.rice.kns.service.KualiModuleService;
050    import org.kuali.rice.kns.service.ParameterService;
051    import org.kuali.rice.kns.util.GlobalVariables;
052    import org.kuali.rice.kns.util.KNSConstants;
053    import org.kuali.rice.kns.util.ObjectUtils;
054    
055    /**
056     * Business rule(s) applicable to AccountMaintenance documents.
057     */
058    public class AccountAutoCreateDefaultsRule extends org.kuali.kfs.coa.document.validation.impl.AccountRule {
059    
060        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountAutoCreateDefaultsRule.class);
061        protected static ParameterService parameterService;
062    
063        protected AccountService accountService;
064        protected ContractsAndGrantsModuleService contractsAndGrantsModuleService;
065    
066        protected AccountAutoCreateDefaults oldAccountAutoCreateDefaults;
067        protected AccountAutoCreateDefaults newAccountAutoCreateDefaults;
068    
069        public AccountAutoCreateDefaultsRule() {
070    
071            // Pseudo-inject some services.
072            //
073            // This approach is being used to make it simpler to convert the Rule classes
074            // to spring-managed with these services injected by Spring at some later date.
075            // When this happens, just remove these calls to the setters with
076            // SpringContext, and configure the bean defs for spring.
077            this.setContractsAndGrantsModuleService(SpringContext.getBean(ContractsAndGrantsModuleService.class));
078            accountService = SpringContext.getBean(AccountService.class);
079        }
080    
081        /**
082         * This method sets the convenience objects like newAccountAutoCreateDefaults and oldAccountAutoCreateDefaults, so you have
083         * short and easy handles to the new and old objects contained in the maintenance document. It also calls the
084         * BusinessObjectBase.refresh(), which will attempt to load all sub-objects from the DB by their primary keys, if available.
085         */
086        public void setupConvenienceObjects() {
087    
088            // setup oldAccountAutoCreateDefaults convenience objects, make sure all possible sub-objects are populated
089            oldAccountAutoCreateDefaults = (AccountAutoCreateDefaults) super.getOldBo();
090    
091            // setup newAccountAutoCreateDefaults convenience objects, make sure all possible sub-objects are populated
092            newAccountAutoCreateDefaults = (AccountAutoCreateDefaults) super.getNewBo();
093        }
094    
095        /**
096         * This method calls the route rules but does not fail if any of them fail (this only happens on routing)
097         * 
098         * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
099         */
100        protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
101    
102            LOG.info("processCustomSaveDocumentBusinessRules called");
103            // call the route rules to report all of the messages, but ignore the result
104            processCustomRouteDocumentBusinessRules(document);
105    
106            // Save always succeeds, even if there are business rule failures
107            return true;
108        }
109    
110        /**
111         * This method calls the following rules: checkAccountGuidelinesValidation checkEmptyValues checkGeneralRules checkCloseAccount
112         * checkContractsAndGrants checkExpirationDate checkFundGroup checkSubFundGroup checkFiscalOfficerIsValidKualiUser this rule
113         * will fail on routing
114         * 
115         * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
116         */
117        protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
118            // default to success
119            boolean success = true;
120    
121            LOG.info("processCustomRouteDocumentBusinessRules called");
122            setupConvenienceObjects();
123            
124            success &= checkEmptyValues(document);
125            success &= checkGeneralRules(document);        
126            success &= checkContractsAndGrants(document);                        
127            success &= checkIncomeStreamAccountRule();        
128            success &= checkRequiredKcUnit(newAccountAutoCreateDefaults, document.isNew());
129            
130            return success;
131        }
132     
133        protected boolean checkEmptyValues(MaintenanceDocument maintenanceDocument) {
134    
135            LOG.info("checkEmptyValues called");
136    
137            boolean success = true;
138    
139            // this set confirms that all fields which are grouped (ie, foreign keys of a reference
140            // object), must either be none filled out, or all filled out.
141            success &= checkForPartiallyFilledOutReferenceForeignKeys("continuationAccount");
142            success &= checkForPartiallyFilledOutReferenceForeignKeys("incomeStreamAccount");
143            
144            success &= checkForPartiallyFilledOutReferenceForeignKeys("reportsToAccount");        
145            success &= checkForPartiallyFilledOutReferenceForeignKeys("indirectCostRecoveryAcct");
146    
147            return success;
148        }
149    
150        protected boolean checkGeneralRules(MaintenanceDocument maintenanceDocument) {
151    
152            LOG.info("checkGeneralRules called");
153            Person fiscalOfficer = newAccountAutoCreateDefaults.getAccountFiscalOfficerUser();
154            Person accountManager = newAccountAutoCreateDefaults.getAccountManagerUser();
155            Person accountSupervisor = newAccountAutoCreateDefaults.getAccountSupervisoryUser();
156    
157            boolean success = true;
158            
159            // check FringeBenefit account rules
160            success &= checkFringeBenefitAccountRule();
161    
162            if (ObjectUtils.isNotNull(fiscalOfficer) && !getDocumentHelperService().getDocumentAuthorizer(maintenanceDocument).isAuthorized(maintenanceDocument, KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER, fiscalOfficer.getPrincipalId())) {
163                super.putFieldError("accountFiscalOfficerUser.principalName", KFSKeyConstants.ERROR_USER_MISSING_PERMISSION, new String[] {fiscalOfficer.getName(), KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER});
164                success = false;
165            }
166            if (ObjectUtils.isNotNull(accountSupervisor) && !getDocumentHelperService().getDocumentAuthorizer(maintenanceDocument).isAuthorized(maintenanceDocument, KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_SUPERVISOR, accountSupervisor.getPrincipalId())) {
167                super.putFieldError("accountSupervisoryUser.principalName", KFSKeyConstants.ERROR_USER_MISSING_PERMISSION, new String[] {accountSupervisor.getName(), KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_SUPERVISOR});
168                success = false;
169            }
170            if (ObjectUtils.isNotNull(accountManager) && !getDocumentHelperService().getDocumentAuthorizer(maintenanceDocument).isAuthorized(maintenanceDocument, KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_MANAGER, accountManager.getPrincipalId())) {
171                super.putFieldError("accountManagerUser.principalName", KFSKeyConstants.ERROR_USER_MISSING_PERMISSION, new String[] {accountManager.getName(), KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_MANAGER});
172                success = false;
173            }
174    
175            // the supervisor cannot be the same as the fiscal officer or account manager.
176            if (isSupervisorSameAsFiscalOfficer()) {
177                success &= false;
178                putFieldError("accountsSupervisorySystemsIdentifier", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ACCT_SUPER_CANNOT_BE_FISCAL_OFFICER);
179            }
180            if (isSupervisorSameAsManager()) {
181                success &= false;
182                putFieldError("accountManagerSystemIdentifier", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ACCT_SUPER_CANNOT_BE_ACCT_MGR);
183            }
184    
185            // disallow continuation account being expired
186            if (isContinuationAccountExpired()) {
187                success &= false;
188                putFieldError("continuationAccountNumber", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ACCOUNT_EXPIRED_CONTINUATION);
189            }
190    
191            return success;
192        }
193    
194        protected boolean checkFringeBenefitAccountRule() {
195    
196            boolean result = true;
197    
198            // if this account is selected as a Fringe Benefit Account, then we have nothing
199            // to test, so exit
200            if (newAccountAutoCreateDefaults.isAccountsFringesBnftIndicator()) {
201                return true;
202            }
203    
204            // if fringe benefit is not selected ... continue processing
205    
206            // fringe benefit account number is required
207            if (StringUtils.isBlank(newAccountAutoCreateDefaults.getReportsToAccountNumber())) {
208                putFieldError("reportsToAccountNumber", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_RPTS_TO_ACCT_REQUIRED_IF_FRINGEBENEFIT_FALSE);
209                result &= false;
210            }
211    
212            // fringe benefit chart of accounts code is required
213            if (StringUtils.isBlank(newAccountAutoCreateDefaults.getReportsToChartOfAccountsCode())) {
214                putFieldError("reportsToChartOfAccountsCode", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_RPTS_TO_ACCT_REQUIRED_IF_FRINGEBENEFIT_FALSE);
215                result &= false;
216            }
217    
218            // if either of the fringe benefit account fields are not present, then we're done
219            if (result == false) {
220                return result;
221            }
222    
223            // attempt to load the fringe benefit account
224            Account fringeBenefitAccount = accountService.getByPrimaryId(newAccountAutoCreateDefaults.getReportsToChartOfAccountsCode(), newAccountAutoCreateDefaults.getReportsToAccountNumber());
225    
226            // fringe benefit account must exist
227            if (fringeBenefitAccount == null) {
228                putFieldError("reportsToAccountNumber", KFSKeyConstants.ERROR_EXISTENCE, getFieldLabel(Account.class, "reportsToAccountNumber"));
229                return false;
230            }
231    
232            // fringe benefit account must be active
233            if (!fringeBenefitAccount.isActive()) {
234                putFieldError("reportsToAccountNumber", KFSKeyConstants.ERROR_INACTIVE, getFieldLabel(Account.class, "reportsToAccountNumber"));
235                result &= false;
236            }
237    
238            // make sure the fringe benefit account specified is set to fringe benefits = Y
239            if (!fringeBenefitAccount.isAccountsFringesBnftIndicator()) {
240                putFieldError("reportsToAccountNumber", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_RPTS_TO_ACCT_MUST_BE_FLAGGED_FRINGEBENEFIT, fringeBenefitAccount.getChartOfAccountsCode() + "-" + fringeBenefitAccount.getAccountNumber());
241                result &= false;
242            }
243    
244            return result;
245        }
246    
247        protected boolean isSupervisorSameAsFiscalOfficer() {
248            return areTwoUsersTheSame(newAccountAutoCreateDefaults.getAccountSupervisoryUser(), newAccountAutoCreateDefaults.getAccountFiscalOfficerUser());
249        }
250    
251        protected boolean isSupervisorSameAsManager() {
252            return areTwoUsersTheSame(newAccountAutoCreateDefaults.getAccountSupervisoryUser(), newAccountAutoCreateDefaults.getAccountManagerUser());
253        }
254    
255        protected boolean isContinuationAccountExpired() {
256    
257            boolean result = false;
258    
259            String chartCode = newAccountAutoCreateDefaults.getContinuationFinChrtOfAcctCd();
260            String accountNumber = newAccountAutoCreateDefaults.getContinuationAccountNumber();
261    
262            // if either chartCode or accountNumber is not entered, then we
263            // can't continue, so exit
264            if (StringUtils.isBlank(chartCode) || StringUtils.isBlank(accountNumber)) {
265                return result;
266            }
267    
268            // attempt to retrieve the continuation account from the DB
269            Account continuation = accountService.getByPrimaryId(chartCode, accountNumber);
270    
271            // if the object doesn't exist, then we can't continue, so exit
272            if (ObjectUtils.isNull(continuation)) {
273                return result;
274            }
275    
276            // at this point, we have a valid continuation account, so we just need to
277            // know whether its expired or not
278            result = continuation.isExpired();
279    
280            return result;
281        }
282    
283        protected boolean checkContractsAndGrants(MaintenanceDocument maintenanceDocument) {
284    
285            LOG.info("checkContractsAndGrants called");
286    
287            boolean success = true;
288    
289            // Certain C&G fields are required if the Account belongs to the CG Fund Group
290            success &= checkCgRequiredFields();
291    
292            // Income Stream account is required if this account is CG fund group,
293            // or GF (general fund) fund group (with some exceptions)
294            success &= checkIncomeStreamValid();
295            
296            // check if the new account has a valid responsibility id
297            if (!ObjectUtils.isNull(newAccountAutoCreateDefaults)) {
298                Account account = new Account();
299                account.setContractsAndGrantsAccountResponsibilityId(newAccountAutoCreateDefaults.getContractsAndGrantsAccountResponsibilityId());
300                final boolean hasValidAccountResponsibility = contractsAndGrantsModuleService.hasValidAccountReponsiblityIdIfNotNull(account);
301                if (!hasValidAccountResponsibility) {
302                    success &= hasValidAccountResponsibility;
303                    putFieldError("contractsAndGrantsAccountResponsibilityId", KFSKeyConstants.ERROR_DOCUMENT_ACCTMAINT_INVALID_CG_RESPONSIBILITY , new String[] { newAccountAutoCreateDefaults.getContractsAndGrantsAccountResponsibilityId().toString(), newAccountAutoCreateDefaults.getChartOfAccountsCode(), "" });
304                }
305            }
306    
307            return success;
308        }
309    
310        protected boolean checkCgRequiredFields() {
311    
312            boolean result = true;
313    
314            // Certain C&G fields are required if the Account belongs to the CG Fund Group
315            if (ObjectUtils.isNotNull(newAccountAutoCreateDefaults.getSubFundGroup())) {
316                if (getSubFundGroupService().isForContractsAndGrants(newAccountAutoCreateDefaults.getSubFundGroup())) {
317    
318                    result &= checkEmptyBOField("indirectCostRcvyFinCoaCode", newAccountAutoCreateDefaults.getIndirectCostRcvyFinCoaCode(), replaceTokens(KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ICR_CHART_CODE_CANNOT_BE_EMPTY));
319                    result &= checkEmptyBOField("indirectCostRecoveryAcctNbr", newAccountAutoCreateDefaults.getIndirectCostRecoveryAcctNbr(), replaceTokens(KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ICR_ACCOUNT_CANNOT_BE_EMPTY));                
320                }
321                else {
322                    // this is not a C&G fund group. So users should not fill in any fields in the C&G tab.
323                    result &= checkCGFieldNotFilledIn("indirectCostRcvyFinCoaCode");
324                    result &= checkCGFieldNotFilledIn("indirectCostRecoveryAcctNbr");
325                }
326            }
327            return result;
328        }
329    
330        protected boolean checkIncomeStreamValid() {
331            // if the subFundGroup object is null, we can't test, so exit
332            if (ObjectUtils.isNull(newAccountAutoCreateDefaults.getSubFundGroup())) {
333                return true;
334            }
335            String subFundGroupCode = newAccountAutoCreateDefaults.getSubFundGroupCode().trim();
336            String fundGroupCode = newAccountAutoCreateDefaults.getSubFundGroup().getFundGroupCode().trim();
337            boolean valid = true;
338            if (getParameterService().getParameterEvaluator(Account.class, KFSConstants.ChartApcParms.INCOME_STREAM_ACCOUNT_REQUIRING_FUND_GROUPS, fundGroupCode).evaluationSucceeds()) {
339                if (getParameterService().getParameterEvaluator(Account.class, KFSConstants.ChartApcParms.INCOME_STREAM_ACCOUNT_REQUIRING_SUB_FUND_GROUPS, subFundGroupCode).evaluationSucceeds()) {
340                    if (StringUtils.isBlank(newAccountAutoCreateDefaults.getIncomeStreamFinancialCoaCode())) {
341                        putFieldError(KFSPropertyConstants.INCOME_STREAM_CHART_OF_ACCOUNTS_CODE, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_INCOME_STREAM_ACCT_COA_CANNOT_BE_EMPTY, new String[] { getDdService().getAttributeLabel(FundGroup.class, KFSConstants.FUND_GROUP_CODE_PROPERTY_NAME), fundGroupCode, getDdService().getAttributeLabel(SubFundGroup.class, KFSConstants.SUB_FUND_GROUP_CODE_PROPERTY_NAME), subFundGroupCode });
342                        valid = false;
343                    } 
344                    if (StringUtils.isBlank(newAccountAutoCreateDefaults.getIncomeStreamAccountNumber())) {
345                        putFieldError(KFSPropertyConstants.INCOME_STREAM_ACCOUNT_NUMBER, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_INCOME_STREAM_ACCT_NBR_CANNOT_BE_EMPTY, new String[] { getDdService().getAttributeLabel(FundGroup.class, KFSConstants.FUND_GROUP_CODE_PROPERTY_NAME), fundGroupCode, getDdService().getAttributeLabel(SubFundGroup.class, KFSConstants.SUB_FUND_GROUP_CODE_PROPERTY_NAME), subFundGroupCode});
346                        valid = false;
347                    }
348                }
349            }
350            return valid;
351        }
352    
353        protected boolean checkCGFieldNotFilledIn(String propertyName) {
354            boolean success = true;
355            Object value = ObjectUtils.getPropertyValue(newAccountAutoCreateDefaults, propertyName);
356            if ((value instanceof String && !StringUtils.isBlank(value.toString())) || (value != null)) {
357                success = false;
358                putFieldError(propertyName, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_CG_FIELDS_FILLED_FOR_NON_CG_ACCOUNT, new String[] { newAccountAutoCreateDefaults.getSubFundGroupCode() });
359            }
360    
361            return success;
362        }
363    
364        protected boolean checkIncomeStreamAccountRule() {
365            // KFSMI-4877: if fund group is in system parameter values then income stream account number must exist.
366            if ( ObjectUtils.isNotNull(newAccountAutoCreateDefaults.getSubFundGroup()) && StringUtils.isNotBlank(newAccountAutoCreateDefaults.getSubFundGroup().getFundGroupCode())) {
367                if (ObjectUtils.isNull(newAccountAutoCreateDefaults.getIncomeStreamAccount())) {
368                    String incomeStreamRequiringFundGroupCode = SpringContext.getBean(ParameterService.class).getParameterValue(Account.class, KFSConstants.ChartApcParms.INCOME_STREAM_ACCOUNT_REQUIRING_FUND_GROUPS);
369                    if (StringUtils.containsIgnoreCase(newAccountAutoCreateDefaults.getSubFundGroup().getFundGroupCode(), incomeStreamRequiringFundGroupCode)) {
370                        GlobalVariables.getMessageMap().putError(KFSPropertyConstants.ACCOUNT_NUMBER, KFSKeyConstants.ERROR_DOCUMENT_BA_NO_INCOME_STREAM_ACCOUNT, "");
371                        return false;
372                    }
373                }
374            }
375            return true;
376        }
377    
378        /**
379         * This method checks to make sure that the kcUnit field exists and is entered correctly
380         * 
381         * @param newAccountAutoCreateDefaults
382         * @return true/false
383         */
384        protected boolean checkRequiredKcUnit(AccountAutoCreateDefaults newAccountAutoCreateDefaults, boolean isNew) {
385    
386            boolean result = true;
387            try {
388                ContractsAndGrantsUnit unitDTO = newAccountAutoCreateDefaults.getUnitDTO();
389                unitDTO = (ContractsAndGrantsUnit) SpringContext.getBean(KualiModuleService.class).getResponsibleModuleService(ContractsAndGrantsUnit.class).retrieveExternalizableBusinessObjectIfNecessary(newAccountAutoCreateDefaults, unitDTO, "unitDTO");
390                if (unitDTO == null) {
391                    putFieldError(KcConstants.AccountCreationDefaults.KcUnit, ContractsAndGrantsConstants.AccountCreationService.ERROR_KC_ACCOUNT_PARAMS_UNIT_NOTFOUND, newAccountAutoCreateDefaults.getKcUnit());
392                    result &= false;
393                }
394                // in the case of new accounts check if KcUnit exists already in accountAutoCreateDefaults table - if so reject
395                if (isNew) {
396                    // check for new copy and new conditions
397                    String kcUnit = newAccountAutoCreateDefaults.getKcUnit();
398                    if ((kcUnit != null)) {
399                        HashMap<String, String> map = new HashMap<String,String>();
400                    
401                        map.put(KcConstants.AccountCreationDefaults.KcUnit, kcUnit);
402                        Collection <AccountAutoCreateDefaults> accountAutoCreateDefaultList = boService.findMatching(AccountAutoCreateDefaults.class, map);
403                        if (accountAutoCreateDefaultList == null || (! accountAutoCreateDefaultList.isEmpty())) {
404                            putFieldError(KcConstants.AccountCreationDefaults.KcUnit, ContractsAndGrantsConstants.AccountCreationService.ERROR_KC_ACCOUNT_ALREADY_DEFINED, newAccountAutoCreateDefaults.getKcUnit());
405                            result &= false;
406                        }
407                    }
408                }
409                return result;
410            }
411            catch (Exception ex) {
412                putFieldError(KcConstants.AccountCreationDefaults.KcUnit, ContractsAndGrantsConstants.AccountCreationService.ERROR_KC_ACCOUNT_PARAMS_UNIT_NOTFOUND, newAccountAutoCreateDefaults.getKcUnit());
413                return false;
414            }
415        }
416    
417    
418        /**
419         * Sets the contractsAndGrantsModuleService attribute value.
420         * 
421         * @param contractsAndGrantsModuleService The contractsAndGrantsModuleService to set.
422         */
423        public void setContractsAndGrantsModuleService(ContractsAndGrantsModuleService contractsAndGrantsModuleService) {
424            this.contractsAndGrantsModuleService = contractsAndGrantsModuleService;
425        }
426    
427    
428        public ParameterService getParameterService() {
429            if (parameterService == null) {
430                parameterService = SpringContext.getBean(ParameterService.class);
431            }
432            return parameterService;
433        }
434        
435    }