1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.gl.batch.service.impl;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.PrintStream;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32
33 import org.apache.commons.collections.IteratorUtils;
34 import org.apache.commons.io.IOUtils;
35 import org.apache.commons.lang.StringUtils;
36 import org.apache.log4j.Logger;
37 import org.kuali.ole.coa.businessobject.Account;
38 import org.kuali.ole.coa.businessobject.BalanceType;
39 import org.kuali.ole.coa.businessobject.ObjectType;
40 import org.kuali.ole.coa.service.AccountService;
41 import org.kuali.ole.gl.GeneralLedgerConstants;
42 import org.kuali.ole.gl.batch.CollectorBatch;
43 import org.kuali.ole.gl.batch.CollectorStep;
44 import org.kuali.ole.gl.batch.service.CollectorHelperService;
45 import org.kuali.ole.gl.batch.service.CollectorScrubberService;
46 import org.kuali.ole.gl.businessobject.CollectorDetail;
47 import org.kuali.ole.gl.businessobject.CollectorHeader;
48 import org.kuali.ole.gl.businessobject.OriginEntryFull;
49 import org.kuali.ole.gl.businessobject.OriginEntryInformation;
50 import org.kuali.ole.gl.report.CollectorReportData;
51 import org.kuali.ole.gl.report.PreScrubberReportData;
52 import org.kuali.ole.gl.service.CollectorDetailService;
53 import org.kuali.ole.gl.service.OriginEntryGroupService;
54 import org.kuali.ole.gl.service.OriginEntryService;
55 import org.kuali.ole.gl.service.PreScrubberService;
56 import org.kuali.ole.gl.service.impl.CollectorScrubberStatus;
57 import org.kuali.ole.sys.OLEConstants;
58 import org.kuali.ole.sys.OLEConstants.SystemGroupParameterNames;
59 import org.kuali.ole.sys.OLEKeyConstants;
60 import org.kuali.ole.sys.OLEPropertyConstants;
61 import org.kuali.ole.sys.batch.BatchInputFileType;
62 import org.kuali.ole.sys.batch.service.BatchInputFileService;
63 import org.kuali.ole.sys.context.SpringContext;
64 import org.kuali.ole.sys.exception.ParseException;
65 import org.kuali.rice.core.api.config.property.ConfigurationService;
66 import org.kuali.rice.core.api.datetime.DateTimeService;
67 import org.kuali.rice.core.api.util.type.KualiDecimal;
68 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
69 import org.kuali.rice.krad.service.BusinessObjectService;
70 import org.kuali.rice.krad.util.GlobalVariables;
71 import org.kuali.rice.krad.util.MessageMap;
72 import org.kuali.rice.krad.util.ObjectUtils;
73
74
75
76
77
78 public class CollectorHelperServiceImpl implements CollectorHelperService {
79 private static Logger LOG = Logger.getLogger(CollectorHelperServiceImpl.class);
80
81 private static final String CURRENCY_SYMBOL = "$";
82
83 private CollectorDetailService collectorDetailService;
84 private OriginEntryService originEntryService;
85 private OriginEntryGroupService originEntryGroupService;
86 private ParameterService parameterService;
87 private ConfigurationService configurationService;
88 private DateTimeService dateTimeService;
89 private BatchInputFileService batchInputFileService;
90 private CollectorScrubberService collectorScrubberService;
91 private AccountService accountService;
92 private PreScrubberService preScrubberService;
93 private String batchFileDirectoryName;
94
95
96
97
98
99
100
101
102
103
104
105
106 public boolean loadCollectorFile(String fileName, CollectorReportData collectorReportData, List<CollectorScrubberStatus> collectorScrubberStatuses, BatchInputFileType collectorInputFileType, PrintStream originEntryOutputPs) {
107 boolean isValid = true;
108
109 MessageMap fileMessageMap = collectorReportData.getMessageMapForFileName(fileName);
110
111 List<CollectorBatch> batches = doCollectorFileParse(fileName, fileMessageMap, collectorInputFileType, collectorReportData);
112 for (int i = 0; i < batches.size(); i++) {
113 CollectorBatch collectorBatch = batches.get(i);
114
115 collectorBatch.setBatchName(fileName + " Batch " + String.valueOf(i + 1));
116 collectorReportData.addBatch(collectorBatch);
117
118 isValid &= loadCollectorBatch(collectorBatch, fileName, i + 1, collectorReportData, collectorScrubberStatuses, collectorInputFileType, originEntryOutputPs);
119 }
120 return isValid;
121 }
122
123 protected boolean loadCollectorBatch(CollectorBatch batch, String fileName, int batchIndex, CollectorReportData collectorReportData, List<CollectorScrubberStatus> collectorScrubberStatuses, BatchInputFileType collectorInputFileType, PrintStream originEntryOutputPs) {
124 boolean isValid = true;
125
126 MessageMap messageMap = batch.getMessageMap();
127
128 if (messageMap.hasErrors()) {
129 isValid = false;
130 }
131
132 if (isValid) {
133 collectorReportData.setNumInputDetails(batch);
134
135 isValid = checkTrailerTotals(batch, collectorReportData, messageMap);
136 }
137
138
139 if (isValid) {
140 isValid = performValidation(batch, messageMap);
141 }
142
143 if (isValid) {
144
145 collectorReportData.markValidationStatus(batch, true);
146
147 prescrubParsedCollectorBatch(batch, collectorReportData);
148
149 String collectorFileDirectoryName = collectorInputFileType.getDirectoryPath();
150
151 String collectorInputFileNameForScrubber = batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.COLLECTOR_BACKUP_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION;
152 PrintStream inputFilePs = null;
153 try {
154 inputFilePs = new PrintStream(collectorInputFileNameForScrubber);
155
156 for (OriginEntryFull entry : batch.getOriginEntries()){
157 inputFilePs.printf("%s\n", entry.getLine());
158 }
159 } catch (IOException e) {
160 throw new RuntimeException("loadCollectorFile Stopped: " + e.getMessage(), e);
161 } finally {
162 IOUtils.closeQuietly(inputFilePs);
163 }
164
165 CollectorScrubberStatus collectorScrubberStatus = collectorScrubberService.scrub(batch, collectorReportData, collectorFileDirectoryName);
166 collectorScrubberStatuses.add(collectorScrubberStatus);
167 processInterDepartmentalBillingAmounts(batch);
168
169
170 String collectorDemergerOutputFileName = batchFileDirectoryName + File.separator + GeneralLedgerConstants.BatchFileSystem.COLLECTOR_DEMERGER_VAILD_OUTPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION;
171 batch.setDefaultsAndStore(collectorReportData, collectorDemergerOutputFileName, originEntryOutputPs);
172 collectorReportData.incrementNumPersistedBatches();
173 }
174 else {
175 collectorReportData.incrementNumNonPersistedBatches();
176 collectorReportData.incrementNumNotPersistedOriginEntryRecords(batch.getOriginEntries().size());
177 collectorReportData.incrementNumNotPersistedCollectorDetailRecords(batch.getCollectorDetails().size());
178
179 collectorReportData.markValidationStatus(batch, false);
180 }
181
182 return isValid;
183 }
184
185
186
187
188
189
190
191
192
193
194 protected String attemptToParseEmailAfterParseError(String fileName) {
195 return null;
196 }
197
198
199
200
201
202
203
204
205 protected List<CollectorBatch> doCollectorFileParse(String fileName, MessageMap messageMap, BatchInputFileType collectorInputFileType, CollectorReportData collectorReportData) {
206
207 InputStream inputStream = null;
208 try {
209 inputStream = new FileInputStream(fileName);
210 }
211 catch (FileNotFoundException e) {
212 LOG.error("file to parse not found " + fileName, e);
213 collectorReportData.markUnparsableFileNames(fileName);
214 throw new RuntimeException("Cannot find the file requested to be parsed " + fileName + " " + e.getMessage(), e);
215 }
216 catch (RuntimeException e) {
217 collectorReportData.markUnparsableFileNames(fileName);
218 throw e;
219 }
220
221 List<CollectorBatch> parsedObject = null;
222 try {
223 byte[] fileByteContent = IOUtils.toByteArray(inputStream);
224 parsedObject = (List<CollectorBatch>) batchInputFileService.parse(collectorInputFileType, fileByteContent);
225 }
226 catch (IOException e) {
227 LOG.error("error while getting file bytes: " + e.getMessage(), e);
228 collectorReportData.markUnparsableFileNames(fileName);
229 throw new RuntimeException("Error encountered while attempting to get file bytes: " + e.getMessage(), e);
230 }
231 catch (ParseException e1) {
232 LOG.error("errors parsing file " + e1.getMessage(), e1);
233 collectorReportData.markUnparsableFileNames(fileName);
234 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.ERROR_BATCH_UPLOAD_PARSING_XML, new String[] { e1.getMessage() });
235 }
236 catch (RuntimeException e) {
237 collectorReportData.markUnparsableFileNames(fileName);
238 throw e;
239 }
240
241 return parsedObject;
242 }
243
244 protected void prescrubParsedCollectorBatch(CollectorBatch collectorBatch, CollectorReportData collectorReportData) {
245 if (preScrubberService.deriveChartOfAccountsCodeIfSpaces()) {
246 PreScrubberReportData preScrubberReportData = collectorReportData.getPreScrubberReportData();
247
248 int inputRecords = collectorBatch.getOriginEntries().size();
249 Set<String> noChartCodesCache = new HashSet<String>();
250 Set<String> multipleChartCodesCache = new HashSet<String>();
251 Map<String, String> accountNumberToChartCodeCache = new HashMap<String, String>();
252
253 Iterator<?> originEntryAndDetailIterator = IteratorUtils.chainedIterator(collectorBatch.getOriginEntries().iterator(), collectorBatch.getCollectorDetails().iterator());
254 while (originEntryAndDetailIterator.hasNext()) {
255 Object originEntryOrDetail = originEntryAndDetailIterator.next();
256 if (StringUtils.isBlank(extractChartOfAccountsCode(originEntryOrDetail))) {
257 String accountNumber = extractAccountNumber(originEntryOrDetail);
258
259 boolean nonExistent = false;
260 boolean multipleFound = false;
261 String chartOfAccountsCode = null;
262
263 if (noChartCodesCache.contains(accountNumber)) {
264 nonExistent = true;
265 }
266 else if (multipleChartCodesCache.contains(accountNumber)) {
267 multipleFound = true;
268 }
269 else if (accountNumberToChartCodeCache.containsKey(accountNumber)) {
270 chartOfAccountsCode = accountNumberToChartCodeCache.get(accountNumber);
271 }
272 else {
273 Collection<Account> accounts = accountService.getAccountsForAccountNumber(accountNumber);
274 if (accounts.size() == 1) {
275 chartOfAccountsCode = accounts.iterator().next().getChartOfAccountsCode();
276 accountNumberToChartCodeCache.put(accountNumber, chartOfAccountsCode);
277 }
278 else if (accounts.size() == 0) {
279 noChartCodesCache.add(accountNumber);
280 nonExistent = true;
281 }
282 else {
283 multipleChartCodesCache.add(accountNumber);
284 multipleFound = true;
285 }
286 }
287
288 if (!nonExistent && !multipleFound) {
289 setChartOfAccountsCode(originEntryOrDetail, chartOfAccountsCode);
290 }
291 }
292 }
293
294 preScrubberReportData.getAccountsWithMultipleCharts().addAll(multipleChartCodesCache);
295 preScrubberReportData.getAccountsWithNoCharts().addAll(noChartCodesCache);
296 preScrubberReportData.setInputRecords(preScrubberReportData.getInputRecords() + inputRecords);
297 preScrubberReportData.setOutputRecords(preScrubberReportData.getOutputRecords() + inputRecords);
298 }
299 }
300
301 protected String extractChartOfAccountsCode(Object originEntryOrDetail) {
302 if (originEntryOrDetail instanceof OriginEntryInformation)
303 return ((OriginEntryInformation) originEntryOrDetail).getChartOfAccountsCode();
304 return ((CollectorDetail) originEntryOrDetail).getChartOfAccountsCode();
305 }
306
307 protected String extractAccountNumber(Object originEntryOrDetail) {
308 if (originEntryOrDetail instanceof OriginEntryInformation)
309 return ((OriginEntryInformation) originEntryOrDetail).getAccountNumber();
310 return ((CollectorDetail) originEntryOrDetail).getAccountNumber();
311 }
312
313 protected void setChartOfAccountsCode(Object originEntryOrDetail, String chartOfAccountsCode) {
314 if (originEntryOrDetail instanceof OriginEntryInformation)
315 ((OriginEntryInformation) originEntryOrDetail).setChartOfAccountsCode(chartOfAccountsCode);
316 else
317 ((CollectorDetail) originEntryOrDetail).setChartOfAccountsCode(chartOfAccountsCode);
318 }
319
320
321
322
323
324
325
326
327 public boolean performValidation(CollectorBatch batch) {
328 return performValidation(batch, GlobalVariables.getMessageMap());
329 }
330
331
332
333
334
335
336
337
338 protected boolean performValidation(CollectorBatch batch, MessageMap messageMap) {
339 boolean valid = performCollectorHeaderValidation(batch, messageMap);
340
341 performUppercasing(batch);
342
343 boolean performDuplicateHeaderCheck = parameterService.getParameterValueAsBoolean(CollectorStep.class, SystemGroupParameterNames.COLLECTOR_PERFORM_DUPLICATE_HEADER_CHECK);
344 if (valid && performDuplicateHeaderCheck) {
345 valid = duplicateHeaderCheck(batch, messageMap);
346 }
347 if (valid) {
348 valid = checkForMixedDocumentTypes(batch, messageMap);
349 }
350
351 if (valid) {
352 valid = checkForMixedBalanceTypes(batch, messageMap);
353 }
354
355 if (valid) {
356 valid = checkDetailKeys(batch, messageMap);
357 }
358
359 return valid;
360 }
361
362
363
364
365
366
367 protected void performUppercasing(CollectorBatch batch) {
368 for (OriginEntryFull originEntry : batch.getOriginEntries()) {
369 if (StringUtils.isNotBlank(originEntry.getSubAccountNumber())) {
370 originEntry.setSubAccountNumber(originEntry.getSubAccountNumber().toUpperCase());
371 }
372
373 if (StringUtils.isNotBlank(originEntry.getFinancialSubObjectCode())) {
374 originEntry.setFinancialSubObjectCode(originEntry.getFinancialSubObjectCode().toUpperCase());
375 }
376
377 if (StringUtils.isNotBlank(originEntry.getProjectCode())) {
378 originEntry.setProjectCode(originEntry.getProjectCode().toUpperCase());
379 }
380 }
381
382 for (CollectorDetail detail : batch.getCollectorDetails()) {
383 if (StringUtils.isNotBlank(detail.getSubAccountNumber())) {
384 detail.setSubAccountNumber(detail.getSubAccountNumber().toUpperCase());
385 }
386
387 if (StringUtils.isNotBlank(detail.getFinancialSubObjectCode())) {
388 detail.setFinancialSubObjectCode(detail.getFinancialSubObjectCode().toUpperCase());
389 }
390 }
391 }
392
393 protected boolean performCollectorHeaderValidation(CollectorBatch batch, MessageMap messageMap) {
394 if (batch.isHeaderlessBatch()) {
395
396 return false;
397 }
398 boolean valid = true;
399 if (StringUtils.isBlank(batch.getChartOfAccountsCode())) {
400 valid = false;
401 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.HEADER_CHART_CODE_REQUIRED);
402 }
403 if (StringUtils.isBlank(batch.getOrganizationCode())) {
404 valid = false;
405 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.HEADER_ORGANIZATION_CODE_REQUIRED);
406 }
407 if (StringUtils.isBlank(batch.getCampusCode())) {
408 valid = false;
409 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.HEADER_CAMPUS_CODE_REQUIRED);
410 }
411 if (StringUtils.isBlank(batch.getPhoneNumber())) {
412 valid = false;
413 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.HEADER_PHONE_NUMBER_REQUIRED);
414 }
415 if (StringUtils.isBlank(batch.getMailingAddress())) {
416 valid = false;
417 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.HEADER_MAILING_ADDRESS_REQUIRED);
418 }
419 if (StringUtils.isBlank(batch.getDepartmentName())) {
420 valid = false;
421 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.HEADER_DEPARTMENT_NAME_REQUIRED);
422 }
423 return valid;
424 }
425
426
427
428
429
430
431
432
433 protected void processInterDepartmentalBillingAmounts(CollectorBatch batch) {
434 for (CollectorDetail collectorDetail : batch.getCollectorDetails()) {
435 String balanceTypeCode = getBalanceTypeCode(collectorDetail, batch);
436
437 BalanceType balanceTyp = new BalanceType();
438 balanceTyp.setFinancialBalanceTypeCode(balanceTypeCode);
439 balanceTyp = (BalanceType) SpringContext.getBean(BusinessObjectService.class).retrieve(balanceTyp);
440 if (balanceTyp == null) {
441
442 LOG.info("No balance type code found for ID billing record. " + collectorDetail);
443 continue;
444 }
445
446 collectorDetail.refreshReferenceObject(OLEPropertyConstants.FINANCIAL_OBJECT);
447 if (collectorDetail.getFinancialObject() == null) {
448
449 LOG.info("No object code found for ID billing record. " + collectorDetail);
450 continue;
451 }
452 ObjectType objectType = collectorDetail.getFinancialObject().getFinancialObjectType();
453
454
455
456 }
457 }
458
459
460
461
462
463
464
465
466
467
468 protected void negateAmountIfNecessary(CollectorDetail collectorDetail, BalanceType balanceTyp, ObjectType objectType, CollectorBatch batch) {
469 if (balanceTyp != null && objectType != null) {
470 if (balanceTyp.isFinancialOffsetGenerationIndicator()) {
471 if (OLEConstants.GL_DEBIT_CODE.equals(objectType.getFinObjectTypeDebitcreditCd())) {
472 KualiDecimal amount = collectorDetail.getCollectorDetailItemAmount();
473 amount = amount.negated();
474 collectorDetail.setCollectorDetailItemAmount(amount);
475 }
476 }
477 }
478 }
479
480
481
482
483
484
485
486
487
488 protected String getBalanceTypeCode(CollectorDetail collectorDetail, CollectorBatch batch) {
489 return collectorDetail.getFinancialBalanceTypeCode();
490 }
491
492
493
494
495
496
497
498 protected boolean duplicateHeaderCheck(CollectorBatch batch, MessageMap messageMap) {
499 boolean validHeader = true;
500
501 CollectorHeader foundHeader = batch.retrieveDuplicateHeader();
502
503 if (foundHeader != null) {
504 LOG.error("batch header was matched to a previously loaded batch");
505 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.DUPLICATE_BATCH_HEADER);
506
507 validHeader = false;
508 }
509
510 return validHeader;
511 }
512
513
514
515
516
517
518
519
520 protected boolean checkForMixedDocumentTypes(CollectorBatch batch, MessageMap messageMap) {
521 boolean docTypesNotMixed = true;
522
523 Set<String> batchDocumentTypes = new HashSet<String>();
524 for (OriginEntryFull entry : batch.getOriginEntries()) {
525 batchDocumentTypes.add(entry.getFinancialDocumentTypeCode());
526 }
527
528 if (batchDocumentTypes.size() > 1) {
529 LOG.error("mixed document types found in batch");
530 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.MIXED_DOCUMENT_TYPES);
531
532 docTypesNotMixed = false;
533 }
534
535 return docTypesNotMixed;
536 }
537
538
539
540
541
542
543
544 protected boolean checkForMixedBalanceTypes(CollectorBatch batch, MessageMap messageMap) {
545 boolean balanceTypesNotMixed = true;
546
547 Set<String> balanceTypes = new HashSet<String>();
548 for (OriginEntryFull entry : batch.getOriginEntries()) {
549 balanceTypes.add(entry.getFinancialBalanceTypeCode());
550 }
551
552 if (balanceTypes.size() > 1) {
553 LOG.error("mixed balance types found in batch");
554 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.MIXED_BALANCE_TYPES);
555
556 balanceTypesNotMixed = false;
557 }
558
559 return balanceTypesNotMixed;
560 }
561
562
563
564
565
566
567
568
569 protected boolean checkDetailKeys(CollectorBatch batch, MessageMap messageMap) {
570 boolean detailKeysFound = true;
571
572
573 Set<String> glEntryKeys = new HashSet<String>();
574 for (OriginEntryFull entry : batch.getOriginEntries()) {
575 glEntryKeys.add(generateOriginEntryMatchingKey(entry, ", "));
576 }
577
578 for (CollectorDetail collectorDetail : batch.getCollectorDetails()) {
579 String collectorDetailKey = generateCollectorDetailMatchingKey(collectorDetail, ", ");
580 if (!glEntryKeys.contains(collectorDetailKey)) {
581 LOG.error("found detail key without a matching gl entry key " + collectorDetailKey);
582 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.NONMATCHING_DETAIL_KEY, collectorDetailKey);
583
584 detailKeysFound = false;
585 }
586 }
587
588 return detailKeysFound;
589 }
590
591
592
593
594
595
596
597
598 protected String generateOriginEntryMatchingKey(OriginEntryFull entry, String delimiter) {
599 return StringUtils.join(new String[] { ObjectUtils.isNull(entry.getUniversityFiscalYear()) ? "" : entry.getUniversityFiscalYear().toString(), entry.getUniversityFiscalPeriodCode(), entry.getChartOfAccountsCode(), entry.getAccountNumber(), entry.getSubAccountNumber(), entry.getFinancialObjectCode(), entry.getFinancialSubObjectCode(), entry.getFinancialObjectTypeCode(), entry.getDocumentNumber(), entry.getFinancialDocumentTypeCode(), entry.getFinancialSystemOriginationCode() }, delimiter);
600 }
601
602
603
604
605
606
607
608
609 protected String generateCollectorDetailMatchingKey(CollectorDetail collectorDetail, String delimiter) {
610 return StringUtils.join(new String[] { ObjectUtils.isNull(collectorDetail.getUniversityFiscalYear()) ? "" : collectorDetail.getUniversityFiscalYear().toString(), collectorDetail.getUniversityFiscalPeriodCode(), collectorDetail.getChartOfAccountsCode(), collectorDetail.getAccountNumber(), collectorDetail.getSubAccountNumber(), collectorDetail.getFinancialObjectCode(), collectorDetail.getFinancialSubObjectCode(), collectorDetail.getFinancialObjectTypeCode(), collectorDetail.getDocumentNumber(), collectorDetail.getFinancialDocumentTypeCode(), collectorDetail.getFinancialSystemOriginationCode() }, delimiter);
611 }
612
613
614
615
616
617
618
619
620
621 public boolean checkTrailerTotals(CollectorBatch batch, CollectorReportData collectorReportData) {
622 return checkTrailerTotals(batch, collectorReportData, GlobalVariables.getMessageMap());
623 }
624
625
626
627
628
629
630
631 protected boolean checkTrailerTotals(CollectorBatch batch, CollectorReportData collectorReportData, MessageMap messageMap) {
632 boolean trailerTotalsMatch = true;
633
634 int actualRecordCount = batch.getOriginEntries().size() + batch.getCollectorDetails().size();
635 if (actualRecordCount != batch.getTotalRecords()) {
636 LOG.error("trailer check on total count did not pass, expected count: " + String.valueOf(batch.getTotalRecords()) + ", actual count: " + String.valueOf(actualRecordCount));
637 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.TRAILER_ERROR_COUNTNOMATCH, String.valueOf(batch.getTotalRecords()), String.valueOf(actualRecordCount));
638 trailerTotalsMatch = false;
639 }
640
641 OriginEntryTotals totals = batch.getOriginEntryTotals();
642
643 if (batch.getOriginEntries().size() == 0) {
644 if (!KualiDecimal.ZERO.equals(batch.getTotalAmount())) {
645 LOG.error("trailer total should be zero when there are no origin entries");
646 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.TRAILER_ERROR_AMOUNT_SHOULD_BE_ZERO);
647 }
648 return false;
649 }
650
651
652 Collection<String> documentTypes = new ArrayList<String>( parameterService.getParameterValuesAsString(CollectorStep.class, OLEConstants.SystemGroupParameterNames.COLLECTOR_EQUAL_DC_TOTAL_DOCUMENT_TYPES) );
653
654 boolean equalDebitCreditTotal = false;
655 for ( String documentType : documentTypes ) {
656 documentType = StringUtils.remove(documentType, "*").toUpperCase();
657 if (batch.getOriginEntries().get(0).getFinancialDocumentTypeCode().startsWith(documentType)
658 && OLEConstants.BALANCE_TYPE_ACTUAL.equals(batch.getOriginEntries().get(0).getFinancialBalanceTypeCode())) {
659 equalDebitCreditTotal = true;
660 }
661 }
662
663 if (equalDebitCreditTotal) {
664
665 if (!totals.getCreditAmount().equals(totals.getDebitAmount()) || !totals.getCreditAmount().equals(batch.getTotalAmount())) {
666 LOG.error("trailer check on total amount did not pass, debit should equal credit, should equal trailer total");
667 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.TRAILER_ERROR_AMOUNTNOMATCH1, totals.getCreditAmount().toString(), totals.getDebitAmount().toString(), batch.getTotalAmount().toString());
668 trailerTotalsMatch = false;
669 }
670 }
671 else {
672
673 KualiDecimal totalGlEntries = totals.getCreditAmount().add(totals.getDebitAmount()).add(totals.getOtherAmount());
674 if (!totalGlEntries.equals(batch.getTotalAmount())) {
675 LOG.error("trailer check on total amount did not pass, sum of gl entry amounts should equal trailer total");
676 messageMap.putError(OLEConstants.GLOBAL_ERRORS, OLEKeyConstants.Collector.TRAILER_ERROR_AMOUNTNOMATCH2, totalGlEntries.toString(), batch.getTotalAmount().toString());
677 trailerTotalsMatch = false;
678 }
679 }
680
681 return trailerTotalsMatch;
682 }
683
684 public void setCollectorDetailService(CollectorDetailService collectorDetailService) {
685 this.collectorDetailService = collectorDetailService;
686 }
687
688 public void setOriginEntryGroupService(OriginEntryGroupService originEntryGroupService) {
689 this.originEntryGroupService = originEntryGroupService;
690 }
691
692 public void setOriginEntryService(OriginEntryService originEntryService) {
693 this.originEntryService = originEntryService;
694 }
695
696
697
698
699
700
701 public String getStagingDirectory() {
702 return configurationService.getPropertyValueAsString(OLEConstants.GL_COLLECTOR_STAGING_DIRECTORY);
703 }
704
705 public void setDateTimeService(DateTimeService dateTimeService) {
706 this.dateTimeService = dateTimeService;
707 }
708
709 public void setBatchInputFileService(BatchInputFileService batchInputFileService) {
710 this.batchInputFileService = batchInputFileService;
711 }
712
713
714
715
716
717
718 public void setCollectorScrubberService(CollectorScrubberService collectorScrubberService) {
719 this.collectorScrubberService = collectorScrubberService;
720 }
721
722 public void setConfigurationService(ConfigurationService configurationService) {
723 this.configurationService = configurationService;
724 }
725
726 public void setParameterService(ParameterService parameterService) {
727 this.parameterService = parameterService;
728 }
729
730
731
732
733
734 public void setBatchFileDirectoryName(String batchFileDirectoryName) {
735 this.batchFileDirectoryName = batchFileDirectoryName;
736 }
737
738
739
740
741
742 public void setAccountService(AccountService accountService) {
743 this.accountService = accountService;
744 }
745
746
747
748
749
750 public void setPreScrubberService(PreScrubberService preScrubberService) {
751 this.preScrubberService = preScrubberService;
752 }
753 }