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 }