1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.ole.coa.document.validation.impl;
17  
18  import java.util.ArrayList;
19  import java.util.Collection;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.commons.lang.StringUtils;
25  import org.kuali.ole.coa.businessobject.A21IndirectCostRecoveryAccount;
26  import org.kuali.ole.coa.businessobject.A21SubAccount;
27  import org.kuali.ole.coa.businessobject.IndirectCostRecoveryAccount;
28  import org.kuali.ole.coa.businessobject.IndirectCostRecoveryRateDetail;
29  import org.kuali.ole.coa.businessobject.SubAccount;
30  import org.kuali.ole.coa.service.SubFundGroupService;
31  import org.kuali.ole.sys.OLEConstants;
32  import org.kuali.ole.sys.OLEKeyConstants;
33  import org.kuali.ole.sys.OLEPropertyConstants;
34  import org.kuali.ole.sys.context.SpringContext;
35  import org.kuali.ole.sys.service.UniversityDateService;
36  import org.kuali.rice.kns.document.MaintenanceDocument;
37  import org.kuali.rice.kns.service.DataDictionaryService;
38  import org.kuali.rice.krad.util.ObjectUtils;
39  
40  
41  
42  
43  public class SubAccountRule extends IndirectCostRecoveryAccountsRule {
44  
45      protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SubAccountRule.class);
46  
47      protected SubAccount oldSubAccount;
48      protected SubAccount newSubAccount;
49  
50      
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61      protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) {
62          LOG.debug("Entering processCustomApproveDocumentBusinessRules()");
63  
64          
65          boolean success = checkForPartiallyEnteredReportingFields();
66  
67          
68          success &= checkCgRules(document);
69  
70          return success;
71      }
72  
73      
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84      protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
85          LOG.debug("Entering processCustomRouteDocumentBusinessRules()");
86  
87          boolean success = true;
88  
89          
90          success &= checkForPartiallyEnteredReportingFields();
91  
92          
93          success &= checkCgRules(document);
94  
95          success &= super.processCustomRouteDocumentBusinessRules(document);
96          return success;
97      }
98  
99      
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 
110     protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
111 
112         boolean success = true;
113 
114         LOG.debug("Entering processCustomSaveDocumentBusinessRules()");
115 
116         
117         success &= checkForPartiallyEnteredReportingFields();
118 
119         
120         success &= checkCgRules(document);
121 
122         return success;
123     }
124 
125     
126 
127 
128 
129 
130 
131 
132     public void setupConvenienceObjects() {
133 
134         
135         oldSubAccount = (SubAccount) super.getOldBo();
136         refreshSubObjects(oldSubAccount);
137 
138         
139         newSubAccount = (SubAccount) super.getNewBo();
140         refreshSubObjects(newSubAccount);
141         
142         
143         if (newSubAccount.getA21SubAccount() != null){
144             List<IndirectCostRecoveryAccount> icrAccountList = new ArrayList<IndirectCostRecoveryAccount>(
145                     newSubAccount.getA21SubAccount().getA21ActiveIndirectCostRecoveryAccounts());
146             setActiveIndirectCostRecoveryAccountList(icrAccountList);
147             setBoFieldPath(OLEPropertyConstants.A21INDIRECT_COST_RECOVERY_ACCOUNTS);
148         }
149     }
150     
151     
152 
153 
154 
155 
156     void refreshSubObjects(SubAccount subaccount) {
157         if (subaccount != null) {
158             if (subaccount.getA21SubAccount() != null) {
159                 subaccount.getA21SubAccount().refreshNonUpdateableReferences();
160                 
161 
162 
163 
164 
165 
166             }
167         }
168     }
169 
170     
171 
172 
173 
174 
175     protected boolean checkForPartiallyEnteredReportingFields() {
176 
177         LOG.debug("Entering checkExistenceAndActive()");
178 
179         boolean success = true;
180         boolean allReportingFieldsEntered = false;
181         boolean anyReportingFieldsEntered = false;
182 
183         
184         if (StringUtils.isNotEmpty(newSubAccount.getFinancialReportChartCode()) && StringUtils.isNotEmpty(newSubAccount.getFinReportOrganizationCode()) && StringUtils.isNotEmpty(newSubAccount.getFinancialReportingCode())) {
185             allReportingFieldsEntered = true;
186         }
187 
188         
189         if (StringUtils.isNotEmpty(newSubAccount.getFinancialReportChartCode()) || StringUtils.isNotEmpty(newSubAccount.getFinReportOrganizationCode()) || StringUtils.isNotEmpty(newSubAccount.getFinancialReportingCode())) {
190             anyReportingFieldsEntered = true;
191         }
192 
193         
194         
195         if (anyReportingFieldsEntered && !allReportingFieldsEntered) {
196             putGlobalError(OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_RPTCODE_ALL_FIELDS_IF_ANY_FIELDS);
197             success &= false;
198         }
199 
200         return success;
201     }
202 
203     
204 
205 
206 
207 
208 
209 
210 
211 
212 
213 
214 
215     protected boolean checkCgRules(MaintenanceDocument document) {
216 
217         boolean success = true;
218 
219         
220         boolean a21SubAccountRefreshed = false;
221         if (ObjectUtils.isNotNull(newSubAccount.getAccount())) {
222             if (ObjectUtils.isNotNull(newSubAccount.getAccount().getSubFundGroup())) {
223 
224                 
225                 if (!SpringContext.getBean(SubFundGroupService.class).isForContractsAndGrants(newSubAccount.getAccount().getSubFundGroup())) {
226 
227                     
228                     if (checkCgCostSharingIsEmpty() == false) {
229                         putFieldError("a21SubAccount.costShareChartOfAccountCode", OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_NON_FUNDED_ACCT_CS_INVALID, new String[] { SpringContext.getBean(SubFundGroupService.class).getContractsAndGrantsDenotingAttributeLabel(), SpringContext.getBean(SubFundGroupService.class).getContractsAndGrantsDenotingValueForMessage() });
230                         success = false;
231                     }
232 
233                     if (checkCgIcrIsEmpty() == false) {
234                         putFieldError("a21SubAccount.indirectCostRecoveryTypeCode", OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_NON_FUNDED_ACCT_ICR_INVALID, new String[] { SpringContext.getBean(SubFundGroupService.class).getContractsAndGrantsDenotingAttributeLabel(), SpringContext.getBean(SubFundGroupService.class).getContractsAndGrantsDenotingValueForMessage() });
235                         success = false;
236                     }
237 
238                     
239                     if (!ObjectUtils.isNull(newSubAccount.getA21SubAccount())) {
240                         
241                         
242                         newSubAccount.getA21SubAccount().refreshNonUpdateableReferences();
243                         a21SubAccountRefreshed = true;
244                         if (StringUtils.isEmpty(newSubAccount.getA21SubAccount().getSubAccountTypeCode()) || !newSubAccount.getA21SubAccount().getSubAccountTypeCode().equals(OLEConstants.SubAccountType.EXPENSE)) {
245                             putFieldError("a21SubAccount.subAccountTypeCode", OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_NON_FUNDED_ACCT_SUB_ACCT_TYPE_CODE_INVALID, new String[] { SpringContext.getBean(SubFundGroupService.class).getContractsAndGrantsDenotingAttributeLabel(), SpringContext.getBean(SubFundGroupService.class).getContractsAndGrantsDenotingValueForMessage() });
246                             success = false;
247                         }
248                     }
249 
250                     return success;
251                 }
252             }
253         }
254 
255         A21SubAccount a21 = newSubAccount.getA21SubAccount();
256         
257         
258         if (ObjectUtils.isNull(a21)) {
259             return success;
260         }
261 
262         
263 
264         
265         
266         
267         
268         
269         if (!a21SubAccountRefreshed) {
270             
271             List<A21IndirectCostRecoveryAccount>icrAccounts =a21.getA21IndirectCostRecoveryAccounts(); 
272             a21.refresh();
273             a21.setA21IndirectCostRecoveryAccounts(icrAccounts);
274             
275         }
276 
277         
278         if (!OLEConstants.SubAccountType.ELIGIBLE_SUB_ACCOUNT_TYPE_CODES.contains(a21.getSubAccountTypeCode())) {
279             putFieldError("a21SubAccount.subAccountTypeCode", OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_INVALI_SUBACCOUNT_TYPE_CODES, OLEConstants.SubAccountType.ELIGIBLE_SUB_ACCOUNT_TYPE_CODES.toString());
280             success &= false;
281         }
282 
283         
284         String cgA21TypeCode = a21.getSubAccountTypeCode();
285 
286         
287         if (OLEConstants.SubAccountType.COST_SHARE.trim().equalsIgnoreCase(StringUtils.trim(cgA21TypeCode))) {
288             success &= checkCgCostSharingRules();
289         }
290 
291         
292         if (OLEConstants.SubAccountType.EXPENSE.trim().equals(StringUtils.trim(cgA21TypeCode))) {
293             success &= checkCgIcrRules();
294         }
295 
296         return success;
297     }
298 
299     
300 
301 
302 
303 
304 
305 
306     protected boolean checkCgCostSharingRules() {
307 
308         boolean success = true;
309         boolean allFieldsSet = false;
310 
311         A21SubAccount a21 = newSubAccount.getA21SubAccount();
312 
313         
314         if (StringUtils.isNotEmpty(a21.getCostShareChartOfAccountCode()) && StringUtils.isNotEmpty(a21.getCostShareSourceAccountNumber())) {
315             allFieldsSet = true;
316         }
317 
318         
319         success &= checkEmptyBOField("a21SubAccount.costShareChartOfAccountCode", a21.getCostShareChartOfAccountCode(), "Cost Share Chart of Accounts Code");
320         success &= checkEmptyBOField("a21SubAccount.costShareSourceAccountNumber", a21.getCostShareSourceAccountNumber(), "Cost Share AccountNumber");
321 
322         
323         if (allFieldsSet) {
324             if (ObjectUtils.isNull(a21.getCostShareAccount())) {
325                 putFieldError("a21SubAccount.costShareSourceAccountNumber", OLEKeyConstants.ERROR_EXISTENCE, getDisplayName("a21SubAccount.costShareSourceAccountNumber"));
326                 success &= false;
327             }
328         }
329 
330         
331         if (allFieldsSet && StringUtils.isNotBlank(a21.getCostShareSourceSubAccountNumber())) {
332             if (ObjectUtils.isNull(a21.getCostShareSourceSubAccount())) {
333                 putFieldError("a21SubAccount.costShareSourceSubAccountNumber", OLEKeyConstants.ERROR_EXISTENCE, getDisplayName("a21SubAccount.costShareSourceSubAccountNumber"));
334                 success &= false;
335             }
336         }
337 
338         
339         if (ObjectUtils.isNotNull(a21.getCostShareAccount())) {
340             if (ObjectUtils.isNotNull(a21.getCostShareAccount().getSubFundGroup())) {
341                 if (a21.getCostShareAccount().isForContractsAndGrants()) {
342                     putFieldError("a21SubAccount.costShareSourceAccountNumber", OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_COST_SHARE_ACCOUNT_MAY_NOT_BE_CG_FUNDGROUP, new String[] { SpringContext.getBean(SubFundGroupService.class).getContractsAndGrantsDenotingAttributeLabel(), SpringContext.getBean(SubFundGroupService.class).getContractsAndGrantsDenotingValueForMessage() });
343                     success &= false;
344                 }
345             }
346         }
347 
348         
349         if (checkCgIcrIsEmpty() == false) {
350             putFieldError("a21SubAccount.indirectCostRecoveryTypeCode", OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_ICR_SECTION_INVALID, a21.getSubAccountTypeCode());
351             success &= false;
352         }
353 
354         return success;
355     }
356 
357     
358 
359 
360 
361 
362 
363     protected boolean checkCgIcrRules() {
364         A21SubAccount a21 = newSubAccount.getA21SubAccount();
365         if(ObjectUtils.isNull(a21)) {
366             return true;
367         }
368 
369         boolean success = true;
370         
371         
372         if (StringUtils.isNotEmpty(a21.getIndirectCostRecoveryTypeCode())) {
373             if (ObjectUtils.isNull(a21.getIndirectCostRecoveryType())) {
374                 putFieldError("a21SubAccount.indirectCostRecoveryTypeCode", OLEKeyConstants.ERROR_EXISTENCE, "ICR Type Code: " + a21.getIndirectCostRecoveryTypeCode());
375                 success = false;
376             }
377         }
378 
379         
380         if (StringUtils.isNotEmpty(a21.getFinancialIcrSeriesIdentifier())) {            
381             String fiscalYear = StringUtils.EMPTY + SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
382             String icrSeriesId = a21.getFinancialIcrSeriesIdentifier();
383             
384             Map<String, String> pkMap = new HashMap<String, String>();
385             pkMap.put(OLEPropertyConstants.UNIVERSITY_FISCAL_YEAR, fiscalYear);
386             pkMap.put(OLEPropertyConstants.FINANCIAL_ICR_SERIES_IDENTIFIER, icrSeriesId);
387             Collection<IndirectCostRecoveryRateDetail> icrRateDetails = getBoService().findMatching(IndirectCostRecoveryRateDetail.class, pkMap);
388             
389             if (ObjectUtils.isNull(icrRateDetails) || icrRateDetails.isEmpty()) {
390                 String label = SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(A21SubAccount.class, OLEPropertyConstants.FINANCIAL_ICR_SERIES_IDENTIFIER);
391                 putFieldError(OLEPropertyConstants.A21_SUB_ACCOUNT + "." + OLEPropertyConstants.FINANCIAL_ICR_SERIES_IDENTIFIER, OLEKeyConstants.ERROR_EXISTENCE, label + " (" + icrSeriesId + ")");
392                 success = false;
393             }
394             else {
395                 for(IndirectCostRecoveryRateDetail icrRateDetail : icrRateDetails) {
396                     if(ObjectUtils.isNull(icrRateDetail.getIndirectCostRecoveryRate())){                                
397                         putFieldError(OLEPropertyConstants.A21_SUB_ACCOUNT + "." + OLEPropertyConstants.FINANCIAL_ICR_SERIES_IDENTIFIER, OLEKeyConstants.IndirectCostRecovery.ERROR_DOCUMENT_ICR_RATE_NOT_FOUND, new String[]{fiscalYear, icrSeriesId});
398                         success = false;
399                         break;
400                     }
401                 }
402             }            
403         }
404 
405         
406         for (A21IndirectCostRecoveryAccount account : a21.getA21ActiveIndirectCostRecoveryAccounts()){
407             if (StringUtils.isNotBlank(account.getIndirectCostRecoveryAccountNumber())
408                 && StringUtils.isNotBlank(account.getIndirectCostRecoveryFinCoaCode())){
409                 if(ObjectUtils.isNull(account.getIndirectCostRecoveryAccount())){                                
410                     putFieldError(OLEPropertyConstants.A21INDIRECT_COST_RECOVERY_ACCOUNTS, OLEKeyConstants.ERROR_EXISTENCE, "ICR Account: " + account.getIndirectCostRecoveryFinCoaCode() + "-" + account.getIndirectCostRecoveryAccountNumber());
411                     success = false;
412                     break;
413                 }
414             }
415         }
416 
417         
418         if (checkCgCostSharingIsEmpty() == false) {
419             putFieldError("a21SubAccount.costShareChartOfAccountCode", OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_COST_SHARE_SECTION_INVALID, a21.getSubAccountTypeCode());
420 
421             success &= false;
422         }
423 
424         return success;
425     }
426 
427     
428 
429 
430 
431 
432     protected boolean checkCgCostSharingIsEmpty() {
433         boolean success = true;
434 
435         A21SubAccount newA21SubAccount = newSubAccount.getA21SubAccount();
436         if (ObjectUtils.isNotNull(newA21SubAccount)) {
437             success &= StringUtils.isEmpty(newA21SubAccount.getCostShareChartOfAccountCode());
438             success &= StringUtils.isEmpty(newA21SubAccount.getCostShareSourceAccountNumber());
439             success &= StringUtils.isEmpty(newA21SubAccount.getCostShareSourceSubAccountNumber());
440         }
441 
442         return success;
443     }
444 
445     
446 
447 
448 
449 
450     protected boolean checkCgIcrIsEmpty() {
451         boolean success = true;
452         
453         A21SubAccount newA21SubAccount = newSubAccount.getA21SubAccount();
454         if (ObjectUtils.isNotNull(newA21SubAccount)) {
455             success &= StringUtils.isEmpty(newA21SubAccount.getFinancialIcrSeriesIdentifier());
456             
457             success &= checkICRCollectionExist(false);
458             success &= StringUtils.isEmpty(newA21SubAccount.getIndirectCostRecoveryTypeCode());
459             
460             success &= StringUtils.isEmpty(newA21SubAccount.getOffCampusCode() ? "1" : "");
461         }
462 
463         return success;
464     }
465 
466     
467 
468 
469 
470 
471 
472 
473     protected boolean disallowAnyValues(String value, String fieldName) {
474         if (StringUtils.isNotEmpty(value)) {
475             putFieldError(fieldName, OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_NOT_AUTHORIZED_ENTER_CG_FIELDS, getDisplayName(fieldName));
476             return false;
477         }
478         return true;
479     }
480 
481     
482 
483 
484 
485 
486 
487 
488 
489 
490 
491     protected boolean disallowChangedValues(String oldValue, String newValue, String fieldName) {
492 
493         if (isFieldValueChanged(oldValue, newValue)) {
494             putFieldError(fieldName, OLEKeyConstants.ERROR_DOCUMENT_SUBACCTMAINT_NOT_AUTHORIZED_CHANGE_CG_FIELDS, getDisplayName(fieldName));
495             return false;
496         }
497         return true;
498     }
499 
500     
501 
502 
503 
504 
505 
506 
507     protected boolean isFieldValueChanged(String oldValue, String newValue) {
508 
509         if (StringUtils.isBlank(oldValue) && StringUtils.isBlank(newValue)) {
510             return false;
511         }
512 
513         if (StringUtils.isBlank(oldValue) && StringUtils.isNotBlank(newValue)) {
514             return true;
515         }
516 
517         if (StringUtils.isNotBlank(oldValue) && StringUtils.isBlank(newValue)) {
518             return true;
519         }
520 
521         if (!oldValue.trim().equalsIgnoreCase(newValue.trim())) {
522             return true;
523         }
524 
525         return false;
526     }
527 
528 
529     
530 
531 
532 
533 
534 
535     protected String getDisplayName(String propertyName) {
536         return getDdService().getAttributeLabel(SubAccount.class, propertyName);
537     }
538 
539 }