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 }