View Javadoc
1   /*
2    * Copyright 2008 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.coa.document.validation.impl;
17  
18  import java.math.BigDecimal;
19  import java.util.HashMap;
20  import java.util.HashSet;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Set;
24  
25  import org.apache.commons.lang.StringUtils;
26  import org.kuali.ole.coa.businessobject.Account;
27  import org.kuali.ole.coa.businessobject.Chart;
28  import org.kuali.ole.coa.businessobject.IndirectCostRecoveryRate;
29  import org.kuali.ole.coa.businessobject.IndirectCostRecoveryRateDetail;
30  import org.kuali.ole.coa.businessobject.ObjectCode;
31  import org.kuali.ole.coa.businessobject.SubAccount;
32  import org.kuali.ole.coa.businessobject.SubObjectCode;
33  import org.kuali.ole.gl.GeneralLedgerConstants;
34  import org.kuali.ole.sys.OLEConstants;
35  import org.kuali.ole.sys.OLEKeyConstants;
36  import org.kuali.ole.sys.OLEPropertyConstants;
37  import org.kuali.ole.sys.businessobject.SystemOptions;
38  import org.kuali.ole.sys.context.SpringContext;
39  import org.kuali.rice.core.api.util.RiceKeyConstants;
40  import org.kuali.rice.kns.document.MaintenanceDocument;
41  import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
42  import org.kuali.rice.kns.service.DataDictionaryService;
43  import org.kuali.rice.krad.bo.PersistableBusinessObject;
44  import org.kuali.rice.krad.util.GlobalVariables;
45  import org.kuali.rice.krad.util.KRADConstants;
46  
47  
48  public class IndirectCostRecoveryRateRule extends MaintenanceDocumentRuleBase {
49  
50      protected static final String MAINTAINABLE_DETAIL_ERROR_PATH = KRADConstants.MAINTENANCE_NEW_MAINTAINABLE + "indirectCostRecoveryRateDetails";
51      protected static final String MAINTAINABLE_DETAIL_ADDLINE_ERROR_PATH = "add.indirectCostRecoveryRateDetails";
52      
53      protected IndirectCostRecoveryRate indirectCostRecoveryRate;
54      protected IndirectCostRecoveryRateDetail indirectCostRecoveryRateDetail;
55      protected List<IndirectCostRecoveryRateDetail> indirectCostRecoveryRateDetails;
56      
57      public void setupConvenienceObjects() {
58          indirectCostRecoveryRate = (IndirectCostRecoveryRate) super.getNewBo();
59          indirectCostRecoveryRateDetails = indirectCostRecoveryRate.getIndirectCostRecoveryRateDetails();
60      }
61      
62      @Override
63      protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
64          boolean success = true;
65  
66          BigDecimal awardIndrCostRcvyRatePctCredits = new BigDecimal(0);
67          BigDecimal awardIndrCostRcvyRatePctDebits = new BigDecimal(0);
68          
69          if (!processYear()) {
70              success = false;
71          }
72          else {
73              for(int i = 0;i<indirectCostRecoveryRateDetails.size();i++) {
74                  if(indirectCostRecoveryRateDetails.get(i).isActive()) {
75                      GlobalVariables.getMessageMap().addToErrorPath(MAINTAINABLE_DETAIL_ERROR_PATH + "[" + i + "]");
76                      success &= processCollectionLine(indirectCostRecoveryRateDetails.get(i));
77                      GlobalVariables.getMessageMap().removeFromErrorPath(MAINTAINABLE_DETAIL_ERROR_PATH + "[" + i + "]");
78                      
79                      if(indirectCostRecoveryRateDetails.get(i).isActive()) {
80                          if(OLEConstants.GL_CREDIT_CODE.equals(indirectCostRecoveryRateDetails.get(i).getTransactionDebitIndicator())) {
81                              awardIndrCostRcvyRatePctCredits = awardIndrCostRcvyRatePctCredits.add(indirectCostRecoveryRateDetails.get(i).getAwardIndrCostRcvyRatePct());
82                          }
83                          if(OLEConstants.GL_DEBIT_CODE.equals(indirectCostRecoveryRateDetails.get(i).getTransactionDebitIndicator())) {
84                              awardIndrCostRcvyRatePctDebits = awardIndrCostRcvyRatePctDebits.add(indirectCostRecoveryRateDetails.get(i).getAwardIndrCostRcvyRatePct());
85                          }                    
86                      }
87                  }
88              }
89          }
90          success &= checkCreditsAndDebits(awardIndrCostRcvyRatePctCredits, awardIndrCostRcvyRatePctDebits);
91          
92          return success;
93      }
94      
95      public boolean checkCreditsAndDebits(BigDecimal credits, BigDecimal debits) {
96          boolean success = true;
97  
98          // global errors, in KeyConstants or KFSconstants or something, use one for the top of the page (mark doc once)
99          // include the key word active (informing that only active records are considered)
100         if(!(credits.compareTo(debits) == 0)) {
101             GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRADConstants.GLOBAL_ERRORS, OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_RATE_PERCENTS_NOT_EQUAL,
102                     SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.AWARD_INDR_COST_RCVY_RATE_PCT));
103             success = false;
104         }
105 
106         return success;
107     }
108  
109     @Override
110     public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) {
111         boolean success = true;
112         IndirectCostRecoveryRateDetail item = (IndirectCostRecoveryRateDetail) line;
113         success &= processCollectionLine(item);
114         return success;
115     }
116     
117     public boolean processCollectionLine(IndirectCostRecoveryRateDetail item) {
118         boolean success = true;
119         
120         success &= validateWildcards(item);
121         if(success) {
122             success &= checkExistence(item) && checkRateFormat(item);
123         }
124                 
125         return success;
126     }
127     
128     public boolean checkExistence(IndirectCostRecoveryRateDetail item) {
129         boolean success = 
130             processYear() && 
131             processChart(item) && 
132             processAccount(item) && 
133             processSubAccount(item) && 
134             processObjectCode(item) && 
135             processSubObjectCode(item);
136         return success;
137     }
138     
139     public boolean processYear() {
140         boolean success = true;
141         Map pkMap = new HashMap();
142         Integer year = indirectCostRecoveryRate.getUniversityFiscalYear();
143         pkMap.put(OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
144         if(!checkExistenceFromTable(SystemOptions.class, pkMap)) {
145             GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE + OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR,
146                     RiceKeyConstants.ERROR_EXISTENCE, 
147                     SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRate.class, OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR));
148             success = false;
149         }
150         return success;
151     }
152     
153     protected boolean processChart(IndirectCostRecoveryRateDetail item) {
154         boolean success = true;
155         Map pkMap = new HashMap();
156         String chart = item.getChartOfAccountsCode();
157         if(StringUtils.isNotBlank(chart)) {
158             if(!propertyIsWildcard(chart)) {
159                 pkMap.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, chart);
160                 if(!checkExistenceFromTable(Chart.class, pkMap)) {
161                     logErrorUtility(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, RiceKeyConstants.ERROR_EXISTENCE);
162                     success = false;
163                 }
164             }
165         }
166         return success;
167     }
168     
169     protected boolean processAccount(IndirectCostRecoveryRateDetail item) {
170         boolean success = true;
171         Map pkMap = new HashMap();
172         String chart = item.getChartOfAccountsCode();
173         String acct = item.getAccountNumber();
174         if(StringUtils.isNotBlank(acct)) {
175             if(!propertyIsWildcard(chart)) {
176                 pkMap.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, chart);    
177             }
178             if(!propertyIsWildcard(acct)) {
179                 pkMap.put(OLEPropertyConstants.ACCOUNT_NUMBER, acct);
180                 if(!checkExistenceFromTable(Account.class, pkMap)) {
181                     logErrorUtility(OLEPropertyConstants.ACCOUNT_NUMBER, RiceKeyConstants.ERROR_EXISTENCE);
182                     success = false;
183                 }
184             }
185         }
186         return success;
187     }
188     
189     protected boolean processSubAccount(IndirectCostRecoveryRateDetail item) {
190         boolean success = true;
191         Map pkMap = new HashMap();
192         String chart = item.getChartOfAccountsCode();
193         String acct = item.getAccountNumber();
194         String subAcct = item.getSubAccountNumber();
195         if(StringUtils.isNotBlank(subAcct) && !StringUtils.containsOnly(subAcct, "-")) { // if doesn't contain only dashes
196             if(!propertyIsWildcard(chart)) {
197                 pkMap.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, chart);    
198             }
199             if(!propertyIsWildcard(acct)) {
200                 pkMap.put(OLEPropertyConstants.ACCOUNT_NUMBER, acct);    
201             }
202             if(!propertyIsWildcard(subAcct) && StringUtils.isNotBlank(subAcct) && !StringUtils.containsOnly(subAcct, "-")) {
203                 pkMap.put(OLEPropertyConstants.SUB_ACCOUNT_NUMBER, subAcct);
204                 if(!checkExistenceFromTable(SubAccount.class, pkMap)) {
205                     logErrorUtility(OLEPropertyConstants.SUB_ACCOUNT_NUMBER, RiceKeyConstants.ERROR_EXISTENCE);
206                     success = false;
207                 }
208             }
209         }
210         return success;
211     }
212     
213     protected boolean processObjectCode(IndirectCostRecoveryRateDetail item) {
214         boolean success = true;
215         Map pkMap = new HashMap();
216         Integer year = indirectCostRecoveryRate.getUniversityFiscalYear();
217         String chart = item.getChartOfAccountsCode();
218         String objCd = item.getFinancialObjectCode();
219         pkMap.put(OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
220         if(StringUtils.isNotBlank(objCd)) {
221             if(!propertyIsWildcard(chart)) {
222                 pkMap.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, chart);    
223             }
224             if(!propertyIsWildcard(objCd)) {
225                 pkMap.put(OLEPropertyConstants.FINANCIAL_OBJECT_CODE, objCd);
226                 if(!checkExistenceFromTable(ObjectCode.class, pkMap)) {
227                     logErrorUtility(OLEPropertyConstants.FINANCIAL_OBJECT_CODE, RiceKeyConstants.ERROR_EXISTENCE);
228                     success = false;
229                 }
230             }
231         }
232         return success;
233     }
234     
235     protected boolean processSubObjectCode(IndirectCostRecoveryRateDetail item) { // chart being a wildcard implies account number being a wildcard, redundant checking?
236         boolean success = true;
237         Map pkMap = new HashMap();
238         Integer year = indirectCostRecoveryRate.getUniversityFiscalYear();
239         String chart = item.getChartOfAccountsCode();
240         String acct = item.getAccountNumber();
241         String objCd = item.getFinancialObjectCode();
242         String subObjCd = item.getFinancialSubObjectCode();
243         if(StringUtils.isNotBlank(subObjCd) && !propertyIsWildcard(subObjCd) && !StringUtils.containsOnly(subObjCd, "-")) {
244             pkMap.put(OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
245             if(!propertyIsWildcard(chart)) {
246                 pkMap.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, chart);    
247             }
248             if(!propertyIsWildcard(acct)) {
249                 pkMap.put(OLEPropertyConstants.ACCOUNT_NUMBER, acct);    
250             }
251             if(!propertyIsWildcard(objCd)) {
252                 pkMap.put(OLEPropertyConstants.FINANCIAL_OBJECT_CODE, objCd);
253             }
254             pkMap.put(OLEPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, subObjCd);
255             if(!GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(subObjCd) && !checkExistenceFromTable(SubObjectCode.class, pkMap)) {
256                 logErrorUtility(OLEPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, RiceKeyConstants.ERROR_EXISTENCE);
257                 success = false;
258             }
259         }
260         return success;
261     }
262     
263     public boolean checkExistenceFromTable(Class clazz, Map fieldValues) {
264         return getBoService().countMatching(clazz, fieldValues) != 0;
265     }
266     
267     public boolean validateWildcards(IndirectCostRecoveryRateDetail item) {
268         boolean success = false;
269         if(!itemUsesWildcard(item) || (itemUsesWildcard(item) && itemPassesWildcardRules(item))) {
270             success = true;
271         }
272         return success;
273     }
274     
275     public boolean itemPassesWildcardRules(IndirectCostRecoveryRateDetail item) {
276         boolean success = false;
277         String[] wildcards = {GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY, GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT};
278         
279         success = !itemUsesWildcard(item) || checkWildcardRules(item);
280         
281         return success;
282     }
283     
284     public boolean itemUsesWildcard(IndirectCostRecoveryRateDetail item) {
285         boolean success = false;
286         String chart = item.getChartOfAccountsCode();
287         String acct = item.getAccountNumber();
288         String subAcct = item.getSubAccountNumber();
289         String objCd = item.getFinancialObjectCode();
290         String subObjCd = item.getFinancialSubObjectCode();
291         String[] fields = {chart,acct,subAcct,objCd,subObjCd};
292         
293         for(int i=0;i<fields.length;i++) {
294             success |= propertyIsWildcard(fields[i]);
295         }
296         
297         return success;
298     }
299     
300     public boolean propertyIsWildcard(String property) {
301         return GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(property) || GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(property);
302     }
303 
304     protected boolean checkAccountNumberWildcardRules(IndirectCostRecoveryRateDetail item) {
305         String accountNumber = item.getAccountNumber();
306         boolean success = true;
307         if (!accountNumber.equals(item.getChartOfAccountsCode())) {
308             GlobalVariables.getMessageMap().putError(
309                     OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE,
310                     OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARDS_MUST_MATCH,
311                     SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.ACCOUNT_NUMBER),
312                     SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE)
313                     );
314             success = false;
315         }
316         
317         String subAccountNumber = item.getSubAccountNumber();
318         
319         // If # is entered on account, then # "must" be entered for chart and sub account "must" be dashes.
320         if (GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(accountNumber)) {
321             if (!GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(item.getChartOfAccountsCode()) && !StringUtils.containsOnly(subAccountNumber, OLEConstants.DASH)) {
322                 GlobalVariables.getMessageMap().putError(
323                         OLEPropertyConstants.SUB_ACCOUNT_NUMBER, 
324                         OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_FIELD_MUST_BE_DASHES,
325                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.ACCOUNT_NUMBER),
326                         GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT,
327                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.SUB_ACCOUNT_NUMBER));
328                 success = false;
329             }
330         }
331         
332         if (GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(accountNumber)) {
333             if (!(StringUtils.equals(GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY, subAccountNumber) || !StringUtils.containsOnly(subAccountNumber, OLEConstants.DASH))) {
334                 GlobalVariables.getMessageMap().putError(OLEPropertyConstants.SUB_ACCOUNT_NUMBER, 
335                         OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_ACCOUNT_USE_EXPENDITURE_ENTRY_WILDCARD_RESTRICTION_ON_SUB_ACCOUNT);
336                 success = false;
337             }
338         }
339         return success;
340     }
341     
342     protected boolean checkAccountNumberNotWildcardRules(IndirectCostRecoveryRateDetail item) {
343         boolean success = true;
344         if (propertyIsWildcard(item.getSubAccountNumber())) {
345             if (!GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(item.getSubAccountNumber())) {
346                 GlobalVariables.getMessageMap().putError(OLEPropertyConstants.SUB_ACCOUNT_NUMBER, OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_CANNOT_BE_WILDCARD,
347                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.SUB_ACCOUNT_NUMBER),
348                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.ACCOUNT_NUMBER));
349                 success = false;
350             }
351         }
352         return success;
353     }
354 
355     protected boolean checkObjectCodeWildcardRules(IndirectCostRecoveryRateDetail item) {
356         String financialObjectCode = item.getFinancialObjectCode();
357         boolean success = true;
358         if (propertyIsWildcard(financialObjectCode)) {
359             if (GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(financialObjectCode)) {
360                 GlobalVariables.getMessageMap().putError(
361                         OLEPropertyConstants.FINANCIAL_OBJECT_CODE,
362                         OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARD_NOT_VALID,
363                         GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT,
364                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.FINANCIAL_OBJECT_CODE),
365                         GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY
366                         );
367                 success = false;
368             } 
369             else {
370                 if (!GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(item.getChartOfAccountsCode())) {
371                     GlobalVariables.getMessageMap().putError(
372                             OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE,
373                             OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARDS_MUST_MATCH,
374                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.FINANCIAL_OBJECT_CODE),
375                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE)
376                             );
377                     success = false;
378                 }
379             }
380         }
381         return success;
382     }
383     
384     protected boolean checkSubObjectWildcardRules(IndirectCostRecoveryRateDetail item) {
385         String financialSubObjectCode = item.getFinancialSubObjectCode();
386         boolean success = true;
387         if (propertyIsWildcard(financialSubObjectCode)) {
388             if (GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(financialSubObjectCode)) {
389                 GlobalVariables.getMessageMap().putError(
390                         OLEPropertyConstants.FINANCIAL_SUB_OBJECT_CODE,
391                         OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARD_NOT_VALID,
392                         GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT,
393                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.FINANCIAL_SUB_OBJECT_CODE),
394                         GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY
395                         );
396                 success = false;
397             }
398             else {
399                 if (!GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(item.getChartOfAccountsCode())) {
400                     GlobalVariables.getMessageMap().putError(
401                             OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE,
402                             OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARDS_MUST_MATCH,
403                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.FINANCIAL_SUB_OBJECT_CODE),
404                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE)
405                             );
406                     success = false;
407                 }
408                 if (!GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(item.getAccountNumber())) {
409                     GlobalVariables.getMessageMap().putError(
410                             OLEPropertyConstants.ACCOUNT_NUMBER,
411                             OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARDS_MUST_MATCH,
412                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.FINANCIAL_SUB_OBJECT_CODE),
413                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.ACCOUNT_NUMBER)
414                             );
415                     success = false;
416                 }
417                 if (!GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(item.getFinancialObjectCode())) {
418                     GlobalVariables.getMessageMap().putError(
419                             OLEPropertyConstants.FINANCIAL_OBJECT_CODE,
420                             OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARDS_MUST_MATCH,
421                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.FINANCIAL_SUB_OBJECT_CODE),
422                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.FINANCIAL_OBJECT_CODE)
423                             );
424                     success = false;
425                 }
426             }
427         }
428         return success;
429     }
430     
431     protected boolean checkSubAccountWildcardRules(IndirectCostRecoveryRateDetail item) {
432         boolean success = true;
433         String subAccountNumber = item.getSubAccountNumber();
434         if (GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT.equals(subAccountNumber)) {
435             GlobalVariables.getMessageMap().putError(
436                     OLEPropertyConstants.SUB_ACCOUNT_NUMBER,
437                     OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARD_NOT_VALID,
438                     GeneralLedgerConstants.PosterService.SYMBOL_USE_ICR_FROM_ACCOUNT,
439                     SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.SUB_ACCOUNT_NUMBER),
440                     GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY
441                     );
442             success = false;
443         }
444         else {
445             if (!GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(item.getChartOfAccountsCode())) {
446                 GlobalVariables.getMessageMap().putError(
447                         OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE,
448                         OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARDS_MUST_MATCH,
449                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.SUB_ACCOUNT_NUMBER),
450                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE)
451                         );
452                 success = false;
453             }
454             if (!GeneralLedgerConstants.PosterService.SYMBOL_USE_EXPENDITURE_ENTRY.equals(item.getAccountNumber())) {
455                 GlobalVariables.getMessageMap().putError(
456                         OLEPropertyConstants.ACCOUNT_NUMBER,
457                         OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_WILDCARDS_MUST_MATCH,
458                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.SUB_ACCOUNT_NUMBER),
459                         SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.ACCOUNT_NUMBER)
460                         );
461                 success = false;
462             }
463             
464         }
465         return success;
466     }
467     
468     /*
469      ** If @ is entered on chart, then @ "must" be entered for account and the sub account "must" be either @ or dashes. 
470      ** If @ is entered on account, then @ "must" be entered for chart and "may" be entered for sub account.
471      ** If @ is entered on sub account, then @ "must" be entered for chart and account.
472      ** If @ is entered on object code, then @ "must" be entered for chart and "may" be entered for account, sub account and sub object. 
473      * (This rule is the murkiest as enter @ in account, sub account, and sub object kicks of some of the other rules in this section).
474      ** If @ is entered on sub object code, then @ "must" be entered for chart, account, and object code and "may" be entered for sub account.
475 
476      ** If # is entered on chart, then # "must" be entered for account and sub account "must" be dashes.
477      ** If # is entered on account, then # "must" be entered for chart and sub account "must" be dashes.
478      ** # can not be entered on the sub account.
479      ** # can not be entered on the object code.
480      ** # can not be entered on the sub object code.
481      * 
482      */
483     
484     public boolean checkWildcardRules(IndirectCostRecoveryRateDetail item) {
485         boolean success = checkAtMostOneWildcardUsed(item);
486         if (success) {
487             if (propertyIsWildcard(item.getFinancialObjectCode())) {
488                 success &= checkObjectCodeWildcardRules(item); // verified
489             }
490             else {
491             }
492             if (propertyIsWildcard(item.getAccountNumber())) {
493                 success &= checkAccountNumberWildcardRules(item); // verified
494             }
495             else {
496                 success &= checkAccountNumberNotWildcardRules(item);
497             }
498             if (propertyIsWildcard(item.getFinancialSubObjectCode())) {
499                 success &= checkSubObjectWildcardRules(item); // verified
500             }
501             
502             if (propertyIsWildcard(item.getSubAccountNumber())) {
503                 success &= checkSubAccountWildcardRules(item); // verified
504             }
505             
506             if (!(propertyIsWildcard(item.getFinancialObjectCode()) || propertyIsWildcard(item.getAccountNumber()))) {
507                 // chart code can't be the only wildcard on the item
508                 if (success && propertyIsWildcard(item.getChartOfAccountsCode())) {
509                     success = false;
510                     GlobalVariables.getMessageMap().putError(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_CHART_CODE_NOT_ONLY_WILDCARD,
511                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE),
512                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.ACCOUNT_NUMBER),
513                             SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, OLEPropertyConstants.FINANCIAL_OBJECT_CODE));
514                 }
515             }
516         }
517         return success;
518     }
519 
520     protected boolean checkAtMostOneWildcardUsed(IndirectCostRecoveryRateDetail item) {
521         String chart = item.getChartOfAccountsCode();
522         String acct = item.getAccountNumber();
523         String subAcct = item.getSubAccountNumber();
524         String objCd = item.getFinancialObjectCode();
525         String subObjCd = item.getFinancialSubObjectCode();
526         
527         boolean success = true;
528         String errorPropertyName = null;
529         
530         Set<String> wildcards = new HashSet<String>();
531         if (propertyIsWildcard(chart)) {
532             wildcards.add(chart);
533             errorPropertyName = OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE;
534         }
535         if (success && propertyIsWildcard(acct)) {
536             wildcards.add(acct);
537             if (wildcards.size() > 1) {
538                 success = false;
539                 errorPropertyName = OLEPropertyConstants.ACCOUNT_NUMBER;
540             }
541         }
542         if (success && propertyIsWildcard(subAcct)) {
543             wildcards.add(subAcct);
544             if (wildcards.size() > 1) {
545                 success = false;
546                 errorPropertyName = OLEPropertyConstants.SUB_ACCOUNT_NUMBER;
547             }
548         }
549         if (success && propertyIsWildcard(objCd)) {
550             wildcards.add(objCd);
551             if (wildcards.size() > 1) {
552                 success = false;
553                 errorPropertyName = OLEPropertyConstants.FINANCIAL_OBJECT_CODE;
554             }
555         }
556         if (success && propertyIsWildcard(subObjCd)) {
557             wildcards.add(subObjCd);
558             if (wildcards.size() > 1) {
559                 success = false;
560                 errorPropertyName = OLEPropertyConstants.FINANCIAL_SUB_OBJECT_CODE;
561             }
562         }
563         
564         if (!success) {
565             GlobalVariables.getMessageMap().putError(
566                     errorPropertyName,
567                     OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_MULTIPLE_WILDCARDS_ON_ITEM);
568         }
569         return success;
570     }
571     
572     public boolean checkRateFormat(IndirectCostRecoveryRateDetail item) {
573         boolean success = true;
574         BigDecimal zero = new BigDecimal(0.00);
575         if(!(item.getAwardIndrCostRcvyRatePct() == null)) {
576             if(item.getAwardIndrCostRcvyRatePct().scale() > 3) {
577                 logErrorUtility(OLEPropertyConstants.AWARD_INDR_COST_RCVY_RATE_PCT, OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_RATE_PERCENT_INVALID_FORMAT_SCALE);
578                 success = false;
579             }
580             if(item.getAwardIndrCostRcvyRatePct().compareTo(zero) < 0) {
581                 logErrorUtility(OLEPropertyConstants.AWARD_INDR_COST_RCVY_RATE_PCT, OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_RATE_PERCENT_INVALID_FORMAT_ZERO);
582                 success = false;
583             }            
584         } else {
585             
586         }
587         return success;
588     }
589     
590     public void logErrorUtility(String propertyName, String errorKey) {
591         GlobalVariables.getMessageMap().putError(propertyName, errorKey, SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(IndirectCostRecoveryRateDetail.class, propertyName));
592     }
593     
594 }