1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.kuali.kfs.module.ar.document.validation.impl;
20
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.commons.lang.StringUtils;
26 import org.kuali.kfs.module.ar.ArAuthorizationConstants;
27 import org.kuali.kfs.module.ar.ArConstants;
28 import org.kuali.kfs.module.ar.ArKeyConstants;
29 import org.kuali.kfs.module.ar.ArPropertyConstants;
30 import org.kuali.kfs.module.ar.businessobject.CashControlDetail;
31 import org.kuali.kfs.module.ar.businessobject.Customer;
32 import org.kuali.kfs.module.ar.businessobject.PaymentMedium;
33 import org.kuali.kfs.module.ar.document.CashControlDocument;
34 import org.kuali.kfs.module.ar.document.PaymentApplicationDocument;
35 import org.kuali.kfs.module.ar.document.authorization.CashControlDocumentPresentationController;
36 import org.kuali.kfs.module.ar.document.validation.AddCashControlDetailRule;
37 import org.kuali.kfs.module.ar.document.validation.DeleteCashControlDetailRule;
38 import org.kuali.kfs.module.ar.document.validation.GenerateReferenceDocumentRule;
39 import org.kuali.kfs.sys.KFSConstants;
40 import org.kuali.kfs.sys.KFSPropertyConstants;
41 import org.kuali.kfs.sys.businessobject.Bank;
42 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
43 import org.kuali.kfs.sys.context.SpringContext;
44 import org.kuali.kfs.sys.service.BankService;
45 import org.kuali.rice.kew.api.WorkflowDocument;
46 import org.kuali.rice.kns.service.DictionaryValidationService;
47 import org.kuali.rice.kns.service.DocumentHelperService;
48 import org.kuali.rice.krad.document.Document;
49 import org.kuali.rice.krad.rules.TransactionalDocumentRuleBase;
50 import org.kuali.rice.krad.rules.rule.event.ApproveDocumentEvent;
51 import org.kuali.rice.krad.service.BusinessObjectService;
52 import org.kuali.rice.krad.service.DocumentService;
53 import org.kuali.rice.krad.util.GlobalVariables;
54 import org.kuali.rice.krad.util.MessageMap;
55 import org.kuali.rice.krad.util.ObjectUtils;
56
57
58
59
60 public class CashControlDocumentRule extends TransactionalDocumentRuleBase implements AddCashControlDetailRule<CashControlDocument>, DeleteCashControlDetailRule<CashControlDocument>, GenerateReferenceDocumentRule<CashControlDocument> {
61
62 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CashControlDocumentRule.class);
63
64
65
66
67 @Override
68 protected boolean processCustomSaveDocumentBusinessRules(Document document) {
69
70 boolean isValid = super.processCustomSaveDocumentBusinessRules(document);
71 CashControlDocument ccDocument = (CashControlDocument) document;
72
73 ccDocument.refreshReferenceObject(ArPropertyConstants.CashControlDocumentFields.CUSTOMER_PAYMENT_MEDIUM);
74 ccDocument.refreshReferenceObject(KFSPropertyConstants.GENERAL_LEDGER_PENDING_ENTRIES);
75
76 MessageMap errorMap = GlobalVariables.getMessageMap();
77
78 if (errorMap.hasErrors()) {
79 isValid &= checkRefDocNumber(ccDocument);
80 isValid &= validateCashControlDetails(ccDocument);
81 }
82
83 return isValid;
84
85 }
86
87
88
89
90 @Override
91 protected boolean processCustomRouteDocumentBusinessRules(Document document) {
92
93 boolean isValid = super.processCustomRouteDocumentBusinessRules(document);
94 CashControlDocument cashControlDocument = (CashControlDocument) document;
95
96 if (isValid) {
97 isValid &= checkPaymentMedium(cashControlDocument);
98 isValid &= checkRefDocNumber(cashControlDocument);
99 isValid &= validateBankCode(cashControlDocument);
100 isValid &= validateCashControlDetails(cashControlDocument);
101 isValid &= checkCashControlDocumentHasDetails(cashControlDocument);
102 }
103
104 return isValid;
105
106 }
107
108
109
110
111 @Override
112 protected boolean processCustomApproveDocumentBusinessRules(ApproveDocumentEvent approveEvent) {
113
114 boolean isValid = super.processCustomApproveDocumentBusinessRules(approveEvent);
115 CashControlDocument cashControlDocument = (CashControlDocument) approveEvent.getDocument();
116
117 cashControlDocument.refreshReferenceObject(ArPropertyConstants.CashControlDocumentFields.CUSTOMER_PAYMENT_MEDIUM);
118 cashControlDocument.refreshReferenceObject(KFSPropertyConstants.GENERAL_LEDGER_PENDING_ENTRIES);
119
120 isValid &= checkAllAppDocsApproved(cashControlDocument);
121 isValid &= checkGLPEsCreated(cashControlDocument);
122
123 return isValid;
124
125 }
126
127
128
129
130
131
132
133
134 public boolean checkLineAmount(CashControlDocument document, CashControlDetail detail) {
135
136 boolean isValid = true;
137
138
139 if (detail.getFinancialDocumentLineAmount().isZero()) {
140 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.FINANCIAL_DOCUMENT_LINE_AMOUNT, ArKeyConstants.ERROR_LINE_AMOUNT_CANNOT_BE_ZERO);
141 isValid = false;
142 }
143
144 if (detail.getFinancialDocumentLineAmount().isNegative()) {
145 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.FINANCIAL_DOCUMENT_LINE_AMOUNT, ArKeyConstants.ERROR_LINE_AMOUNT_CANNOT_BE_NEGATIVE);
146 isValid = false;
147 }
148 return isValid;
149
150 }
151
152
153
154
155
156
157
158 public boolean checkCashControlDocumentHasDetails(CashControlDocument cashControlDocument) {
159
160 boolean isValid = true;
161 GlobalVariables.getMessageMap().addToErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
162
163 if (cashControlDocument.getCashControlDetails().isEmpty()) {
164 GlobalVariables.getMessageMap().putError(KFSPropertyConstants.CASH_CONTROL_DETAILS, ArKeyConstants.ERROR_NO_LINES_TO_PROCESS);
165 }
166
167 GlobalVariables.getMessageMap().removeFromErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
168
169 return isValid;
170
171 }
172
173
174
175
176
177
178
179 public boolean checkPaymentMedium(CashControlDocument document) {
180
181 boolean isValid = true;
182 GlobalVariables.getMessageMap().addToErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
183 String paymentMediumCode = document.getCustomerPaymentMediumCode();
184
185 Map<String, String> criteria = new HashMap<String, String>();
186 criteria.put("customerPaymentMediumCode", paymentMediumCode);
187
188 PaymentMedium paymentMedium = SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(PaymentMedium.class, criteria);
189
190 if (paymentMedium == null) {
191 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.CUSTOMER_PAYMENT_MEDIUM_CODE, ArKeyConstants.ERROR_PAYMENT_MEDIUM_IS_NOT_VALID);
192 isValid = false;
193 }
194
195 GlobalVariables.getMessageMap().removeFromErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
196 return isValid;
197
198 }
199
200
201
202
203
204
205
206 public boolean checkRefDocNumber(CashControlDocument document) {
207
208 boolean isValid = true;
209 GlobalVariables.getMessageMap().addToErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
210 String paymentMedium = document.getCustomerPaymentMediumCode();
211 if (ArConstants.PaymentMediumCode.CASH.equalsIgnoreCase(paymentMedium)) {
212 String refDocNumber = document.getReferenceFinancialDocumentNumber();
213 try {
214 Long.parseLong(refDocNumber);
215 if (StringUtils.isBlank(refDocNumber)) {
216 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.REFERENCE_FINANCIAL_DOC_NBR, ArKeyConstants.ERROR_REFERENCE_DOC_NUMBER_CANNOT_BE_NULL_FOR_PAYMENT_MEDIUM_CASH);
217 isValid = false;
218 }
219 else {
220 boolean docExists = SpringContext.getBean(DocumentService.class).documentExists(refDocNumber);
221 if (!docExists) {
222 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.REFERENCE_FINANCIAL_DOC_NBR, ArKeyConstants.ERROR_REFERENCE_DOC_NUMBER_MUST_BE_VALID_FOR_PAYMENT_MEDIUM_CASH);
223 isValid = false;
224 }
225 }
226 }
227 catch (NumberFormatException nfe) {
228 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.REFERENCE_FINANCIAL_DOC_NBR, ArKeyConstants.ERROR_REFERENCE_DOC_NUMBER_MUST_BE_VALID_FOR_PAYMENT_MEDIUM_CASH);
229 isValid = false;
230 }
231
232 }
233 GlobalVariables.getMessageMap().removeFromErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
234 return isValid;
235
236 }
237
238
239
240
241
242
243
244 public boolean checkGLPEsCreated(CashControlDocument cashControlDocument) {
245
246 boolean isValid = true;
247 List<GeneralLedgerPendingEntry> glpes = cashControlDocument.getGeneralLedgerPendingEntries();
248
249 Integer totalGLRecordsCreated = 0;
250
251 if (glpes == null || glpes.isEmpty()) {
252 totalGLRecordsCreated = cashControlDocument.getGeneralLedgerEntriesPostedCount();
253 }
254
255
256
257
258 if (!ArConstants.PaymentMediumCode.CASH.equalsIgnoreCase(cashControlDocument.getCustomerPaymentMediumCode()) && ((glpes == null || glpes.isEmpty()) && totalGLRecordsCreated.intValue() == 0)) {
259 GlobalVariables.getMessageMap().putError(KFSConstants.GENERAL_LEDGER_PENDING_ENTRIES_TAB_ERRORS, ArKeyConstants.ERROR_GLPES_NOT_CREATED);
260 isValid = false;
261 }
262
263 return isValid;
264
265 }
266
267
268
269
270
271 @Override
272 public boolean processAddCashControlDetailBusinessRules(CashControlDocument transactionalDocument, CashControlDetail cashControlDetail) {
273
274 boolean success = true;
275
276 success &= checkGLPEsNotGenerated(transactionalDocument);
277 if (success) {
278 GlobalVariables.getMessageMap().removeFromErrorPath(ArConstants.NEW_CASH_CONTROL_DETAIL_ERROR_PATH_PREFIX);
279 success &= validateBankCode(transactionalDocument);
280 GlobalVariables.getMessageMap().addToErrorPath(ArConstants.NEW_CASH_CONTROL_DETAIL_ERROR_PATH_PREFIX);
281
282 success &= validateCashControlDetail(transactionalDocument, cashControlDetail);
283 }
284 return success;
285
286 }
287
288
289
290
291
292
293
294
295 protected boolean validateCashControlDetail(CashControlDocument document, CashControlDetail cashControlDetail) {
296
297 MessageMap errorMap = GlobalVariables.getMessageMap();
298
299 boolean isValid = true;
300
301 int originalErrorCount = errorMap.getErrorCount();
302
303 SpringContext.getBean(DictionaryValidationService.class).validateBusinessObject(cashControlDetail);
304 isValid = (errorMap.getErrorCount() == originalErrorCount);
305
306
307 if (isValid) {
308 String customerNumber = cashControlDetail.getCustomerNumber();
309
310 if (customerNumber != null && !customerNumber.equals("")) {
311 isValid &= checkCustomerNumber(customerNumber);
312 }
313
314 isValid &= checkLineAmount(document, cashControlDetail);
315 }
316
317 return isValid;
318
319 }
320
321
322
323
324
325
326
327 public boolean validateCashControlDetails(CashControlDocument cashControlDocument) {
328
329 GlobalVariables.getMessageMap().addToErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
330 boolean isValid = true;
331
332 for (int i = 0; i < cashControlDocument.getCashControlDetails().size(); i++) {
333
334 CashControlDetail cashControlDetail = cashControlDocument.getCashControlDetail(i);
335 String propertyName = KFSPropertyConstants.CASH_CONTROL_DETAIL + "[" + i + "]";
336 GlobalVariables.getMessageMap().addToErrorPath(propertyName);
337
338 isValid &= validateCashControlDetail(cashControlDocument, cashControlDetail);
339
340 GlobalVariables.getMessageMap().removeFromErrorPath(propertyName);
341 }
342
343 GlobalVariables.getMessageMap().removeFromErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
344 return isValid;
345
346 }
347
348
349
350
351
352
353
354 protected boolean checkCustomerNumber(String customerNumber) {
355 boolean isValid = true;
356
357 if (customerNumber != null && !customerNumber.equals("")) {
358
359 Map<String, String> criteria = new HashMap<String, String>();
360 criteria.put(ArPropertyConstants.CustomerFields.CUSTOMER_NUMBER, customerNumber);
361
362 Customer customer = SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(Customer.class, criteria);
363
364 if (customer == null) {
365 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CustomerFields.CUSTOMER_NUMBER, ArKeyConstants.ERROR_CUSTOMER_NUMBER_IS_NOT_VALID);
366 isValid = false;
367 }
368 }
369
370 return isValid;
371 }
372
373
374
375
376
377
378
379 public boolean checkGLPEsNotGenerated(CashControlDocument cashControlDocument) {
380
381 boolean success = true;
382 List<GeneralLedgerPendingEntry> glpes = cashControlDocument.getGeneralLedgerPendingEntries();
383
384 if (glpes != null && !glpes.isEmpty()) {
385 success = false;
386 GlobalVariables.getMessageMap().putError(KFSConstants.GENERAL_LEDGER_PENDING_ENTRIES_TAB_ERRORS, ArKeyConstants.ERROR_DELETE_ADD_APP_DOCS_NOT_ALLOWED_AFTER_GLPES_GEN);
387 }
388 return success;
389
390 }
391
392
393
394
395
396
397
398 public boolean checkAllAppDocsApproved(CashControlDocument cashControlDocument) {
399
400 boolean allAppDocsApproved = true;
401
402 for (int i = 0; i < cashControlDocument.getCashControlDetails().size(); i++) {
403
404 CashControlDetail cashControlDetail = cashControlDocument.getCashControlDetail(i);
405 PaymentApplicationDocument applicationDocument = cashControlDetail.getReferenceFinancialDocument();
406 WorkflowDocument workflowDocument = applicationDocument.getDocumentHeader().getWorkflowDocument();
407
408 if (!(workflowDocument.isApproved() || workflowDocument.isFinal())) {
409 allAppDocsApproved = false;
410
411 String propertyName = KFSPropertyConstants.CASH_CONTROL_DETAIL + "[" + i + "]";
412 GlobalVariables.getMessageMap().addToErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
413 GlobalVariables.getMessageMap().addToErrorPath(propertyName);
414 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.APPLICATION_DOC_STATUS, ArKeyConstants.ERROR_ALL_APPLICATION_DOCS_MUST_BE_APPROVED);
415 GlobalVariables.getMessageMap().removeFromErrorPath(propertyName);
416 GlobalVariables.getMessageMap().removeFromErrorPath(KFSConstants.DOCUMENT_PROPERTY_NAME);
417
418 break;
419 }
420
421 }
422
423 return allAppDocsApproved;
424
425 }
426
427
428
429
430
431 @Override
432 public boolean processDeleteCashControlDetailBusinessRules(CashControlDocument transactionalDocument, CashControlDetail cashControlDetail) {
433
434 boolean success = true;
435 success &= checkGLPEsNotGenerated(transactionalDocument);
436 return success;
437
438 }
439
440
441
442
443 @Override
444 public boolean processGenerateReferenceDocumentBusinessRules(CashControlDocument transactionalDocument) {
445
446 boolean success = true;
447 success &= checkPaymentMedium(transactionalDocument);
448 if (success) {
449 success &= checkGLPEsNotGenerated(transactionalDocument);
450 }
451 return success;
452
453 }
454
455
456
457
458
459
460
461 public boolean validateBankCode(CashControlDocument document) {
462 boolean isValid = true;
463
464
465 CashControlDocumentPresentationController ccPC = (CashControlDocumentPresentationController) SpringContext.getBean(DocumentHelperService.class).getDocumentPresentationController(document);
466 if (!ccPC.getEditModes(document).contains(ArAuthorizationConstants.CashControlDocumentEditMode.EDIT_BANK_CODE)) {
467 return isValid;
468 }
469
470
471 String bankCode = document.getBankCode();
472 if (StringUtils.isNotBlank(bankCode)) {
473 Bank bank = SpringContext.getBean(BankService.class).getByPrimaryId(bankCode);
474 if (ObjectUtils.isNull(bank)) {
475 isValid = false;
476 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.BANK_CODE, ArKeyConstants.ERROR_INVALID_BANK_CODE);
477 }
478 else {
479
480 if (!bank.isBankDepositIndicator()) {
481 isValid = false;
482 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.BANK_CODE, ArKeyConstants.ERROR_BANK_NOT_ELIGIBLE_FOR_DEPOSIT_ACTIVITY);
483 }
484 }
485 }
486 else {
487 if (SpringContext.getBean(BankService.class).isBankSpecificationEnabled()) {
488 isValid = false;
489 GlobalVariables.getMessageMap().putError(ArPropertyConstants.CashControlDocumentFields.BANK_CODE, ArKeyConstants.ERROR_BANK_CODE_REQUIRED);
490 }
491 }
492
493 return isValid;
494 }
495
496 }