Source Code Cross Referenced for ScrubberProcess.java in  » ERP-CRM-Financial » Kuali-Financial-System » org » kuali » module » gl » service » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » Kuali Financial System » org.kuali.module.gl.service.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2006-2007 The Kuali Foundation.
0003:         * 
0004:         * Licensed under the Educational Community License, Version 1.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         * 
0008:         * http://www.opensource.org/licenses/ecl1.php
0009:         * 
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        package org.kuali.module.gl.service.impl;
0017:
0018:        import java.sql.Date;
0019:        import java.text.NumberFormat;
0020:        import java.util.ArrayList;
0021:        import java.util.Calendar;
0022:        import java.util.Collection;
0023:        import java.util.HashMap;
0024:        import java.util.Iterator;
0025:        import java.util.List;
0026:        import java.util.Map;
0027:
0028:        import org.kuali.core.bo.DocumentType;
0029:        import org.kuali.core.service.DateTimeService;
0030:        import org.kuali.core.service.DocumentTypeService;
0031:        import org.kuali.core.service.KualiConfigurationService;
0032:        import org.kuali.core.service.PersistenceService;
0033:        import org.kuali.core.util.KualiDecimal;
0034:        import org.kuali.core.util.ObjectUtils;
0035:        import org.kuali.kfs.KFSConstants;
0036:        import org.kuali.kfs.KFSKeyConstants;
0037:        import org.kuali.kfs.KFSPropertyConstants;
0038:        import org.kuali.kfs.bo.Options;
0039:        import org.kuali.kfs.context.SpringContext;
0040:        import org.kuali.kfs.service.ParameterEvaluator;
0041:        import org.kuali.kfs.service.ParameterService;
0042:        import org.kuali.module.chart.bo.A21SubAccount;
0043:        import org.kuali.module.chart.bo.Account;
0044:        import org.kuali.module.chart.bo.Chart;
0045:        import org.kuali.module.chart.bo.ObjectCode;
0046:        import org.kuali.module.chart.bo.OffsetDefinition;
0047:        import org.kuali.module.chart.bo.codes.BalanceTyp;
0048:        import org.kuali.module.chart.service.ObjectCodeService;
0049:        import org.kuali.module.chart.service.OffsetDefinitionService;
0050:        import org.kuali.module.financial.exceptions.InvalidFlexibleOffsetException;
0051:        import org.kuali.module.financial.service.FlexibleOffsetAccountService;
0052:        import org.kuali.module.gl.GLConstants;
0053:        import org.kuali.module.gl.batch.ScrubberStep;
0054:        import org.kuali.module.gl.batch.collector.CollectorBatch;
0055:        import org.kuali.module.gl.bo.OriginEntry;
0056:        import org.kuali.module.gl.bo.OriginEntryFull;
0057:        import org.kuali.module.gl.bo.OriginEntryGroup;
0058:        import org.kuali.module.gl.bo.OriginEntryLite;
0059:        import org.kuali.module.gl.bo.OriginEntrySource;
0060:        import org.kuali.module.gl.bo.Transaction;
0061:        import org.kuali.module.gl.bo.UniversityDate;
0062:        import org.kuali.module.gl.dao.UniversityDateDao;
0063:        import org.kuali.module.gl.service.OriginEntryGroupService;
0064:        import org.kuali.module.gl.service.OriginEntryLiteService;
0065:        import org.kuali.module.gl.service.OriginEntryLookupService;
0066:        import org.kuali.module.gl.service.OriginEntryService;
0067:        import org.kuali.module.gl.service.ReportService;
0068:        import org.kuali.module.gl.service.RunDateService;
0069:        import org.kuali.module.gl.service.ScrubberProcessObjectCodeOverride;
0070:        import org.kuali.module.gl.service.ScrubberValidator;
0071:        import org.kuali.module.gl.service.impl.scrubber.DemergerReportData;
0072:        import org.kuali.module.gl.service.impl.scrubber.ScrubberReportData;
0073:        import org.kuali.module.gl.util.CachingLookup;
0074:        import org.kuali.module.gl.util.CollectorReportData;
0075:        import org.kuali.module.gl.util.Message;
0076:        import org.kuali.module.gl.util.ObjectHelper;
0077:        import org.kuali.module.gl.util.OriginEntryStatistics;
0078:        import org.kuali.module.gl.util.ScrubberStatus;
0079:        import org.kuali.module.gl.util.StringHelper;
0080:        import org.springframework.util.StringUtils;
0081:
0082:        /**
0083:         * This class has the logic for the scrubber. It is required because the scrubber process needs instance variables. Instance
0084:         * variables in a spring service are shared between all code calling the service. This will make sure each run of the scrubber has
0085:         * it's own instance variables instead of being shared.
0086:         */
0087:        public class ScrubberProcess {
0088:            private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
0089:                    .getLogger(ScrubberProcess.class);
0090:
0091:            private static final String TRANSACTION_TYPE_COST_SHARE_ENCUMBRANCE = "CE";
0092:            private static final String TRANSACTION_TYPE_OFFSET = "O";
0093:            private static final String TRANSACTION_TYPE_CAPITALIZATION = "C";
0094:            private static final String TRANSACTION_TYPE_LIABILITY = "L";
0095:            private static final String TRANSACTION_TYPE_TRANSFER = "T";
0096:            private static final String TRANSACTION_TYPE_COST_SHARE = "CS";
0097:            private static final String TRANSACTION_TYPE_OTHER = "X";
0098:
0099:            private static final String COST_SHARE_CODE = "CSHR";
0100:
0101:            private static final String COST_SHARE_TRANSFER_ENTRY_IND = "***";
0102:
0103:            // These lengths are different then database field lengths, hence they are not from the DD
0104:            private static final int COST_SHARE_ENCUMBRANCE_ENTRY_MAXLENGTH = 28;
0105:            private static final int DEMERGER_TRANSACTION_LEDGET_ENTRY_DESCRIPTION = 33;
0106:            private static final int OFFSET_MESSAGE_MAXLENGTH = 33;
0107:
0108:            /* Services required */
0109:            private FlexibleOffsetAccountService flexibleOffsetAccountService;
0110:            private DocumentTypeService documentTypeService;
0111:            private OriginEntryService originEntryService;
0112:            private OriginEntryLiteService originEntryLiteService;
0113:            private OriginEntryGroupService originEntryGroupService;
0114:            private DateTimeService dateTimeService;
0115:            private OffsetDefinitionService offsetDefinitionService;
0116:            private ObjectCodeService objectCodeService;
0117:            private KualiConfigurationService configurationService;
0118:            private UniversityDateDao universityDateDao;
0119:            private PersistenceService persistenceService;
0120:            private ReportService reportService;
0121:            private ScrubberValidator scrubberValidator;
0122:            private ScrubberProcessObjectCodeOverride scrubberProcessObjectCodeOverride;
0123:            private RunDateService runDateService;
0124:            private ThreadLocal<OriginEntryLookupService> referenceLookup = new ThreadLocal<OriginEntryLookupService>();
0125:
0126:            // this will only be populated when in collector mode, otherwise the memory requirements will be huge
0127:            private Map<OriginEntry, OriginEntry> unscrubbedToUnscrubbedEntries;
0128:
0129:            /* These are all different forms of the run date for this job */
0130:            private Date runDate;
0131:            private Calendar runCal;
0132:            private UniversityDate universityRunDate;
0133:            private String offsetString;
0134:
0135:            /* These are the output groups */
0136:            private OriginEntryGroup validGroup;
0137:            private OriginEntryGroup errorGroup;
0138:            private OriginEntryGroup expiredGroup;
0139:
0140:            /* Unit Of Work info */
0141:            private UnitOfWorkInfo unitOfWork;
0142:            private KualiDecimal scrubCostShareAmount;
0143:
0144:            /* Statistics for the reports */
0145:            private ScrubberReportData scrubberReport;
0146:            private Map<Transaction, List<Message>> scrubberReportErrors;
0147:            private List<Message> transactionErrors;
0148:            private DemergerReportData demergerReport;
0149:
0150:            /* Description names */
0151:            private String offsetDescription;
0152:            private String capitalizationDescription;
0153:            private String liabilityDescription;
0154:            private String transferDescription;
0155:            private String costShareDescription;
0156:
0157:            private ParameterService parameterService;
0158:
0159:            /* Misc stuff */
0160:            private boolean reportOnlyMode;
0161:            /**
0162:             * Whether this instance is being used to support the scrubbing of a collector batch
0163:             */
0164:            private boolean collectorMode;
0165:
0166:            /**
0167:             * These parameters are all the dependencies.
0168:             */
0169:            public ScrubberProcess(
0170:                    FlexibleOffsetAccountService flexibleOffsetAccountService,
0171:                    DocumentTypeService documentTypeService,
0172:                    OriginEntryService originEntryService,
0173:                    OriginEntryGroupService originEntryGroupService,
0174:                    DateTimeService dateTimeService,
0175:                    OffsetDefinitionService offsetDefinitionService,
0176:                    ObjectCodeService objectCodeService,
0177:                    KualiConfigurationService configurationService,
0178:                    UniversityDateDao universityDateDao,
0179:                    PersistenceService persistenceService,
0180:                    ReportService reportService,
0181:                    ScrubberValidator scrubberValidator,
0182:                    ScrubberProcessObjectCodeOverride scrubberProcessObjectCodeOverride,
0183:                    RunDateService runDateService,
0184:                    OriginEntryLiteService originEntryLiteService) {
0185:                super ();
0186:                this .flexibleOffsetAccountService = flexibleOffsetAccountService;
0187:                this .documentTypeService = documentTypeService;
0188:                this .originEntryService = originEntryService;
0189:                this .originEntryLiteService = originEntryLiteService;
0190:                this .originEntryGroupService = originEntryGroupService;
0191:                this .dateTimeService = dateTimeService;
0192:                this .offsetDefinitionService = offsetDefinitionService;
0193:                this .objectCodeService = objectCodeService;
0194:                this .configurationService = configurationService;
0195:                this .universityDateDao = universityDateDao;
0196:                this .persistenceService = persistenceService;
0197:                this .reportService = reportService;
0198:                this .scrubberValidator = scrubberValidator;
0199:                this .unscrubbedToUnscrubbedEntries = new HashMap<OriginEntry, OriginEntry>();
0200:                this .scrubberProcessObjectCodeOverride = scrubberProcessObjectCodeOverride;
0201:                this .runDateService = runDateService;
0202:                collectorMode = false;
0203:                parameterService = SpringContext
0204:                        .getBean(ParameterService.class);
0205:            }
0206:
0207:            /**
0208:             * Scrub this single group read only. This will only output the scrubber report. It won't output any other groups.
0209:             * 
0210:             * @param group the origin entry group that should be scrubbed
0211:             * @param the document number of any specific entries to scrub
0212:             */
0213:            public void scrubGroupReportOnly(OriginEntryGroup group,
0214:                    String documentNumber) {
0215:                LOG.debug("scrubGroupReportOnly() started");
0216:
0217:                scrubEntries(group, documentNumber);
0218:            }
0219:
0220:            /**
0221:             * Scrubs all entries in all groups and documents.
0222:             */
0223:            public void scrubEntries() {
0224:                scrubEntries(null, null);
0225:            }
0226:
0227:            /**
0228:             * Scrubs the origin entry and ID billing details if the given batch. Store all scrubber output into the collectorReportData
0229:             * parameter. NOTE: DO NOT CALL ANY OF THE scrub* METHODS OF THIS CLASS AFTER CALLING THIS METHOD FOR EVERY UNIQUE INSTANCE OF
0230:             * THIS CLASS, OR THE COLLECTOR REPORTS MAY BE CORRUPTED
0231:             * 
0232:             * @param batch the data gathered from a Collector file
0233:             * @param collectorReportData the statistics generated by running the Collector
0234:             */
0235:            public ScrubberStatus scrubCollectorBatch(CollectorBatch batch,
0236:                    CollectorReportData collectorReportData) {
0237:                collectorMode = true;
0238:
0239:                OriginEntryGroup group = originEntryGroupService.createGroup(
0240:                        batch.getTransmissionDate(),
0241:                        OriginEntrySource.COLLECTOR, false, false, false);
0242:                for (OriginEntryFull originEntry : batch.getOriginEntries()) {
0243:                    originEntry.setGroup(group);
0244:                    originEntryService.save(originEntry);
0245:                }
0246:
0247:                // first, scrub the origin entries
0248:                scrubEntries(group, null);
0249:                // the scrubber process has just updated several member variables of this class. Store these values for the collector report
0250:                collectorReportData.setBatchOriginEntryScrubberErrors(batch,
0251:                        scrubberReportErrors);
0252:                collectorReportData
0253:                        .setScrubberReportData(batch, scrubberReport);
0254:                collectorReportData
0255:                        .setDemergerReportData(batch, demergerReport);
0256:
0257:                ScrubberStatus scrubberStatus = new ScrubberStatus();
0258:                scrubberStatus.setInputGroup(group);
0259:                scrubberStatus.setValidGroup(validGroup);
0260:                scrubberStatus.setErrorGroup(errorGroup);
0261:                scrubberStatus.setExpiredGroup(expiredGroup);
0262:                scrubberStatus
0263:                        .setUnscrubbedToScrubbedEntries(unscrubbedToUnscrubbedEntries);
0264:                return scrubberStatus;
0265:            }
0266:
0267:            /**
0268:             * Scrub all entries that need it in origin entry. Put valid scrubbed entries in a scrubber valid group, put errors in a
0269:             * scrubber error group, and transactions with an expired account in the scrubber expired account group.
0270:             * @param group the specific origin entry group to scrub
0271:             * @param documentNumber the number of the document with entries to scrub
0272:             */
0273:            public void scrubEntries(OriginEntryGroup group,
0274:                    String documentNumber) {
0275:                LOG.debug("scrubEntries() started");
0276:
0277:                // We are in report only mode if we pass a group to this method.
0278:                // if not, we are in batch mode and we scrub the backup group
0279:                reportOnlyMode = (group != null) && !collectorMode;
0280:
0281:                scrubberReportErrors = new HashMap<Transaction, List<Message>>();
0282:
0283:                // setup an object to hold the "default" date information
0284:                runDate = calculateRunDate(dateTimeService.getCurrentDate());
0285:                runCal = Calendar.getInstance();
0286:                runCal.setTime(runDate);
0287:
0288:                universityRunDate = universityDateDao.getByPrimaryKey(runDate);
0289:                if (universityRunDate == null) {
0290:                    throw new IllegalStateException(
0291:                            configurationService
0292:                                    .getPropertyString(KFSKeyConstants.ERROR_UNIV_DATE_NOT_FOUND));
0293:                }
0294:
0295:                setOffsetString();
0296:                setDescriptions();
0297:
0298:                // Create the groups that will store the valid and error entries that come out of the scrubber
0299:                // We don't need groups for the reportOnlyMode
0300:                if (!reportOnlyMode) {
0301:                    if (collectorMode) {
0302:                        // for collector mode, these groups are not meant to be permanently persisted.
0303:                        // after the collector is done, it will delete these groups, but in case there's a failure and the following groups
0304:                        // aren't created,
0305:                        // we set all of the group flags to false to prevent these groups from entering the nightly cycle
0306:                        validGroup = originEntryGroupService.createGroup(
0307:                                runDate, OriginEntrySource.SCRUBBER_VALID,
0308:                                false, false, false);
0309:                        errorGroup = originEntryGroupService.createGroup(
0310:                                runDate, OriginEntrySource.SCRUBBER_ERROR,
0311:                                false, false, false);
0312:                        expiredGroup = originEntryGroupService.createGroup(
0313:                                runDate, OriginEntrySource.SCRUBBER_EXPIRED,
0314:                                false, false, false);
0315:                    } else {
0316:                        validGroup = originEntryGroupService.createGroup(
0317:                                runDate, OriginEntrySource.SCRUBBER_VALID,
0318:                                true, true, false);
0319:                        errorGroup = originEntryGroupService.createGroup(
0320:                                runDate, OriginEntrySource.SCRUBBER_ERROR,
0321:                                false, true, false);
0322:                        expiredGroup = originEntryGroupService.createGroup(
0323:                                runDate, OriginEntrySource.SCRUBBER_EXPIRED,
0324:                                false, true, false);
0325:                    }
0326:                }
0327:
0328:                // get the origin entry groups to be processed by Scrubber
0329:                Collection<OriginEntryGroup> groupsToScrub = null;
0330:                if (reportOnlyMode || collectorMode) {
0331:                    groupsToScrub = new ArrayList<OriginEntryGroup>();
0332:                    groupsToScrub.add(group);
0333:                } else {
0334:                    groupsToScrub = originEntryGroupService
0335:                            .getAllScrubbableBackupGroups();
0336:                }
0337:                LOG.debug("scrubEntries() number of groups to scrub: "
0338:                        + groupsToScrub.size());
0339:
0340:                // generate the reports based on the origin entries to be processed by scrubber
0341:                if (reportOnlyMode) {
0342:                    reportService.generateScrubberLedgerSummaryReportOnline(
0343:                            runDate, group, documentNumber);
0344:                } else if (collectorMode) {
0345:                    // defer report generation for later
0346:                } else {
0347:                    reportService.generateScrubberLedgerSummaryReportBatch(
0348:                            runDate, groupsToScrub);
0349:                }
0350:
0351:                // Scrub all of the OriginEntryGroups waiting to be scrubbed as of runDate.
0352:                scrubberReport = new ScrubberReportData();
0353:                for (Iterator iteratorOverGroups = groupsToScrub.iterator(); iteratorOverGroups
0354:                        .hasNext();) {
0355:                    OriginEntryGroup originEntryGroup = (OriginEntryGroup) iteratorOverGroups
0356:                            .next();
0357:                    LOG.debug("scrubEntries() Scrubbing group "
0358:                            + originEntryGroup.getId());
0359:
0360:                    processGroup(originEntryGroup);
0361:
0362:                    if (!reportOnlyMode && !collectorMode) {
0363:                        // Mark the origin entry group as being processed ...
0364:                        originEntryGroup.setProcess(Boolean.FALSE);
0365:
0366:                        // ... and save the origin entry group with the new process flag.
0367:                        originEntryGroupService.save(originEntryGroup);
0368:                    }
0369:                }
0370:
0371:                // generate the scrubber status summary report
0372:                if (reportOnlyMode) {
0373:                    reportService.generateOnlineScrubberStatisticsReport(group
0374:                            .getId(), runDate, scrubberReport,
0375:                            scrubberReportErrors, documentNumber);
0376:                } else if (collectorMode) {
0377:                    // defer report generation for later
0378:                } else {
0379:                    reportService.generateBatchScrubberStatisticsReport(
0380:                            runDate, scrubberReport, scrubberReportErrors);
0381:                }
0382:
0383:                // run the demerger if during regular nightly processing and collector processing
0384:                if (!reportOnlyMode) {
0385:                    performDemerger(errorGroup, validGroup);
0386:                }
0387:
0388:                // Run the reports
0389:                if (reportOnlyMode) {
0390:                    // Run transaction list
0391:                    reportService.generateScrubberTransactionsOnline(runDate,
0392:                            group, documentNumber);
0393:                } else if (collectorMode) {
0394:                    // defer report generation for later
0395:                } else {
0396:                    // Run bad balance type report and removed transaction report
0397:                    reportService.generateScrubberBadBalanceTypeListingReport(
0398:                            runDate, groupsToScrub);
0399:                    reportService.generateScrubberRemovedTransactions(runDate,
0400:                            errorGroup);
0401:                }
0402:            }
0403:
0404:            /**
0405:             * The demerger process reads all of the documents in the error group, then moves all of the original entries for that document
0406:             * from the valid group to the error group. It does not move generated entries to the error group. Those are deleted. It also
0407:             * modifies the doc number and origin code of cost share transfers.
0408:             * 
0409:             * @param errorGroup this scrubber run's error group
0410:             * @param validGroup this scrubber run's valid group
0411:             */
0412:            private void performDemerger(OriginEntryGroup errorGroup,
0413:                    OriginEntryGroup validGroup) {
0414:                LOG.debug("performDemerger() started");
0415:
0416:                // Without this step, the job fails with Optimistic Lock Exceptions
0417:                persistenceService.clearCache();
0418:
0419:                demergerReport = new DemergerReportData();
0420:
0421:                OriginEntryStatistics eOes = originEntryService
0422:                        .getStatistics(errorGroup.getId());
0423:                demergerReport.setErrorTransactionsRead(eOes.getRowCount());
0424:
0425:                // Read all the documents from the error group and move all non-generated
0426:                // transactions for these documents from the valid group into the error group
0427:                Collection<OriginEntryFull> errorDocuments = originEntryService
0428:                        .getDocumentsByGroup(errorGroup);
0429:                Iterator<OriginEntryFull> i = errorDocuments.iterator();
0430:                while (i.hasNext()) {
0431:                    OriginEntryFull document = i.next();
0432:
0433:                    // Get all the transactions for the document in the valid group
0434:                    Iterator<OriginEntryLite> transactions = originEntryLiteService
0435:                            .getEntriesByDocument(validGroup, document
0436:                                    .getDocumentNumber(), document
0437:                                    .getFinancialDocumentTypeCode(), document
0438:                                    .getFinancialSystemOriginationCode());
0439:
0440:                    while (transactions.hasNext()) {
0441:                        OriginEntryLite transaction = transactions.next();
0442:
0443:                        String transactionType = getTransactionType(transaction);
0444:
0445:                        if (TRANSACTION_TYPE_COST_SHARE_ENCUMBRANCE
0446:                                .equals(transactionType)) {
0447:                            demergerReport
0448:                                    .incrementCostShareEncumbranceTransactionsBypassed();
0449:                            originEntryLiteService.delete(transaction);
0450:                        } else if (TRANSACTION_TYPE_OFFSET
0451:                                .equals(transactionType)) {
0452:                            demergerReport
0453:                                    .incrementOffsetTransactionsBypassed();
0454:                            originEntryLiteService.delete(transaction);
0455:                        } else if (TRANSACTION_TYPE_CAPITALIZATION
0456:                                .equals(transactionType)) {
0457:                            demergerReport
0458:                                    .incrementCapitalizationTransactionsBypassed();
0459:                            originEntryLiteService.delete(transaction);
0460:                        } else if (TRANSACTION_TYPE_LIABILITY
0461:                                .equals(transactionType)) {
0462:                            demergerReport
0463:                                    .incrementLiabilityTransactionsBypassed();
0464:                            originEntryLiteService.delete(transaction);
0465:                        } else if (TRANSACTION_TYPE_TRANSFER
0466:                                .equals(transactionType)) {
0467:                            demergerReport
0468:                                    .incrementTransferTransactionsBypassed();
0469:                            originEntryLiteService.delete(transaction);
0470:                        } else if (TRANSACTION_TYPE_COST_SHARE
0471:                                .equals(transactionType)) {
0472:                            demergerReport
0473:                                    .incrementCostShareTransactionsBypassed();
0474:                            originEntryLiteService.delete(transaction);
0475:                        } else {
0476:                            demergerReport.incrementErrorTransactionsSaved();
0477:                            transaction.setEntryGroupId(errorGroup.getId());
0478:                            originEntryLiteService.save(transaction);
0479:                        }
0480:                    }
0481:                }
0482:
0483:                // Read all the transactions in the error group and delete the generated ones
0484:                Iterator<OriginEntryLite> ie = originEntryLiteService
0485:                        .getEntriesByGroup(errorGroup);
0486:                while (ie.hasNext()) {
0487:                    OriginEntryLite transaction = ie.next();
0488:
0489:                    String transactionType = getTransactionType(transaction);
0490:
0491:                    if (TRANSACTION_TYPE_COST_SHARE_ENCUMBRANCE
0492:                            .equals(transactionType)) {
0493:                        demergerReport
0494:                                .incrementCostShareEncumbranceTransactionsBypassed();
0495:                        originEntryLiteService.delete(transaction);
0496:                    } else if (TRANSACTION_TYPE_OFFSET.equals(transactionType)) {
0497:                        demergerReport.incrementOffsetTransactionsBypassed();
0498:                        originEntryLiteService.delete(transaction);
0499:                    } else if (TRANSACTION_TYPE_CAPITALIZATION
0500:                            .equals(transactionType)) {
0501:                        demergerReport
0502:                                .incrementCapitalizationTransactionsBypassed();
0503:                        originEntryLiteService.delete(transaction);
0504:                    } else if (TRANSACTION_TYPE_LIABILITY
0505:                            .equals(transactionType)) {
0506:                        demergerReport.incrementLiabilityTransactionsBypassed();
0507:                        originEntryLiteService.delete(transaction);
0508:                    } else if (TRANSACTION_TYPE_TRANSFER
0509:                            .equals(transactionType)) {
0510:                        demergerReport.incrementTransferTransactionsBypassed();
0511:                        originEntryLiteService.delete(transaction);
0512:                    } else if (TRANSACTION_TYPE_COST_SHARE
0513:                            .equals(transactionType)) {
0514:                        demergerReport.incrementCostShareTransactionsBypassed();
0515:                        originEntryLiteService.delete(transaction);
0516:                    }
0517:                }
0518:
0519:                // Read all the transactions in the valid group and update the cost share transactions
0520:                Iterator<OriginEntryLite> it = originEntryLiteService
0521:                        .getEntriesByGroup(validGroup);
0522:                while (it.hasNext()) {
0523:                    OriginEntryLite transaction = it.next();
0524:                    demergerReport.incrementValidTransactionsSaved();
0525:
0526:                    String transactionType = getTransactionType(transaction);
0527:                    if (TRANSACTION_TYPE_COST_SHARE.equals(transactionType)) {
0528:                        transaction
0529:                                .setFinancialDocumentTypeCode(KFSConstants.TRANSFER_FUNDS);
0530:                        transaction
0531:                                .setFinancialSystemOriginationCode(KFSConstants.COST_SHARE);
0532:                        StringBuffer docNbr = new StringBuffer(COST_SHARE_CODE);
0533:
0534:                        String desc = transaction
0535:                                .getTransactionLedgerEntryDescription();
0536:
0537:                        docNbr.append(desc.substring(36, 38));
0538:                        docNbr.append("/");
0539:                        docNbr.append(desc.substring(38, 40));
0540:                        transaction.setDocumentNumber(docNbr.toString());
0541:
0542:                        transaction
0543:                                .setTransactionLedgerEntryDescription(desc
0544:                                        .substring(0,
0545:                                                DEMERGER_TRANSACTION_LEDGET_ENTRY_DESCRIPTION));
0546:
0547:                        originEntryLiteService.save(transaction);
0548:                    }
0549:                }
0550:
0551:                eOes = originEntryService.getStatistics(errorGroup.getId());
0552:                demergerReport.setErrorTransactionWritten(eOes.getRowCount());
0553:
0554:                if (!collectorMode) {
0555:                    reportService.generateScrubberDemergerStatisticsReports(
0556:                            runDate, demergerReport);
0557:                }
0558:            }
0559:
0560:            /**
0561:             * Determine the type of the transaction by looking at attributes
0562:             * 
0563:             * @param transaction Transaction to identify
0564:             * @return CE (Cost share encumbrance, O (Offset), C (apitalization), L (Liability), T (Transfer), CS (Cost Share), X (Other)
0565:             */
0566:            private String getTransactionType(OriginEntry transaction) {
0567:                if (TRANSACTION_TYPE_COST_SHARE_ENCUMBRANCE.equals(transaction
0568:                        .getFinancialBalanceTypeCode())) {
0569:                    return TRANSACTION_TYPE_COST_SHARE_ENCUMBRANCE;
0570:                }
0571:                String desc = transaction
0572:                        .getTransactionLedgerEntryDescription();
0573:
0574:                if (desc == null) {
0575:                    return TRANSACTION_TYPE_OTHER;
0576:                }
0577:
0578:                if (desc.startsWith(offsetDescription)
0579:                        && desc.indexOf(COST_SHARE_TRANSFER_ENTRY_IND) > -1) {
0580:                    return TRANSACTION_TYPE_COST_SHARE;
0581:                }
0582:                if (desc.startsWith(costShareDescription)
0583:                        && desc.indexOf(COST_SHARE_TRANSFER_ENTRY_IND) > -1) {
0584:                    return TRANSACTION_TYPE_COST_SHARE;
0585:                }
0586:                if (desc.startsWith(offsetDescription)) {
0587:                    return TRANSACTION_TYPE_OFFSET;
0588:                }
0589:                if (desc.startsWith(capitalizationDescription)) {
0590:                    return TRANSACTION_TYPE_CAPITALIZATION;
0591:                }
0592:                if (desc.startsWith(liabilityDescription)) {
0593:                    return TRANSACTION_TYPE_LIABILITY;
0594:                }
0595:                if (desc.startsWith(transferDescription)) {
0596:                    return TRANSACTION_TYPE_TRANSFER;
0597:                }
0598:                return TRANSACTION_TYPE_OTHER;
0599:            }
0600:
0601:            /**
0602:             * This will process a group of origin entries. The COBOL code was refactored a lot to get this so there isn't a 1 to 1 section
0603:             * of Cobol relating to this.
0604:             * 
0605:             * @param originEntryGroup Group to process
0606:             */
0607:            private void processGroup(OriginEntryGroup originEntryGroup) {
0608:                this .referenceLookup.get().setLookupService(
0609:                        SpringContext.getBean(CachingLookup.class));
0610:
0611:                OriginEntry lastEntry = null;
0612:                scrubCostShareAmount = KualiDecimal.ZERO;
0613:                unitOfWork = new UnitOfWorkInfo();
0614:
0615:                LOG.info("Starting Scrubber Process process group...");
0616:                Iterator entries = originEntryLiteService
0617:                        .getEntriesByGroup(originEntryGroup);
0618:                while (entries.hasNext()) {
0619:                    OriginEntry unscrubbedEntry = (OriginEntry) entries.next();
0620:                    scrubberReport.incrementUnscrubbedRecordsRead();
0621:
0622:                    transactionErrors = new ArrayList<Message>();
0623:
0624:                    // This is done so if the code modifies this row, then saves it, it will be an insert,
0625:                    // and it won't touch the original. The Scrubber never modifies input rows/groups.
0626:                    unscrubbedEntry.setEntryGroupId(null);
0627:                    unscrubbedEntry.resetEntryId();
0628:
0629:                    boolean saveErrorTransaction = false;
0630:                    boolean saveValidTransaction = false;
0631:
0632:                    // Build a scrubbed entry
0633:                    OriginEntry scrubbedEntry = new OriginEntryLite();
0634:                    scrubbedEntry.setDocumentNumber(unscrubbedEntry
0635:                            .getDocumentNumber());
0636:                    scrubbedEntry.setOrganizationDocumentNumber(unscrubbedEntry
0637:                            .getOrganizationDocumentNumber());
0638:                    scrubbedEntry.setOrganizationReferenceId(unscrubbedEntry
0639:                            .getOrganizationReferenceId());
0640:                    scrubbedEntry
0641:                            .setReferenceFinancialDocumentNumber(unscrubbedEntry
0642:                                    .getReferenceFinancialDocumentNumber());
0643:
0644:                    Integer transactionNumber = unscrubbedEntry
0645:                            .getTransactionLedgerEntrySequenceNumber();
0646:                    scrubbedEntry
0647:                            .setTransactionLedgerEntrySequenceNumber(null == transactionNumber ? new Integer(
0648:                                    0)
0649:                                    : transactionNumber);
0650:                    scrubbedEntry
0651:                            .setTransactionLedgerEntryDescription(unscrubbedEntry
0652:                                    .getTransactionLedgerEntryDescription());
0653:                    scrubbedEntry
0654:                            .setTransactionLedgerEntryAmount(unscrubbedEntry
0655:                                    .getTransactionLedgerEntryAmount());
0656:                    scrubbedEntry.setTransactionDebitCreditCode(unscrubbedEntry
0657:                            .getTransactionDebitCreditCode());
0658:
0659:                    // For Labor Scrubber
0660:                    boolean laborIndicator = false;
0661:
0662:                    List<Message> tmperrors = scrubberValidator
0663:                            .validateTransaction(unscrubbedEntry,
0664:                                    scrubbedEntry, universityRunDate,
0665:                                    laborIndicator);
0666:                    transactionErrors.addAll(tmperrors);
0667:
0668:                    // Expired account?
0669:                    Account unscrubbedEntryAccount = referenceLookup.get()
0670:                            .getAccount(unscrubbedEntry);
0671:                    if ((unscrubbedEntryAccount != null)
0672:                            && (unscrubbedEntryAccount
0673:                                    .isAccountClosedIndicator())) {
0674:                        // Make a copy of it so OJB doesn't just update the row in the original
0675:                        // group. It needs to make a new one in the expired group
0676:                        OriginEntryFull expiredEntry = OriginEntryFull
0677:                                .copyFromOriginEntryable(scrubbedEntry);
0678:
0679:                        createOutputEntry(expiredEntry, expiredGroup);
0680:                        scrubberReport.incrementExpiredAccountFound();
0681:                    }
0682:
0683:                    if (!isFatal(transactionErrors)) {
0684:                        saveValidTransaction = true;
0685:
0686:                        if (collectorMode) {
0687:                            // only populate this map in collector mode because it's only needed for the collector
0688:
0689:                            // the collector scrubber uses this map to apply the same changes made on an origin entry during scrubbing to
0690:                            // the collector detail record
0691:                            unscrubbedToUnscrubbedEntries.put(unscrubbedEntry,
0692:                                    scrubbedEntry);
0693:
0694:                            // for the collector, we don't need further processing, since we're going to rescrub all of the origin entries
0695:                            // anyways during the nightly process
0696:                        } else {
0697:
0698:                            // See if unit of work has changed
0699:                            if (!unitOfWork.isSameUnitOfWork(scrubbedEntry)) {
0700:                                // Generate offset for last unit of work
0701:                                generateOffset(lastEntry);
0702:
0703:                                unitOfWork = new UnitOfWorkInfo(scrubbedEntry);
0704:                            }
0705:
0706:                            KualiDecimal transactionAmount = scrubbedEntry
0707:                                    .getTransactionLedgerEntryAmount();
0708:
0709:                            ParameterEvaluator offsetFiscalPeriods = parameterService
0710:                                    .getParameterEvaluator(
0711:                                            ScrubberStep.class,
0712:                                            GLConstants.GlScrubberGroupRules.OFFSET_FISCAL_PERIOD_CODES,
0713:                                            scrubbedEntry
0714:                                                    .getUniversityFiscalPeriodCode());
0715:
0716:                            BalanceTyp scrubbedEntryBalanceType = referenceLookup
0717:                                    .get().getBalanceType(scrubbedEntry);
0718:                            if (scrubbedEntryBalanceType
0719:                                    .isFinancialOffsetGenerationIndicator()
0720:                                    && offsetFiscalPeriods.evaluationSucceeds()) {
0721:                                if (scrubbedEntry.isDebit()) {
0722:                                    unitOfWork.offsetAmount = unitOfWork.offsetAmount
0723:                                            .add(transactionAmount);
0724:                                } else {
0725:                                    unitOfWork.offsetAmount = unitOfWork.offsetAmount
0726:                                            .subtract(transactionAmount);
0727:                                }
0728:                            }
0729:
0730:                            // The sub account type code will only exist if there is a valid sub account
0731:                            String subAccountTypeCode = GLConstants
0732:                                    .getSpaceSubAccountTypeCode();
0733:                            // major assumption: the a21 subaccount is proxied, so we don't want to query the database if the subacct
0734:                            // number is dashes
0735:                            A21SubAccount scrubbedEntryA21SubAccount = referenceLookup
0736:                                    .get().getA21SubAccount(scrubbedEntry);
0737:                            if (!KFSConstants.getDashSubAccountNumber().equals(
0738:                                    scrubbedEntry.getSubAccountNumber())
0739:                                    && scrubbedEntryA21SubAccount != null) {
0740:                                subAccountTypeCode = scrubbedEntryA21SubAccount
0741:                                        .getSubAccountTypeCode();
0742:
0743:                            }
0744:
0745:                            ParameterEvaluator costShareObjectTypeCodes = parameterService
0746:                                    .getParameterEvaluator(
0747:                                            ScrubberStep.class,
0748:                                            GLConstants.GlScrubberGroupRules.COST_SHARE_OBJ_TYPE_CODES,
0749:                                            scrubbedEntry
0750:                                                    .getFinancialObjectTypeCode());
0751:                            ParameterEvaluator costShareEncBalanceTypeCodes = parameterService
0752:                                    .getParameterEvaluator(
0753:                                            ScrubberStep.class,
0754:                                            GLConstants.GlScrubberGroupRules.COST_SHARE_ENC_BAL_TYP_CODES,
0755:                                            scrubbedEntry
0756:                                                    .getFinancialBalanceTypeCode());
0757:                            ParameterEvaluator costShareEncFiscalPeriodCodes = parameterService
0758:                                    .getParameterEvaluator(
0759:                                            ScrubberStep.class,
0760:                                            GLConstants.GlScrubberGroupRules.COST_SHARE_ENC_FISCAL_PERIOD_CODES,
0761:                                            scrubbedEntry
0762:                                                    .getUniversityFiscalPeriodCode());
0763:                            ParameterEvaluator costShareEncDocTypeCodes = parameterService
0764:                                    .getParameterEvaluator(
0765:                                            ScrubberStep.class,
0766:                                            GLConstants.GlScrubberGroupRules.COST_SHARE_ENC_DOC_TYPE_CODES,
0767:                                            scrubbedEntry
0768:                                                    .getFinancialDocumentTypeCode()
0769:                                                    .trim());
0770:                            ParameterEvaluator costShareFiscalPeriodCodes = parameterService
0771:                                    .getParameterEvaluator(
0772:                                            ScrubberStep.class,
0773:                                            GLConstants.GlScrubberGroupRules.COST_SHARE_FISCAL_PERIOD_CODES,
0774:                                            scrubbedEntry
0775:                                                    .getUniversityFiscalPeriodCode());
0776:
0777:                            Account scrubbedEntryAccount = referenceLookup
0778:                                    .get().getAccount(scrubbedEntry);
0779:                            if (costShareObjectTypeCodes.evaluationSucceeds()
0780:                                    && costShareEncBalanceTypeCodes
0781:                                            .evaluationSucceeds()
0782:                                    && scrubbedEntryAccount
0783:                                            .isForContractsAndGrants()
0784:                                    && KFSConstants.COST_SHARE
0785:                                            .equals(subAccountTypeCode)
0786:                                    && costShareEncFiscalPeriodCodes
0787:                                            .evaluationSucceeds()
0788:                                    && costShareEncDocTypeCodes
0789:                                            .evaluationSucceeds()) {
0790:                                TransactionError te1 = generateCostShareEncumbranceEntries(scrubbedEntry);
0791:                                if (te1 != null) {
0792:                                    List errors = new ArrayList();
0793:                                    errors.add(te1.message);
0794:                                    scrubberReportErrors.put(te1.transaction,
0795:                                            errors);
0796:
0797:                                    saveValidTransaction = false;
0798:                                    saveErrorTransaction = true;
0799:                                }
0800:                            }
0801:
0802:                            Options scrubbedEntryOption = referenceLookup.get()
0803:                                    .getOption(scrubbedEntry);
0804:                            if (costShareObjectTypeCodes.evaluationSucceeds()
0805:                                    && scrubbedEntryOption
0806:                                            .getActualFinancialBalanceTypeCd()
0807:                                            .equals(
0808:                                                    scrubbedEntry
0809:                                                            .getFinancialBalanceTypeCode())
0810:                                    && scrubbedEntryAccount
0811:                                            .isForContractsAndGrants()
0812:                                    && KFSConstants.COST_SHARE
0813:                                            .equals(subAccountTypeCode)
0814:                                    && costShareFiscalPeriodCodes
0815:                                            .evaluationSucceeds()
0816:                                    && costShareEncDocTypeCodes
0817:                                            .evaluationSucceeds()) {
0818:                                if (scrubbedEntry.isDebit()) {
0819:                                    scrubCostShareAmount = scrubCostShareAmount
0820:                                            .subtract(transactionAmount);
0821:                                } else {
0822:                                    scrubCostShareAmount = scrubCostShareAmount
0823:                                            .add(transactionAmount);
0824:                                }
0825:                            }
0826:
0827:                            ParameterEvaluator otherDocTypeCodes = parameterService
0828:                                    .getParameterEvaluator(
0829:                                            ScrubberStep.class,
0830:                                            GLConstants.GlScrubberGroupRules.OFFSET_DOC_TYPE_CODES,
0831:                                            scrubbedEntry
0832:                                                    .getFinancialDocumentTypeCode());
0833:
0834:                            if (otherDocTypeCodes.evaluationSucceeds()) {
0835:                                String m = processCapitalization(scrubbedEntry);
0836:                                if (m != null) {
0837:                                    saveValidTransaction = false;
0838:                                    saveErrorTransaction = false;
0839:                                    addTransactionError(m, "",
0840:                                            Message.TYPE_FATAL);
0841:                                }
0842:
0843:                                m = processLiabilities(scrubbedEntry);
0844:                                if (m != null) {
0845:                                    saveValidTransaction = false;
0846:                                    saveErrorTransaction = false;
0847:                                    addTransactionError(m, "",
0848:                                            Message.TYPE_FATAL);
0849:                                }
0850:
0851:                                m = processPlantIndebtedness(scrubbedEntry);
0852:                                if (m != null) {
0853:                                    saveValidTransaction = false;
0854:                                    saveErrorTransaction = false;
0855:                                    addTransactionError(m, "",
0856:                                            Message.TYPE_FATAL);
0857:                                }
0858:                            }
0859:
0860:                            if (!scrubCostShareAmount.isZero()) {
0861:                                TransactionError te = generateCostShareEntries(scrubbedEntry);
0862:
0863:                                if (te != null) {
0864:                                    saveValidTransaction = false;
0865:                                    saveErrorTransaction = false;
0866:
0867:                                    // Make a copy of it so OJB doesn't just update the row in the original
0868:                                    // group. It needs to make a new one in the error group
0869:                                    OriginEntryFull errorEntry = new OriginEntryFull(
0870:                                            te.transaction);
0871:                                    errorEntry
0872:                                            .setTransactionScrubberOffsetGenerationIndicator(false);
0873:                                    createOutputEntry(errorEntry, errorGroup);
0874:                                    scrubberReport
0875:                                            .incrementErrorRecordWritten();
0876:
0877:                                    List messages = new ArrayList();
0878:                                    messages.add(te.message);
0879:                                    scrubberReportErrors.put(errorEntry,
0880:                                            messages);
0881:                                }
0882:                                scrubCostShareAmount = KualiDecimal.ZERO;
0883:                            }
0884:
0885:                            if (transactionErrors.size() > 0) {
0886:                                scrubberReportErrors
0887:                                        .put(
0888:                                                OriginEntryFull
0889:                                                        .copyFromOriginEntryable(scrubbedEntry),
0890:                                                transactionErrors);
0891:                            }
0892:
0893:                            lastEntry = scrubbedEntry;
0894:
0895:                        }
0896:                    } else {
0897:                        // Error transaction
0898:                        saveErrorTransaction = true;
0899:
0900:                        scrubberReportErrors.put(OriginEntryFull
0901:                                .copyFromOriginEntryable(unscrubbedEntry),
0902:                                transactionErrors);
0903:                    }
0904:
0905:                    if (saveValidTransaction) {
0906:                        scrubbedEntry
0907:                                .setTransactionScrubberOffsetGenerationIndicator(false);
0908:                        createOutputEntry(scrubbedEntry, validGroup);
0909:                        scrubberReport.incrementScrubbedRecordWritten();
0910:                    }
0911:
0912:                    if (saveErrorTransaction) {
0913:                        // Make a copy of it so OJB doesn't just update the row in the original
0914:                        // group. It needs to make a new one in the error group
0915:                        OriginEntryFull errorEntry = OriginEntryFull
0916:                                .copyFromOriginEntryable(unscrubbedEntry);
0917:                        errorEntry
0918:                                .setTransactionScrubberOffsetGenerationIndicator(false);
0919:                        createOutputEntry(errorEntry, errorGroup);
0920:                        scrubberReport.incrementErrorRecordWritten();
0921:                    }
0922:                }
0923:
0924:                if (!collectorMode) {
0925:                    // Generate last offset (if necessary)
0926:                    generateOffset(lastEntry);
0927:                }
0928:
0929:                this .referenceLookup.get().setLookupService(null);
0930:            }
0931:
0932:            /**
0933:             * Determines if a given error is fatal and should stop this scrubber run
0934:             * 
0935:             * @param errors errors from a scrubber run
0936:             * @return true if the run should be abended, false otherwise
0937:             */
0938:            private boolean isFatal(List<Message> errors) {
0939:                for (Iterator<Message> iter = errors.iterator(); iter.hasNext();) {
0940:                    Message element = iter.next();
0941:                    if (element.getType() == Message.TYPE_FATAL) {
0942:                        return true;
0943:                    }
0944:                }
0945:                return false;
0946:            }
0947:
0948:            /**
0949:             * Generates a cost share entry and offset for the given entry and saves both to the valid group
0950:             * 
0951:             * @param scrubbedEntry the originEntry that was scrubbed
0952:             * @return a TransactionError initialized with any error encounted during entry generation, or (hopefully) null
0953:             */
0954:            private TransactionError generateCostShareEntries(
0955:                    OriginEntry scrubbedEntry) {
0956:                // 3000-COST-SHARE to 3100-READ-OFSD in the cobol Generate Cost Share Entries
0957:                LOG.debug("generateCostShareEntries() started");
0958:
0959:                OriginEntryFull costShareEntry = OriginEntryFull
0960:                        .copyFromOriginEntryable(scrubbedEntry);
0961:
0962:                Options scrubbedEntryOption = referenceLookup.get().getOption(
0963:                        scrubbedEntry);
0964:                A21SubAccount scrubbedEntryA21SubAccount = referenceLookup
0965:                        .get().getA21SubAccount(scrubbedEntry);
0966:
0967:                costShareEntry
0968:                        .setFinancialObjectCode(parameterService
0969:                                .getParameterValue(
0970:                                        ScrubberStep.class,
0971:                                        GLConstants.GlScrubberGroupParameters.COST_SHARE_OBJECT_CODE_PARM_NM));
0972:                costShareEntry.setFinancialSubObjectCode(KFSConstants
0973:                        .getDashFinancialSubObjectCode());
0974:                costShareEntry.setFinancialObjectTypeCode(scrubbedEntryOption
0975:                        .getFinancialObjectTypeTransferExpenseCd());
0976:                costShareEntry
0977:                        .setTransactionLedgerEntrySequenceNumber(new Integer(0));
0978:
0979:                StringBuffer description = new StringBuffer();
0980:                description.append(costShareDescription);
0981:                description.append(" ")
0982:                        .append(scrubbedEntry.getAccountNumber());
0983:                description.append(offsetString);
0984:                costShareEntry.setTransactionLedgerEntryDescription(description
0985:                        .toString());
0986:
0987:                costShareEntry
0988:                        .setTransactionLedgerEntryAmount(scrubCostShareAmount);
0989:                if (scrubCostShareAmount.isPositive()) {
0990:                    costShareEntry
0991:                            .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
0992:                } else {
0993:                    costShareEntry
0994:                            .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
0995:                    costShareEntry
0996:                            .setTransactionLedgerEntryAmount(scrubCostShareAmount
0997:                                    .negated());
0998:                }
0999:
1000:                costShareEntry.setTransactionDate(runDate);
1001:                costShareEntry.setOrganizationDocumentNumber(null);
1002:                costShareEntry
1003:                        .setProjectCode(KFSConstants.getDashProjectCode());
1004:                costShareEntry.setOrganizationReferenceId(null);
1005:                costShareEntry.setReferenceFinancialDocumentTypeCode(null);
1006:                costShareEntry.setReferenceFinancialSystemOriginationCode(null);
1007:                costShareEntry.setReferenceFinancialDocumentNumber(null);
1008:                costShareEntry.setFinancialDocumentReversalDate(null);
1009:                costShareEntry.setTransactionEncumbranceUpdateCode(null);
1010:
1011:                createOutputEntry(costShareEntry, validGroup);
1012:                scrubberReport.incrementCostShareEntryGenerated();
1013:
1014:                OriginEntryFull costShareOffsetEntry = new OriginEntryFull(
1015:                        costShareEntry);
1016:                costShareOffsetEntry
1017:                        .setTransactionLedgerEntryDescription(getOffsetMessage());
1018:
1019:                OffsetDefinition offsetDefinition = offsetDefinitionService
1020:                        .getByPrimaryId(
1021:                                scrubbedEntry.getUniversityFiscalYear(),
1022:                                scrubbedEntry.getChartOfAccountsCode(),
1023:                                KFSConstants.TRANSFER_FUNDS, scrubbedEntry
1024:                                        .getFinancialBalanceTypeCode());
1025:                if (offsetDefinition != null) {
1026:                    if (offsetDefinition.getFinancialObject() == null) {
1027:                        StringBuffer objectCodeKey = new StringBuffer();
1028:                        objectCodeKey.append(offsetDefinition
1029:                                .getUniversityFiscalYear());
1030:                        objectCodeKey.append("-").append(
1031:                                offsetDefinition.getChartOfAccountsCode());
1032:                        objectCodeKey.append("-").append(
1033:                                offsetDefinition.getFinancialObjectCode());
1034:
1035:                        Message m = new Message(
1036:                                configurationService
1037:                                        .getPropertyString(KFSKeyConstants.ERROR_OFFSET_DEFINITION_OBJECT_CODE_NOT_FOUND)
1038:                                        + " (" + objectCodeKey.toString() + ")",
1039:                                Message.TYPE_FATAL);
1040:                        LOG
1041:                                .debug("generateCostShareEntries() Error 1 object not found");
1042:                        return new TransactionError(costShareEntry, m);
1043:                    }
1044:
1045:                    costShareOffsetEntry
1046:                            .setFinancialObjectCode(offsetDefinition
1047:                                    .getFinancialObjectCode());
1048:                    costShareOffsetEntry.setFinancialObject(offsetDefinition
1049:                            .getFinancialObject());
1050:                    costShareOffsetEntry.setFinancialSubObjectCode(KFSConstants
1051:                            .getDashFinancialSubObjectCode());
1052:
1053:                } else {
1054:                    Map<Transaction, List<Message>> errors = new HashMap<Transaction, List<Message>>();
1055:
1056:                    StringBuffer offsetKey = new StringBuffer(
1057:                            "cost share transfer ");
1058:                    offsetKey.append(scrubbedEntry.getUniversityFiscalYear());
1059:                    offsetKey.append("-");
1060:                    offsetKey.append(scrubbedEntry.getChartOfAccountsCode());
1061:                    offsetKey.append("-TF-");
1062:                    offsetKey.append(scrubbedEntry
1063:                            .getFinancialBalanceTypeCode());
1064:
1065:                    Message m = new Message(
1066:                            configurationService
1067:                                    .getPropertyString(KFSKeyConstants.ERROR_OFFSET_DEFINITION_NOT_FOUND)
1068:                                    + " (" + offsetKey.toString() + ")",
1069:                            Message.TYPE_FATAL);
1070:
1071:                    LOG
1072:                            .debug("generateCostShareEntries() Error 2 offset not found");
1073:                    return new TransactionError(costShareEntry, m);
1074:                }
1075:
1076:                costShareOffsetEntry
1077:                        .setFinancialObjectTypeCode(offsetDefinition
1078:                                .getFinancialObject()
1079:                                .getFinancialObjectTypeCode());
1080:
1081:                if (costShareEntry.isCredit()) {
1082:                    costShareOffsetEntry
1083:                            .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
1084:                } else {
1085:                    costShareOffsetEntry
1086:                            .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
1087:                }
1088:
1089:                try {
1090:                    flexibleOffsetAccountService
1091:                            .updateOffset(costShareOffsetEntry);
1092:                } catch (InvalidFlexibleOffsetException e) {
1093:                    Message m = new Message(e.getMessage(), Message.TYPE_FATAL);
1094:                    LOG
1095:                            .debug("generateCostShareEntries() Cost Share Transfer Flexible Offset Error: "
1096:                                    + e.getMessage());
1097:                    return new TransactionError(costShareEntry, m);
1098:                }
1099:
1100:                createOutputEntry(costShareOffsetEntry, validGroup);
1101:                scrubberReport.incrementCostShareEntryGenerated();
1102:
1103:                OriginEntryFull costShareSourceAccountEntry = new OriginEntryFull(
1104:                        costShareEntry);
1105:
1106:                description = new StringBuffer();
1107:                description.append(costShareDescription);
1108:                description.append(" ")
1109:                        .append(scrubbedEntry.getAccountNumber());
1110:                description.append(offsetString);
1111:                costShareSourceAccountEntry
1112:                        .setTransactionLedgerEntryDescription(description
1113:                                .toString());
1114:
1115:                costShareSourceAccountEntry
1116:                        .setChartOfAccountsCode(scrubbedEntryA21SubAccount
1117:                                .getCostShareChartOfAccountCode());
1118:                costShareSourceAccountEntry
1119:                        .setAccountNumber(scrubbedEntryA21SubAccount
1120:                                .getCostShareSourceAccountNumber());
1121:
1122:                setCostShareObjectCode(costShareSourceAccountEntry,
1123:                        scrubbedEntry);
1124:                costShareSourceAccountEntry
1125:                        .setSubAccountNumber(scrubbedEntryA21SubAccount
1126:                                .getCostShareSourceSubAccountNumber());
1127:
1128:                if (StringHelper.isNullOrEmpty(costShareSourceAccountEntry
1129:                        .getSubAccountNumber())) {
1130:                    costShareSourceAccountEntry
1131:                            .setSubAccountNumber(KFSConstants
1132:                                    .getDashSubAccountNumber());
1133:                }
1134:
1135:                costShareSourceAccountEntry
1136:                        .setFinancialSubObjectCode(KFSConstants
1137:                                .getDashFinancialSubObjectCode());
1138:                costShareSourceAccountEntry
1139:                        .setFinancialObjectTypeCode(scrubbedEntryOption
1140:                                .getFinancialObjectTypeTransferExpenseCd());
1141:                costShareSourceAccountEntry
1142:                        .setTransactionLedgerEntrySequenceNumber(new Integer(0));
1143:
1144:                costShareSourceAccountEntry
1145:                        .setTransactionLedgerEntryAmount(scrubCostShareAmount);
1146:                if (scrubCostShareAmount.isPositive()) {
1147:                    costShareSourceAccountEntry
1148:                            .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
1149:                } else {
1150:                    costShareSourceAccountEntry
1151:                            .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
1152:                    costShareSourceAccountEntry
1153:                            .setTransactionLedgerEntryAmount(scrubCostShareAmount
1154:                                    .negated());
1155:                }
1156:
1157:                costShareSourceAccountEntry.setTransactionDate(runDate);
1158:                costShareSourceAccountEntry.setOrganizationDocumentNumber(null);
1159:                costShareSourceAccountEntry.setProjectCode(KFSConstants
1160:                        .getDashProjectCode());
1161:                costShareSourceAccountEntry.setOrganizationReferenceId(null);
1162:                costShareSourceAccountEntry
1163:                        .setReferenceFinancialDocumentTypeCode(null);
1164:                costShareSourceAccountEntry
1165:                        .setReferenceFinancialSystemOriginationCode(null);
1166:                costShareSourceAccountEntry
1167:                        .setReferenceFinancialDocumentNumber(null);
1168:                costShareSourceAccountEntry
1169:                        .setFinancialDocumentReversalDate(null);
1170:                costShareSourceAccountEntry
1171:                        .setTransactionEncumbranceUpdateCode(null);
1172:
1173:                createOutputEntry(costShareSourceAccountEntry, validGroup);
1174:                scrubberReport.incrementCostShareEntryGenerated();
1175:
1176:                OriginEntryFull costShareSourceAccountOffsetEntry = new OriginEntryFull(
1177:                        costShareSourceAccountEntry);
1178:                costShareSourceAccountOffsetEntry
1179:                        .setTransactionLedgerEntryDescription(getOffsetMessage());
1180:
1181:                // Lookup the new offset definition.
1182:                offsetDefinition = offsetDefinitionService.getByPrimaryId(
1183:                        scrubbedEntry.getUniversityFiscalYear(), scrubbedEntry
1184:                                .getChartOfAccountsCode(),
1185:                        KFSConstants.TRANSFER_FUNDS, scrubbedEntry
1186:                                .getFinancialBalanceTypeCode());
1187:                if (offsetDefinition != null) {
1188:                    if (offsetDefinition.getFinancialObject() == null) {
1189:                        Map<Transaction, List<Message>> errors = new HashMap<Transaction, List<Message>>();
1190:
1191:                        StringBuffer objectCodeKey = new StringBuffer();
1192:                        objectCodeKey.append(costShareEntry
1193:                                .getUniversityFiscalYear());
1194:                        objectCodeKey.append("-").append(
1195:                                scrubbedEntry.getChartOfAccountsCode());
1196:                        objectCodeKey.append("-").append(
1197:                                scrubbedEntry.getFinancialObjectCode());
1198:
1199:                        Message m = new Message(
1200:                                configurationService
1201:                                        .getPropertyString(KFSKeyConstants.ERROR_OFFSET_DEFINITION_OBJECT_CODE_NOT_FOUND)
1202:                                        + " (" + objectCodeKey.toString() + ")",
1203:                                Message.TYPE_FATAL);
1204:
1205:                        LOG
1206:                                .debug("generateCostShareEntries() Error 3 object not found");
1207:                        return new TransactionError(
1208:                                costShareSourceAccountEntry, m);
1209:                    }
1210:
1211:                    costShareSourceAccountOffsetEntry
1212:                            .setFinancialObjectCode(offsetDefinition
1213:                                    .getFinancialObjectCode());
1214:                    costShareSourceAccountOffsetEntry
1215:                            .setFinancialObject(offsetDefinition
1216:                                    .getFinancialObject());
1217:                    costShareSourceAccountOffsetEntry
1218:                            .setFinancialSubObjectCode(KFSConstants
1219:                                    .getDashFinancialSubObjectCode());
1220:                } else {
1221:                    Map<Transaction, List<Message>> errors = new HashMap<Transaction, List<Message>>();
1222:
1223:                    StringBuffer offsetKey = new StringBuffer(
1224:                            "cost share transfer source ");
1225:                    offsetKey.append(scrubbedEntry.getUniversityFiscalYear());
1226:                    offsetKey.append("-");
1227:                    offsetKey.append(scrubbedEntry.getChartOfAccountsCode());
1228:                    offsetKey.append("-TF-");
1229:                    offsetKey.append(scrubbedEntry
1230:                            .getFinancialBalanceTypeCode());
1231:
1232:                    Message m = new Message(
1233:                            configurationService
1234:                                    .getPropertyString(KFSKeyConstants.ERROR_OFFSET_DEFINITION_NOT_FOUND)
1235:                                    + " (" + offsetKey.toString() + ")",
1236:                            Message.TYPE_FATAL);
1237:
1238:                    LOG
1239:                            .debug("generateCostShareEntries() Error 4 offset not found");
1240:                    return new TransactionError(costShareSourceAccountEntry, m);
1241:                }
1242:
1243:                costShareSourceAccountOffsetEntry
1244:                        .setFinancialObjectTypeCode(offsetDefinition
1245:                                .getFinancialObject()
1246:                                .getFinancialObjectTypeCode());
1247:
1248:                if (scrubbedEntry.isCredit()) {
1249:                    costShareSourceAccountOffsetEntry
1250:                            .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
1251:                } else {
1252:                    costShareSourceAccountOffsetEntry
1253:                            .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
1254:                }
1255:
1256:                try {
1257:                    flexibleOffsetAccountService
1258:                            .updateOffset(costShareSourceAccountOffsetEntry);
1259:                } catch (InvalidFlexibleOffsetException e) {
1260:                    Message m = new Message(e.getMessage(), Message.TYPE_FATAL);
1261:                    LOG
1262:                            .debug("generateCostShareEntries() Cost Share Transfer Account Flexible Offset Error: "
1263:                                    + e.getMessage());
1264:                    return new TransactionError(costShareEntry, m);
1265:                }
1266:
1267:                createOutputEntry(costShareSourceAccountOffsetEntry, validGroup);
1268:                scrubberReport.incrementCostShareEntryGenerated();
1269:
1270:                scrubCostShareAmount = KualiDecimal.ZERO;
1271:
1272:                LOG.debug("generateCostShareEntries() successful");
1273:                return null;
1274:            }
1275:
1276:            /**
1277:             * Get all the transaction descriptions from the param table
1278:             */
1279:            private void setDescriptions() {
1280:                offsetDescription = configurationService
1281:                        .getPropertyString(KFSKeyConstants.MSG_GENERATED_OFFSET);
1282:                capitalizationDescription = configurationService
1283:                        .getPropertyString(KFSKeyConstants.MSG_GENERATED_CAPITALIZATION);
1284:                liabilityDescription = configurationService
1285:                        .getPropertyString(KFSKeyConstants.MSG_GENERATED_LIABILITY);
1286:                costShareDescription = configurationService
1287:                        .getPropertyString(KFSKeyConstants.MSG_GENERATED_COST_SHARE);
1288:                transferDescription = configurationService
1289:                        .getPropertyString(KFSKeyConstants.MSG_GENERATED_TRANSFER);
1290:            }
1291:
1292:            /**
1293:             * Generate the flag for the end of specific descriptions. This will be used in the demerger step
1294:             */
1295:            private void setOffsetString() {
1296:
1297:                NumberFormat nf = NumberFormat.getInstance();
1298:                nf.setMaximumFractionDigits(0);
1299:                nf.setMaximumIntegerDigits(2);
1300:                nf.setMinimumFractionDigits(0);
1301:                nf.setMinimumIntegerDigits(2);
1302:
1303:                offsetString = COST_SHARE_TRANSFER_ENTRY_IND
1304:                        + nf.format(runCal.get(Calendar.MONTH) + 1)
1305:                        + nf.format(runCal.get(Calendar.DAY_OF_MONTH));
1306:            }
1307:
1308:            /**
1309:             * Generate the offset message with the flag at the end
1310:             * 
1311:             * @return a generated offset message
1312:             */
1313:            private String getOffsetMessage() {
1314:                String msg = offsetDescription
1315:                        + GLConstants
1316:                                .getSpaceTransactionLedgetEntryDescription();
1317:
1318:                return msg.substring(0, OFFSET_MESSAGE_MAXLENGTH)
1319:                        + offsetString;
1320:            }
1321:
1322:            /**
1323:             * Generates capitalization entries if necessary
1324:             * 
1325:             * @param scrubbedEntry the entry to generate capitalization entries (possibly) for
1326:             * @return null if no error, message if error
1327:             */
1328:            private String processCapitalization(OriginEntry scrubbedEntry) {
1329:                // Lines 4694 - 4798 of the Pro Cobol listing on Confluence
1330:                if (!parameterService
1331:                        .getIndicatorParameter(
1332:                                ScrubberStep.class,
1333:                                GLConstants.GlScrubberGroupParameters.CAPITALIZATION_IND)) {
1334:                    return null;
1335:                }
1336:
1337:                OriginEntryFull capitalizationEntry = OriginEntryFull
1338:                        .copyFromOriginEntryable(scrubbedEntry);
1339:
1340:                Options scrubbedEntryOption = referenceLookup.get().getOption(
1341:                        scrubbedEntry);
1342:                ObjectCode scrubbedEntryObjectCode = referenceLookup.get()
1343:                        .getFinancialObject(scrubbedEntry);
1344:                Chart scrubbedEntryChart = referenceLookup.get().getChart(
1345:                        scrubbedEntry);
1346:                Account scrubbedEntryAccount = referenceLookup.get()
1347:                        .getAccount(scrubbedEntry);
1348:
1349:                ParameterEvaluator documentTypeCodes = parameterService
1350:                        .getParameterEvaluator(
1351:                                ScrubberStep.class,
1352:                                GLConstants.GlScrubberGroupRules.CAPITALIZATION_DOC_TYPE_CODES,
1353:                                scrubbedEntry.getFinancialDocumentTypeCode());
1354:                ParameterEvaluator fiscalPeriodCodes = parameterService
1355:                        .getParameterEvaluator(
1356:                                ScrubberStep.class,
1357:                                GLConstants.GlScrubberGroupRules.CAPITALIZATION_FISCAL_PERIOD_CODES,
1358:                                scrubbedEntry.getUniversityFiscalPeriodCode());
1359:                ParameterEvaluator objectSubTypeCodes = parameterService
1360:                        .getParameterEvaluator(
1361:                                ScrubberStep.class,
1362:                                GLConstants.GlScrubberGroupRules.CAPITALIZATION_OBJ_SUB_TYPE_CODES,
1363:                                scrubbedEntryObjectCode
1364:                                        .getFinancialObjectSubTypeCode());
1365:                ParameterEvaluator subFundGroupCodes = parameterService
1366:                        .getParameterEvaluator(
1367:                                ScrubberStep.class,
1368:                                GLConstants.GlScrubberGroupRules.CAPITALIZATION_SUB_FUND_GROUP_CODES,
1369:                                scrubbedEntryAccount.getSubFundGroupCode());
1370:                ParameterEvaluator chartCodes = parameterService
1371:                        .getParameterEvaluator(
1372:                                ScrubberStep.class,
1373:                                GLConstants.GlScrubberGroupRules.CAPITALIZATION_CHART_CODES,
1374:                                scrubbedEntry.getChartOfAccountsCode());
1375:
1376:                if (scrubbedEntry.getFinancialBalanceTypeCode().equals(
1377:                        scrubbedEntryOption.getActualFinancialBalanceTypeCd())
1378:                        && scrubbedEntry.getUniversityFiscalYear().intValue() > 1995
1379:                        && documentTypeCodes.evaluationSucceeds()
1380:                        && fiscalPeriodCodes.evaluationSucceeds()
1381:                        && objectSubTypeCodes.evaluationSucceeds()
1382:                        && subFundGroupCodes.evaluationSucceeds()
1383:                        && chartCodes.evaluationSucceeds()) {
1384:
1385:                    String objectSubTypeCode = scrubbedEntryObjectCode
1386:                            .getFinancialObjectSubTypeCode();
1387:
1388:                    String capitalizationObjectCode = parameterService
1389:                            .getParameterValue(
1390:                                    ScrubberStep.class,
1391:                                    GLConstants.GlScrubberGroupParameters.CAPITALIZATION_SUBTYPE_OBJECT,
1392:                                    objectSubTypeCode);
1393:                    if (capitalizationObjectCode != null) {
1394:                        capitalizationEntry
1395:                                .setFinancialObjectCode(capitalizationObjectCode);
1396:                        persistenceService.retrieveReferenceObject(
1397:                                capitalizationEntry,
1398:                                KFSPropertyConstants.FINANCIAL_OBJECT);
1399:                    }
1400:
1401:                    capitalizationEntry
1402:                            .setFinancialObjectTypeCode(scrubbedEntryOption
1403:                                    .getFinancialObjectTypeAssetsCd());
1404:                    persistenceService.retrieveReferenceObject(
1405:                            capitalizationEntry,
1406:                            KFSPropertyConstants.OBJECT_TYPE);
1407:                    capitalizationEntry
1408:                            .setTransactionLedgerEntryDescription(capitalizationDescription);
1409:
1410:                    plantFundAccountLookup(scrubbedEntry, capitalizationEntry);
1411:
1412:                    capitalizationEntry
1413:                            .setUniversityFiscalPeriodCode(scrubbedEntry
1414:                                    .getUniversityFiscalPeriodCode());
1415:
1416:                    createOutputEntry(capitalizationEntry, validGroup);
1417:                    scrubberReport.incrementCapitalizationEntryGenerated();
1418:
1419:                    // Clear out the id & the ojb version number to make sure we do an insert on the next one
1420:                    capitalizationEntry.setVersionNumber(null);
1421:                    capitalizationEntry.setEntryId(null);
1422:
1423:                    capitalizationEntry
1424:                            .setFinancialObjectCode(scrubbedEntryChart
1425:                                    .getFundBalanceObjectCode());
1426:                    if (ObjectUtils.isNotNull(scrubbedEntryChart
1427:                            .getFundBalanceObject())) {
1428:                        capitalizationEntry
1429:                                .setFinancialObjectTypeCode(scrubbedEntryChart
1430:                                        .getFundBalanceObject()
1431:                                        .getFinancialObjectTypeCode());
1432:                    } else {
1433:                        capitalizationEntry
1434:                                .setFinancialObjectTypeCode(scrubbedEntryOption
1435:                                        .getFinObjectTypeFundBalanceCd());
1436:                    }
1437:
1438:                    if (scrubbedEntry.isDebit()) {
1439:                        capitalizationEntry
1440:                                .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
1441:                    } else {
1442:                        capitalizationEntry
1443:                                .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
1444:                    }
1445:
1446:                    try {
1447:                        flexibleOffsetAccountService
1448:                                .updateOffset(capitalizationEntry);
1449:                    } catch (InvalidFlexibleOffsetException e) {
1450:                        LOG
1451:                                .debug("processCapitalization() Capitalization Flexible Offset Error: "
1452:                                        + e.getMessage());
1453:                        return e.getMessage();
1454:                    }
1455:
1456:                    createOutputEntry(capitalizationEntry, validGroup);
1457:                    scrubberReport.incrementCapitalizationEntryGenerated();
1458:                }
1459:                return null;
1460:            }
1461:
1462:            /**
1463:             * Generates the plant indebtedness entries
1464:             * 
1465:             * @param scrubbedEntry the entry to generated plant indebtedness entries for if necessary
1466:             * @return null if no error, message if error
1467:             */
1468:            private String processPlantIndebtedness(OriginEntry scrubbedEntry) {
1469:                // Lines 4855 - 4979 of the Pro Cobol listing on Confluence 
1470:                if (!parameterService
1471:                        .getIndicatorParameter(
1472:                                ScrubberStep.class,
1473:                                GLConstants.GlScrubberGroupParameters.PLANT_INDEBTEDNESS_IND)) {
1474:                    return null;
1475:                }
1476:
1477:                OriginEntryFull plantIndebtednessEntry = OriginEntryFull
1478:                        .copyFromOriginEntryable(scrubbedEntry);
1479:
1480:                Options scrubbedEntryOption = referenceLookup.get().getOption(
1481:                        scrubbedEntry);
1482:                ObjectCode scrubbedEntryObjectCode = referenceLookup.get()
1483:                        .getFinancialObject(scrubbedEntry);
1484:                Account scrubbedEntryAccount = referenceLookup.get()
1485:                        .getAccount(scrubbedEntry);
1486:                Chart scrubbedEntryChart = referenceLookup.get().getChart(
1487:                        scrubbedEntry);
1488:
1489:                ParameterEvaluator objectSubTypeCodes = parameterService
1490:                        .getParameterEvaluator(
1491:                                ScrubberStep.class,
1492:                                GLConstants.GlScrubberGroupRules.PLANT_INDEBTEDNESS_OBJ_SUB_TYPE_CODES,
1493:                                scrubbedEntryObjectCode
1494:                                        .getFinancialObjectSubTypeCode());
1495:                ParameterEvaluator subFundGroupCodes = parameterService
1496:                        .getParameterEvaluator(
1497:                                ScrubberStep.class,
1498:                                GLConstants.GlScrubberGroupRules.PLANT_INDEBTEDNESS_SUB_FUND_GROUP_CODES,
1499:                                scrubbedEntryAccount.getSubFundGroupCode());
1500:
1501:                if (scrubbedEntry.getFinancialBalanceTypeCode().equals(
1502:                        scrubbedEntryOption.getActualFinancialBalanceTypeCd())
1503:                        && subFundGroupCodes.evaluationSucceeds()
1504:                        && objectSubTypeCodes.evaluationSucceeds()) {
1505:
1506:                    plantIndebtednessEntry
1507:                            .setTransactionLedgerEntryDescription(KFSConstants.PLANT_INDEBTEDNESS_ENTRY_DESCRIPTION);
1508:
1509:                    if (scrubbedEntry.isDebit()) {
1510:                        plantIndebtednessEntry
1511:                                .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
1512:                    } else {
1513:                        plantIndebtednessEntry
1514:                                .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
1515:                    }
1516:
1517:                    plantIndebtednessEntry
1518:                            .setTransactionScrubberOffsetGenerationIndicator(true);
1519:                    createOutputEntry(plantIndebtednessEntry, validGroup);
1520:                    scrubberReport.incrementPlantIndebtednessEntryGenerated();
1521:
1522:                    // Clear out the id & the ojb version number to make sure we do an insert on the next one
1523:                    plantIndebtednessEntry.setVersionNumber(null);
1524:                    plantIndebtednessEntry.setEntryId(null);
1525:
1526:                    plantIndebtednessEntry
1527:                            .setFinancialObjectCode(scrubbedEntryChart
1528:                                    .getFundBalanceObjectCode());
1529:                    plantIndebtednessEntry
1530:                            .setFinancialObjectTypeCode(scrubbedEntryOption
1531:                                    .getFinObjectTypeFundBalanceCd());
1532:                    plantIndebtednessEntry
1533:                            .setTransactionDebitCreditCode(scrubbedEntry
1534:                                    .getTransactionDebitCreditCode());
1535:
1536:                    plantIndebtednessEntry
1537:                            .setTransactionScrubberOffsetGenerationIndicator(true);
1538:                    plantIndebtednessEntry
1539:                            .setFinancialSubObjectCode(KFSConstants
1540:                                    .getDashFinancialSubObjectCode());
1541:
1542:                    try {
1543:                        flexibleOffsetAccountService
1544:                                .updateOffset(plantIndebtednessEntry);
1545:                    } catch (InvalidFlexibleOffsetException e) {
1546:                        LOG
1547:                                .error(
1548:                                        "processPlantIndebtedness() Flexible Offset Exception (1)",
1549:                                        e);
1550:                        LOG
1551:                                .debug("processPlantIndebtedness() Plant Indebtedness Flexible Offset Error: "
1552:                                        + e.getMessage());
1553:                        return e.getMessage();
1554:                    }
1555:
1556:                    createOutputEntry(plantIndebtednessEntry, validGroup);
1557:                    scrubberReport.incrementPlantIndebtednessEntryGenerated();
1558:
1559:                    // Clear out the id & the ojb version number to make sure we do an insert on the next one
1560:                    plantIndebtednessEntry.setVersionNumber(null);
1561:                    plantIndebtednessEntry.setEntryId(null);
1562:
1563:                    plantIndebtednessEntry.setFinancialObjectCode(scrubbedEntry
1564:                            .getFinancialObjectCode());
1565:                    plantIndebtednessEntry
1566:                            .setFinancialObjectTypeCode(scrubbedEntry
1567:                                    .getFinancialObjectTypeCode());
1568:                    plantIndebtednessEntry
1569:                            .setTransactionDebitCreditCode(scrubbedEntry
1570:                                    .getTransactionDebitCreditCode());
1571:
1572:                    plantIndebtednessEntry
1573:                            .setTransactionLedgerEntryDescription(scrubbedEntry
1574:                                    .getTransactionLedgerEntryDescription());
1575:
1576:                    plantIndebtednessEntry.setAccountNumber(scrubbedEntry
1577:                            .getAccountNumber());
1578:                    plantIndebtednessEntry.setSubAccountNumber(scrubbedEntry
1579:                            .getSubAccountNumber());
1580:
1581:                    if (scrubbedEntry.getChartOfAccountsCode().equals(
1582:                            scrubbedEntryAccount.getOrganization()
1583:                                    .getChartOfAccountsCode())
1584:                            && scrubbedEntryAccount.getOrganizationCode()
1585:                                    .equals(
1586:                                            scrubbedEntryAccount
1587:                                                    .getOrganizationCode())
1588:                            && scrubbedEntry.getAccountNumber().equals(
1589:                                    scrubbedEntryAccount.getAccountNumber())
1590:                            && scrubbedEntry.getChartOfAccountsCode().equals(
1591:                                    scrubbedEntryAccount
1592:                                            .getChartOfAccountsCode())) {
1593:                        plantIndebtednessEntry
1594:                                .setAccountNumber(scrubbedEntryAccount
1595:                                        .getOrganization()
1596:                                        .getCampusPlantAccountNumber());
1597:                        plantIndebtednessEntry
1598:                                .setChartOfAccountsCode(scrubbedEntryAccount
1599:                                        .getOrganization()
1600:                                        .getCampusPlantChartCode());
1601:                    }
1602:
1603:                    plantIndebtednessEntry.setSubAccountNumber(KFSConstants
1604:                            .getDashSubAccountNumber());
1605:                    plantIndebtednessEntry
1606:                            .setFinancialSubObjectCode(KFSConstants
1607:                                    .getDashFinancialSubObjectCode());
1608:
1609:                    StringBuffer litGenPlantXferFrom = new StringBuffer();
1610:                    litGenPlantXferFrom.append(transferDescription + " ");
1611:                    litGenPlantXferFrom.append(
1612:                            scrubbedEntry.getChartOfAccountsCode()).append(" ");
1613:                    litGenPlantXferFrom
1614:                            .append(scrubbedEntry.getAccountNumber());
1615:                    plantIndebtednessEntry
1616:                            .setTransactionLedgerEntryDescription(litGenPlantXferFrom
1617:                                    .toString());
1618:
1619:                    createOutputEntry(plantIndebtednessEntry, validGroup);
1620:                    scrubberReport.incrementPlantIndebtednessEntryGenerated();
1621:
1622:                    // Clear out the id & the ojb version number to make sure we do an insert on the next one
1623:                    plantIndebtednessEntry.setVersionNumber(null);
1624:                    plantIndebtednessEntry.setEntryId(null);
1625:
1626:                    plantIndebtednessEntry
1627:                            .setFinancialObjectCode(scrubbedEntryChart
1628:                                    .getFundBalanceObjectCode());
1629:                    plantIndebtednessEntry
1630:                            .setFinancialObjectTypeCode(scrubbedEntryOption
1631:                                    .getFinObjectTypeFundBalanceCd());
1632:                    plantIndebtednessEntry
1633:                            .setFinancialSubObjectCode(KFSConstants
1634:                                    .getDashFinancialSubObjectCode());
1635:
1636:                    if (scrubbedEntry.isDebit()) {
1637:                        plantIndebtednessEntry
1638:                                .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
1639:                    } else {
1640:                        plantIndebtednessEntry
1641:                                .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
1642:                    }
1643:
1644:                    try {
1645:                        flexibleOffsetAccountService
1646:                                .updateOffset(plantIndebtednessEntry);
1647:                    } catch (InvalidFlexibleOffsetException e) {
1648:                        LOG
1649:                                .error(
1650:                                        "processPlantIndebtedness() Flexible Offset Exception (2)",
1651:                                        e);
1652:                        LOG
1653:                                .debug("processPlantIndebtedness() Plant Indebtedness Flexible Offset Error: "
1654:                                        + e.getMessage());
1655:                        return e.getMessage();
1656:                    }
1657:
1658:                    createOutputEntry(plantIndebtednessEntry, validGroup);
1659:                    scrubberReport.incrementPlantIndebtednessEntryGenerated();
1660:                }
1661:
1662:                return null;
1663:            }
1664:
1665:            /**
1666:             * Generate the liability entries for the entry if necessary
1667:             * 
1668:             * @param scrubbedEntry the entry to generate liability entries for if necessary
1669:             * @return null if no error, message if error
1670:             */
1671:            private String processLiabilities(OriginEntry scrubbedEntry) {
1672:                // Lines 4799 to 4839 of the Pro Cobol list of the scrubber on Confluence
1673:                if (!parameterService.getIndicatorParameter(ScrubberStep.class,
1674:                        GLConstants.GlScrubberGroupParameters.LIABILITY_IND)) {
1675:                    return null;
1676:                }
1677:
1678:                OriginEntryFull liabilityEntry = OriginEntryFull
1679:                        .copyFromOriginEntryable(scrubbedEntry);
1680:
1681:                Chart scrubbedEntryChart = referenceLookup.get().getChart(
1682:                        scrubbedEntry);
1683:                Options scrubbedEntryOption = referenceLookup.get().getOption(
1684:                        scrubbedEntry);
1685:                ObjectCode scrubbedEntryFinancialObject = referenceLookup.get()
1686:                        .getFinancialObject(scrubbedEntry);
1687:                Account scrubbedEntryAccount = referenceLookup.get()
1688:                        .getAccount(scrubbedEntry);
1689:
1690:                ParameterEvaluator chartCodes = parameterService
1691:                        .getParameterEvaluator(
1692:                                ScrubberStep.class,
1693:                                GLConstants.GlScrubberGroupRules.LIABILITY_CHART_CODES,
1694:                                scrubbedEntry.getChartOfAccountsCode());
1695:                ParameterEvaluator docTypeCodes = parameterService
1696:                        .getParameterEvaluator(
1697:                                ScrubberStep.class,
1698:                                GLConstants.GlScrubberGroupRules.LIABILITY_DOC_TYPE_CODES,
1699:                                scrubbedEntry.getFinancialDocumentTypeCode());
1700:                ParameterEvaluator fiscalPeriods = parameterService
1701:                        .getParameterEvaluator(
1702:                                ScrubberStep.class,
1703:                                GLConstants.GlScrubberGroupRules.LIABILITY_FISCAL_PERIOD_CODES,
1704:                                scrubbedEntry.getUniversityFiscalPeriodCode());
1705:                ParameterEvaluator objSubTypeCodes = parameterService
1706:                        .getParameterEvaluator(
1707:                                ScrubberStep.class,
1708:                                GLConstants.GlScrubberGroupRules.LIABILITY_OBJ_SUB_TYPE_CODES,
1709:                                scrubbedEntryFinancialObject
1710:                                        .getFinancialObjectSubTypeCode());
1711:                ParameterEvaluator subFundGroupCodes = parameterService
1712:                        .getParameterEvaluator(
1713:                                ScrubberStep.class,
1714:                                GLConstants.GlScrubberGroupRules.LIABILITY_SUB_FUND_GROUP_CODES,
1715:                                scrubbedEntryAccount.getSubFundGroupCode());
1716:
1717:                if (scrubbedEntry.getFinancialBalanceTypeCode().equals(
1718:                        scrubbedEntryOption.getActualFinancialBalanceTypeCd())
1719:                        && scrubbedEntry.getUniversityFiscalYear().intValue() > 1995
1720:                        && docTypeCodes.evaluationSucceeds()
1721:                        && fiscalPeriods.evaluationSucceeds()
1722:                        && objSubTypeCodes.evaluationSucceeds()
1723:                        && subFundGroupCodes.evaluationSucceeds()
1724:                        && chartCodes.evaluationSucceeds()) {
1725:
1726:                    liabilityEntry
1727:                            .setFinancialObjectCode(parameterService
1728:                                    .getParameterValue(
1729:                                            ScrubberStep.class,
1730:                                            GLConstants.GlScrubberGroupParameters.LIABILITY_OBJECT_CODE));
1731:                    liabilityEntry
1732:                            .setFinancialObjectTypeCode(scrubbedEntryOption
1733:                                    .getFinObjectTypeLiabilitiesCode());
1734:
1735:                    liabilityEntry.setTransactionDebitCreditCode(scrubbedEntry
1736:                            .getTransactionDebitCreditCode());
1737:                    liabilityEntry
1738:                            .setTransactionLedgerEntryDescription(liabilityDescription);
1739:                    plantFundAccountLookup(scrubbedEntry, liabilityEntry);
1740:
1741:                    createOutputEntry(liabilityEntry, validGroup);
1742:                    scrubberReport.incrementLiabilityEntryGenerated();
1743:
1744:                    // Clear out the id & the ojb version number to make sure we do an insert on the next one
1745:                    liabilityEntry.setVersionNumber(null);
1746:                    liabilityEntry.setEntryId(null);
1747:
1748:                    // ... and now generate the offset half of the liability entry
1749:                    liabilityEntry.setFinancialObjectCode(scrubbedEntryChart
1750:                            .getFundBalanceObjectCode());
1751:                    if (ObjectUtils.isNotNull(scrubbedEntryChart
1752:                            .getFundBalanceObject())) {
1753:                        liabilityEntry
1754:                                .setFinancialObjectTypeCode(scrubbedEntryChart
1755:                                        .getFundBalanceObject()
1756:                                        .getFinancialObjectTypeCode());
1757:                    } else {
1758:                        liabilityEntry
1759:                                .setFinancialObjectTypeCode(scrubbedEntryOption
1760:                                        .getFinObjectTypeFundBalanceCd());
1761:                    }
1762:
1763:                    if (liabilityEntry.isDebit()) {
1764:                        liabilityEntry
1765:                                .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
1766:                    } else {
1767:                        liabilityEntry
1768:                                .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
1769:                    }
1770:
1771:                    try {
1772:                        flexibleOffsetAccountService
1773:                                .updateOffset(liabilityEntry);
1774:                    } catch (InvalidFlexibleOffsetException e) {
1775:                        LOG
1776:                                .debug("processLiabilities() Liability Flexible Offset Error: "
1777:                                        + e.getMessage());
1778:                        return e.getMessage();
1779:                    }
1780:
1781:                    createOutputEntry(liabilityEntry, validGroup);
1782:                    scrubberReport.incrementLiabilityEntryGenerated();
1783:                }
1784:                return null;
1785:            }
1786:
1787:            /**
1788:             * Updates the entries with the proper chart and account for the plant fund
1789:             * 
1790:             * @param scrubbedEntry basis for plant fund entry
1791:             * @param liabilityEntry liability entry
1792:             */
1793:            private void plantFundAccountLookup(OriginEntry scrubbedEntry,
1794:                    OriginEntryFull liabilityEntry) {
1795:                // 4000-PLANT-FUND-ACCT to 4000-PLANT-FUND-ACCT-EXIT in cobol
1796:
1797:                liabilityEntry.setSubAccountNumber(KFSConstants
1798:                        .getDashSubAccountNumber());
1799:                persistenceService.retrieveReferenceObject(liabilityEntry,
1800:                        KFSPropertyConstants.ACCOUNT);
1801:
1802:                ObjectCode scrubbedEntryObjectCode = referenceLookup.get()
1803:                        .getFinancialObject(scrubbedEntry);
1804:                Account scrubbedEntryAccount = referenceLookup.get()
1805:                        .getAccount(scrubbedEntry);
1806:
1807:                if (liabilityEntry.getChartOfAccountsCode().equals(
1808:                        liabilityEntry.getAccount().getOrganization()
1809:                                .getChartOfAccountsCode())
1810:                        && scrubbedEntryAccount.getOrganizationCode().equals(
1811:                                liabilityEntry.getAccount().getOrganization()
1812:                                        .getOrganizationCode())
1813:                        && liabilityEntry.getAccountNumber().equals(
1814:                                liabilityEntry.getAccount().getAccountNumber())
1815:                        && liabilityEntry.getChartOfAccountsCode().equals(
1816:                                liabilityEntry.getAccount()
1817:                                        .getChartOfAccountsCode())) {
1818:                    persistenceService.retrieveReferenceObject(liabilityEntry,
1819:                            KFSPropertyConstants.FINANCIAL_OBJECT);
1820:                    persistenceService.retrieveReferenceObject(liabilityEntry
1821:                            .getAccount(), KFSPropertyConstants.ORGANIZATION);
1822:
1823:                    String objectSubTypeCode = scrubbedEntryObjectCode
1824:                            .getFinancialObjectSubTypeCode();
1825:                    ParameterEvaluator campusObjSubTypeCodes = parameterService
1826:                            .getParameterEvaluator(
1827:                                    ScrubberStep.class,
1828:                                    GLConstants.GlScrubberGroupRules.PLANT_FUND_CAMPUS_OBJECT_SUB_TYPE_CODES,
1829:                                    objectSubTypeCode);
1830:                    ParameterEvaluator orgObjSubTypeCodes = parameterService
1831:                            .getParameterEvaluator(
1832:                                    ScrubberStep.class,
1833:                                    GLConstants.GlScrubberGroupRules.PLANT_FUND_ORG_OBJECT_SUB_TYPE_CODES,
1834:                                    objectSubTypeCode);
1835:
1836:                    if (campusObjSubTypeCodes.evaluationSucceeds()) {
1837:                        liabilityEntry.setAccountNumber(scrubbedEntryAccount
1838:                                .getOrganization()
1839:                                .getCampusPlantAccountNumber());
1840:                        liabilityEntry
1841:                                .setChartOfAccountsCode(scrubbedEntryAccount
1842:                                        .getOrganization()
1843:                                        .getCampusPlantChartCode());
1844:
1845:                        persistenceService.retrieveReferenceObject(
1846:                                liabilityEntry, KFSPropertyConstants.ACCOUNT);
1847:                        persistenceService.retrieveReferenceObject(
1848:                                liabilityEntry, KFSPropertyConstants.CHART);
1849:                    } else if (orgObjSubTypeCodes.evaluationSucceeds()) {
1850:                        liabilityEntry.setAccountNumber(scrubbedEntryAccount
1851:                                .getOrganization()
1852:                                .getOrganizationPlantAccountNumber());
1853:                        liabilityEntry
1854:                                .setChartOfAccountsCode(scrubbedEntryAccount
1855:                                        .getOrganization()
1856:                                        .getOrganizationPlantChartCode());
1857:
1858:                        persistenceService.retrieveReferenceObject(
1859:                                liabilityEntry, KFSPropertyConstants.ACCOUNT);
1860:                        persistenceService.retrieveReferenceObject(
1861:                                liabilityEntry, KFSPropertyConstants.CHART);
1862:                    }
1863:                }
1864:            }
1865:
1866:            /**
1867:             * The purpose of this method is to generate a "Cost Share Encumbrance"
1868:             * transaction for the current transaction and its offset. The cost share chart and account for current transaction are obtained
1869:             * from the CA_A21_SUB_ACCT_T table. This method calls the method SET-OBJECT-2004 to get the Cost Share Object Code. It then
1870:             * writes out the cost share transaction. Next it read the GL_OFFSET_DEFN_T table for the offset object code that corresponds to
1871:             * the cost share object code. In addition to the object code it needs to get subobject code. It then reads the CA_OBJECT_CODE_T
1872:             * table to make sure the offset object code found in the GL_OFFSET_DEFN_T is valid and to get the object type code associated
1873:             * with this object code. It writes out the offset transaction and returns.
1874:             * 
1875:             * @param scrubbedEntry the entry to perhaps create a cost share encumbrance for 
1876:             * @return a message if there was an error encountered generating the entries, or (hopefully) null if no errors were encountered
1877:             */
1878:            private TransactionError generateCostShareEncumbranceEntries(
1879:                    OriginEntry scrubbedEntry) {
1880:                // 3200-COST-SHARE-ENC to 3200-CSE-EXIT in the COBOL
1881:                LOG.debug("generateCostShareEncumbranceEntries() started");
1882:
1883:                OriginEntryFull costShareEncumbranceEntry = OriginEntryFull
1884:                        .copyFromOriginEntryable(scrubbedEntry);
1885:
1886:                // First 28 characters of the description, padding to 28 if shorter)
1887:                StringBuffer buffer = new StringBuffer((scrubbedEntry
1888:                        .getTransactionLedgerEntryDescription() + GLConstants
1889:                        .getSpaceTransactionLedgetEntryDescription())
1890:                        .substring(0, COST_SHARE_ENCUMBRANCE_ENTRY_MAXLENGTH));
1891:
1892:                buffer.append("FR-");
1893:                buffer.append(costShareEncumbranceEntry
1894:                        .getChartOfAccountsCode());
1895:                buffer.append(costShareEncumbranceEntry.getAccountNumber());
1896:
1897:                costShareEncumbranceEntry
1898:                        .setTransactionLedgerEntryDescription(buffer.toString());
1899:
1900:                A21SubAccount scrubbedEntryA21SubAccount = referenceLookup
1901:                        .get().getA21SubAccount(scrubbedEntry);
1902:                Options scrubbedEntryOption = referenceLookup.get().getOption(
1903:                        scrubbedEntry);
1904:
1905:                costShareEncumbranceEntry
1906:                        .setChartOfAccountsCode(scrubbedEntryA21SubAccount
1907:                                .getCostShareChartOfAccountCode());
1908:                costShareEncumbranceEntry
1909:                        .setAccountNumber(scrubbedEntryA21SubAccount
1910:                                .getCostShareSourceAccountNumber());
1911:                costShareEncumbranceEntry
1912:                        .setSubAccountNumber(scrubbedEntryA21SubAccount
1913:                                .getCostShareSourceSubAccountNumber());
1914:
1915:                if (!StringUtils.hasText(costShareEncumbranceEntry
1916:                        .getSubAccountNumber())) {
1917:                    costShareEncumbranceEntry.setSubAccountNumber(KFSConstants
1918:                            .getDashSubAccountNumber());
1919:                }
1920:
1921:                costShareEncumbranceEntry
1922:                        .setFinancialBalanceTypeCode(scrubbedEntryOption
1923:                                .getCostShareEncumbranceBalanceTypeCd());
1924:                setCostShareObjectCode(costShareEncumbranceEntry, scrubbedEntry);
1925:                costShareEncumbranceEntry
1926:                        .setFinancialSubObjectCode(KFSConstants
1927:                                .getDashFinancialSubObjectCode());
1928:                costShareEncumbranceEntry
1929:                        .setTransactionLedgerEntrySequenceNumber(new Integer(0));
1930:
1931:                if (!StringUtils.hasText(scrubbedEntry
1932:                        .getTransactionDebitCreditCode())) {
1933:                    if (scrubbedEntry.getTransactionLedgerEntryAmount()
1934:                            .isPositive()) {
1935:                        costShareEncumbranceEntry
1936:                                .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
1937:                    } else {
1938:                        costShareEncumbranceEntry
1939:                                .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
1940:                        costShareEncumbranceEntry
1941:                                .setTransactionLedgerEntryAmount(scrubbedEntry
1942:                                        .getTransactionLedgerEntryAmount()
1943:                                        .negated());
1944:                    }
1945:                }
1946:
1947:                costShareEncumbranceEntry.setTransactionDate(runDate);
1948:
1949:                costShareEncumbranceEntry
1950:                        .setTransactionScrubberOffsetGenerationIndicator(true);
1951:                createOutputEntry(costShareEncumbranceEntry, validGroup);
1952:                scrubberReport.incrementCostShareEncumbranceGenerated();
1953:
1954:                OriginEntryFull costShareEncumbranceOffsetEntry = new OriginEntryFull(
1955:                        costShareEncumbranceEntry);
1956:
1957:                costShareEncumbranceOffsetEntry
1958:                        .setTransactionLedgerEntryDescription(offsetDescription);
1959:
1960:                OffsetDefinition offset = offsetDefinitionService
1961:                        .getByPrimaryId(costShareEncumbranceEntry
1962:                                .getUniversityFiscalYear(),
1963:                                costShareEncumbranceEntry
1964:                                        .getChartOfAccountsCode(),
1965:                                costShareEncumbranceEntry
1966:                                        .getFinancialDocumentTypeCode(),
1967:                                costShareEncumbranceEntry
1968:                                        .getFinancialBalanceTypeCode());
1969:
1970:                if (offset != null) {
1971:                    if (offset.getFinancialObject() == null) {
1972:                        StringBuffer offsetKey = new StringBuffer();
1973:                        offsetKey.append(offset.getUniversityFiscalYear());
1974:                        offsetKey.append("-");
1975:                        offsetKey.append(offset.getChartOfAccountsCode());
1976:                        offsetKey.append("-");
1977:                        offsetKey.append(offset.getFinancialObjectCode());
1978:
1979:                        LOG
1980:                                .debug("generateCostShareEncumbranceEntries() object code not found");
1981:                        return new TransactionError(
1982:                                costShareEncumbranceEntry,
1983:                                new Message(
1984:                                        configurationService
1985:                                                .getPropertyString(KFSKeyConstants.ERROR_NO_OBJECT_FOR_OBJECT_ON_OFSD)
1986:                                                + "("
1987:                                                + offsetKey.toString()
1988:                                                + ")", Message.TYPE_FATAL));
1989:                    }
1990:                    costShareEncumbranceOffsetEntry
1991:                            .setFinancialObjectCode(offset
1992:                                    .getFinancialObjectCode());
1993:                    costShareEncumbranceOffsetEntry.setFinancialObject(offset
1994:                            .getFinancialObject());
1995:                    costShareEncumbranceOffsetEntry
1996:                            .setFinancialSubObjectCode(KFSConstants
1997:                                    .getDashFinancialSubObjectCode());
1998:                } else {
1999:                    StringBuffer offsetKey = new StringBuffer(
2000:                            "Cost share encumbrance ");
2001:                    offsetKey.append(costShareEncumbranceEntry
2002:                            .getUniversityFiscalYear());
2003:                    offsetKey.append("-");
2004:                    offsetKey.append(costShareEncumbranceEntry
2005:                            .getChartOfAccountsCode());
2006:                    offsetKey.append("-");
2007:                    offsetKey.append(costShareEncumbranceEntry
2008:                            .getFinancialDocumentTypeCode());
2009:                    offsetKey.append("-");
2010:                    offsetKey.append(costShareEncumbranceEntry
2011:                            .getFinancialBalanceTypeCode());
2012:
2013:                    LOG
2014:                            .debug("generateCostShareEncumbranceEntries() offset not found");
2015:                    return new TransactionError(
2016:                            costShareEncumbranceEntry,
2017:                            new Message(
2018:                                    configurationService
2019:                                            .getPropertyString(KFSKeyConstants.ERROR_OFFSET_DEFINITION_NOT_FOUND)
2020:                                            + "(" + offsetKey.toString() + ")",
2021:                                    Message.TYPE_FATAL));
2022:                }
2023:
2024:                costShareEncumbranceOffsetEntry
2025:                        .setFinancialObjectTypeCode(offset.getFinancialObject()
2026:                                .getFinancialObjectTypeCode());
2027:
2028:                if (costShareEncumbranceEntry.isCredit()) {
2029:                    costShareEncumbranceOffsetEntry
2030:                            .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
2031:                } else {
2032:                    costShareEncumbranceOffsetEntry
2033:                            .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
2034:                }
2035:
2036:                costShareEncumbranceOffsetEntry.setTransactionDate(runDate);
2037:                costShareEncumbranceOffsetEntry
2038:                        .setOrganizationDocumentNumber(null);
2039:                costShareEncumbranceOffsetEntry.setProjectCode(KFSConstants
2040:                        .getDashProjectCode());
2041:                costShareEncumbranceOffsetEntry
2042:                        .setOrganizationReferenceId(null);
2043:                costShareEncumbranceOffsetEntry
2044:                        .setReferenceFinancialDocumentTypeCode(null);
2045:                costShareEncumbranceOffsetEntry
2046:                        .setReferenceFinancialSystemOriginationCode(null);
2047:                costShareEncumbranceOffsetEntry
2048:                        .setReferenceFinancialDocumentNumber(null);
2049:                costShareEncumbranceOffsetEntry.setReversalDate(null);
2050:                costShareEncumbranceOffsetEntry
2051:                        .setTransactionEncumbranceUpdateCode(null);
2052:
2053:                costShareEncumbranceOffsetEntry
2054:                        .setTransactionScrubberOffsetGenerationIndicator(true);
2055:
2056:                try {
2057:                    flexibleOffsetAccountService
2058:                            .updateOffset(costShareEncumbranceOffsetEntry);
2059:                } catch (InvalidFlexibleOffsetException e) {
2060:                    Message m = new Message(e.getMessage(), Message.TYPE_FATAL);
2061:                    LOG
2062:                            .debug("generateCostShareEncumbranceEntries() Cost Share Encumbrance Flexible Offset Error: "
2063:                                    + e.getMessage());
2064:                    return new TransactionError(
2065:                            costShareEncumbranceOffsetEntry, m);
2066:                }
2067:
2068:                createOutputEntry(costShareEncumbranceOffsetEntry, validGroup);
2069:                scrubberReport.incrementCostShareEncumbranceGenerated();
2070:
2071:                LOG
2072:                        .debug("generateCostShareEncumbranceEntries() returned successfully");
2073:                return null;
2074:            }
2075:
2076:            /**
2077:             * Sets the proper cost share object code in an entry and its offset
2078:             * 
2079:             * @param costShareEntry GL Entry for cost share
2080:             * @param originEntry Scrubbed GL Entry that this is based on
2081:             */
2082:            private void setCostShareObjectCode(OriginEntryFull costShareEntry,
2083:                    OriginEntry originEntry) {
2084:                // This code is SET-OBJECT-2004 to 2520-INIT-SCRB-AREA in the Cobol
2085:                ObjectCode originEntryFinancialObject = referenceLookup.get()
2086:                        .getFinancialObject(originEntry);
2087:
2088:                if (originEntryFinancialObject == null) {
2089:                    addTransactionError(
2090:                            configurationService
2091:                                    .getPropertyString(KFSKeyConstants.ERROR_OBJECT_CODE_NOT_FOUND),
2092:                            originEntry.getFinancialObjectCode(),
2093:                            Message.TYPE_FATAL);
2094:                }
2095:
2096:                String originEntryObjectLevelCode = (originEntryFinancialObject == null) ? ""
2097:                        : originEntryFinancialObject
2098:                                .getFinancialObjectLevelCode();
2099:
2100:                String financialOriginEntryObjectCode = originEntry
2101:                        .getFinancialObjectCode();
2102:                String originEntryObjectCode = scrubberProcessObjectCodeOverride
2103:                        .getOriginEntryObjectCode(originEntryObjectLevelCode,
2104:                                financialOriginEntryObjectCode);
2105:
2106:                // General rules
2107:                if (originEntryObjectCode
2108:                        .equals(financialOriginEntryObjectCode)) {
2109:                    String param = parameterService
2110:                            .getParameterValue(
2111:                                    ScrubberStep.class,
2112:                                    GLConstants.GlScrubberGroupParameters.COST_SHARE_OBJECT_CODE_BY_LEVEL_PARM_NM,
2113:                                    originEntryObjectLevelCode);
2114:                    if (param == null) {
2115:                        param = parameterService
2116:                                .getParameterValue(
2117:                                        ScrubberStep.class,
2118:                                        GLConstants.GlScrubberGroupParameters.COST_SHARE_OBJECT_CODE_BY_LEVEL_PARM_NM,
2119:                                        "DEFAULT");
2120:                        if (param == null) {
2121:                            throw new RuntimeException(
2122:                                    "Unable to determine cost sharing object code from object level.  Default entry missing.");
2123:                        }
2124:                    }
2125:                    originEntryObjectCode = param;
2126:                }
2127:
2128:                // Lookup the new object code
2129:                ObjectCode objectCode = objectCodeService.getByPrimaryId(
2130:                        costShareEntry.getUniversityFiscalYear(),
2131:                        costShareEntry.getChartOfAccountsCode(),
2132:                        originEntryObjectCode);
2133:                if (objectCode != null) {
2134:                    costShareEntry.setFinancialObjectTypeCode(objectCode
2135:                            .getFinancialObjectTypeCode());
2136:                    costShareEntry
2137:                            .setFinancialObjectCode(originEntryObjectCode);
2138:                } else {
2139:                    addTransactionError(
2140:                            configurationService
2141:                                    .getPropertyString(KFSKeyConstants.ERROR_COST_SHARE_OBJECT_NOT_FOUND),
2142:                            costShareEntry.getFinancialObjectCode(),
2143:                            Message.TYPE_FATAL);
2144:                }
2145:            }
2146:
2147:            /**
2148:             * The purpose of this method is to build the actual offset transaction. It does this by performing the following steps: 1.
2149:             * Getting the offset object code and offset subobject code from the GL Offset Definition Table. 2. For the offset object code
2150:             * it needs to get the associated object type, object subtype, and object active code. 
2151:             * 
2152:             * @param scrubbedEntry entry to determine if an offset is needed for
2153:             * @return true if an offset would be needed for this entry, false otherwise
2154:             */
2155:            private boolean generateOffset(OriginEntry scrubbedEntry) {
2156:                // This code is 3000-OFFSET to SET-OBJECT-2004 in the Cobol
2157:                LOG.debug("generateOffset() started");
2158:
2159:                // There was no previous unit of work so we need no offset
2160:                if (scrubbedEntry == null) {
2161:                    return true;
2162:                }
2163:
2164:                // If the offset amount is zero, don't bother to lookup the offset definition ...
2165:                if (unitOfWork.offsetAmount.isZero()) {
2166:                    return true;
2167:                }
2168:
2169:                ParameterEvaluator docTypeRule = parameterService
2170:                        .getParameterEvaluator(
2171:                                ScrubberStep.class,
2172:                                GLConstants.GlScrubberGroupRules.OFFSET_DOC_TYPE_CODES,
2173:                                scrubbedEntry.getFinancialDocumentTypeCode());
2174:                if (!docTypeRule.evaluationSucceeds()) {
2175:                    return true;
2176:                }
2177:
2178:                // do nothing if flexible offset is enabled and scrubber offset indicator of the document
2179:                // type code is turned off in the document type table
2180:                String documentTypeCode = scrubbedEntry
2181:                        .getFinancialDocumentTypeCode();
2182:                DocumentType documentType = documentTypeService
2183:                        .getDocumentTypeByCode(documentTypeCode);
2184:                if ((!documentType
2185:                        .isTransactionScrubberOffsetGenerationIndicator())
2186:                        && flexibleOffsetAccountService.getEnabled()) {
2187:                    return true;
2188:                }
2189:
2190:                // Create an offset
2191:                OriginEntryFull offsetEntry = OriginEntryFull
2192:                        .copyFromOriginEntryable(scrubbedEntry);
2193:                offsetEntry
2194:                        .setTransactionLedgerEntryDescription(offsetDescription);
2195:
2196:                OffsetDefinition offsetDefinition = offsetDefinitionService
2197:                        .getByPrimaryId(
2198:                                scrubbedEntry.getUniversityFiscalYear(),
2199:                                scrubbedEntry.getChartOfAccountsCode(),
2200:                                scrubbedEntry.getFinancialDocumentTypeCode(),
2201:                                scrubbedEntry.getFinancialBalanceTypeCode());
2202:                if (offsetDefinition != null) {
2203:                    if (offsetDefinition.getFinancialObject() == null) {
2204:                        StringBuffer offsetKey = new StringBuffer(
2205:                                offsetDefinition.getUniversityFiscalYear());
2206:                        offsetKey.append("-");
2207:                        offsetKey.append(offsetDefinition
2208:                                .getChartOfAccountsCode());
2209:                        offsetKey.append("-");
2210:                        offsetKey.append(offsetDefinition
2211:                                .getFinancialObjectCode());
2212:
2213:                        putTransactionError(
2214:                                offsetEntry,
2215:                                configurationService
2216:                                        .getPropertyString(KFSKeyConstants.ERROR_OFFSET_DEFINITION_OBJECT_CODE_NOT_FOUND),
2217:                                offsetKey.toString(), Message.TYPE_FATAL);
2218:
2219:                        createOutputEntry(offsetEntry, errorGroup);
2220:                        scrubberReport.incrementErrorRecordWritten();
2221:                        return false;
2222:                    }
2223:
2224:                    offsetEntry.setFinancialObject(offsetDefinition
2225:                            .getFinancialObject());
2226:                    offsetEntry.setFinancialObjectCode(offsetDefinition
2227:                            .getFinancialObjectCode());
2228:
2229:                    offsetEntry.setFinancialSubObject(null);
2230:                    offsetEntry.setFinancialSubObjectCode(KFSConstants
2231:                            .getDashFinancialSubObjectCode());
2232:                } else {
2233:                    StringBuffer sb = new StringBuffer("Unit of work offset ");
2234:                    sb.append(scrubbedEntry.getUniversityFiscalYear());
2235:                    sb.append("-");
2236:                    sb.append(scrubbedEntry.getChartOfAccountsCode());
2237:                    sb.append("-");
2238:                    sb.append(scrubbedEntry.getFinancialDocumentTypeCode());
2239:                    sb.append("-");
2240:                    sb.append(scrubbedEntry.getFinancialBalanceTypeCode());
2241:
2242:                    putTransactionError(
2243:                            offsetEntry,
2244:                            configurationService
2245:                                    .getPropertyString(KFSKeyConstants.ERROR_OFFSET_DEFINITION_NOT_FOUND),
2246:                            sb.toString(), Message.TYPE_FATAL);
2247:
2248:                    createOutputEntry(offsetEntry, errorGroup);
2249:                    scrubberReport.incrementErrorRecordWritten();
2250:                    return false;
2251:                }
2252:
2253:                offsetEntry.setFinancialObjectTypeCode(offsetEntry
2254:                        .getFinancialObject().getFinancialObjectTypeCode());
2255:                offsetEntry
2256:                        .setTransactionLedgerEntryAmount(unitOfWork.offsetAmount);
2257:
2258:                if (unitOfWork.offsetAmount.isPositive()) {
2259:                    offsetEntry
2260:                            .setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE);
2261:                } else {
2262:                    offsetEntry
2263:                            .setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE);
2264:                    offsetEntry
2265:                            .setTransactionLedgerEntryAmount(unitOfWork.offsetAmount
2266:                                    .negated());
2267:                }
2268:
2269:                offsetEntry.setOrganizationDocumentNumber(null);
2270:                offsetEntry.setOrganizationReferenceId(null);
2271:                offsetEntry.setReferenceFinancialDocumentTypeCode(null);
2272:                offsetEntry.setReferenceDocumentType(null);
2273:                offsetEntry.setReferenceFinancialSystemOriginationCode(null);
2274:                offsetEntry.setReferenceFinancialDocumentNumber(null);
2275:                offsetEntry.setTransactionEncumbranceUpdateCode(null);
2276:                offsetEntry.setProjectCode(KFSConstants.getDashProjectCode());
2277:                offsetEntry.setTransactionDate(runDate);
2278:
2279:                try {
2280:                    flexibleOffsetAccountService.updateOffset(offsetEntry);
2281:                } catch (InvalidFlexibleOffsetException e) {
2282:                    LOG.debug("generateOffset() Offset Flexible Offset Error: "
2283:                            + e.getMessage());
2284:                    putTransactionError(offsetEntry, e.getMessage(), "",
2285:                            Message.TYPE_FATAL);
2286:                    return true;
2287:                }
2288:
2289:                createOutputEntry(offsetEntry, validGroup);
2290:                scrubberReport.incrementOffsetEntryGenerated();
2291:                return true;
2292:            }
2293:
2294:            /**
2295:             * Save an entry in origin entry
2296:             * 
2297:             * @param entry Entry to save
2298:             * @param group Group to save it in
2299:             */
2300:            private void createOutputEntry(OriginEntry entry,
2301:                    OriginEntryGroup group) {
2302:                // Write the entry if we aren't running in report only or collector mode.
2303:                if (reportOnlyMode || collectorMode) {
2304:                    // If the group is null don't write it because the error and expired groups aren't created in reportOnlyMode
2305:                    if (group != null) {
2306:                        entry.setEntryGroupId(group.getId());
2307:                        originEntryLiteService.save((OriginEntryLite) entry);
2308:                    }
2309:                } else {
2310:                    entry.setEntryGroupId(group.getId());
2311:                    originEntryLiteService.save((OriginEntryLite) entry);
2312:                }
2313:            }
2314:
2315:            /**
2316:             * If object is null, generate an error
2317:             * 
2318:             * @param glObject object to test
2319:             * @param errorMessage error message if glObject is null
2320:             * @param errorValue value of glObject to print in the error message
2321:             * @param type Type of message (fatal or warning)
2322:             * @return true of glObject is null
2323:             */
2324:            private boolean ifNullAddTransactionErrorAndReturnFalse(
2325:                    Object glObject, String errorMessage, String errorValue,
2326:                    int type) {
2327:                if (glObject == null) {
2328:                    if (StringUtils.hasText(errorMessage)) {
2329:                        addTransactionError(errorMessage, errorValue, type);
2330:                    } else {
2331:                        addTransactionError("Unexpected null object", glObject
2332:                                .getClass().getName(), type);
2333:                    }
2334:                    return false;
2335:                }
2336:                return true;
2337:            }
2338:
2339:            /**
2340:             * Add an error message to the list of messages for this transaction
2341:             * 
2342:             * @param errorMessage Error message
2343:             * @param errorValue Value that is in error
2344:             * @param type Type of error (Fatal or Warning)
2345:             */
2346:            private void addTransactionError(String errorMessage,
2347:                    String errorValue, int type) {
2348:                transactionErrors.add(new Message(errorMessage + " ("
2349:                        + errorValue + ")", type));
2350:            }
2351:
2352:            /**
2353:             * Puts a transaction error into this instance's collection of errors
2354:             * 
2355:             * @param s a transaction that caused a scrubber error
2356:             * @param errorMessage the message of what caused the error
2357:             * @param errorValue the value in error
2358:             * @param type the type of error
2359:             */
2360:            private void putTransactionError(Transaction s,
2361:                    String errorMessage, String errorValue, int type) {
2362:                List te = new ArrayList();
2363:                te
2364:                        .add(new Message(errorMessage + "(" + errorValue + ")",
2365:                                type));
2366:                scrubberReportErrors.put(s, te);
2367:            }
2368:
2369:            /**
2370:             * A class to hold the current unit of work the scrubber is using
2371:             */
2372:            class UnitOfWorkInfo {
2373:                // Unit of work key
2374:                public Integer univFiscalYr = 0;
2375:                public String finCoaCd = "";
2376:                public String accountNbr = "";
2377:                public String subAcctNbr = "";
2378:                public String finBalanceTypCd = "";
2379:                public String fdocTypCd = "";
2380:                public String fsOriginCd = "";
2381:                public String fdocNbr = "";
2382:                public Date fdocReversalDt = new Date(dateTimeService
2383:                        .getCurrentDate().getTime());
2384:                public String univFiscalPrdCd = "";
2385:
2386:                // Data about unit of work
2387:                public boolean entryMode = true;
2388:                public KualiDecimal offsetAmount = KualiDecimal.ZERO;
2389:                public String scrbFinCoaCd;
2390:                public String scrbAccountNbr;
2391:
2392:                /**
2393:                 * Constructs a ScrubberProcess.UnitOfWorkInfo instance
2394:                 */
2395:                public UnitOfWorkInfo() {
2396:                }
2397:
2398:                /**
2399:                 * Constructs a ScrubberProcess.UnitOfWorkInfo instance
2400:                 * @param e an origin entry belonging to this unit of work
2401:                 */
2402:                public UnitOfWorkInfo(OriginEntry e) {
2403:                    univFiscalYr = e.getUniversityFiscalYear();
2404:                    finCoaCd = e.getChartOfAccountsCode();
2405:                    accountNbr = e.getAccountNumber();
2406:                    subAcctNbr = e.getSubAccountNumber();
2407:                    finBalanceTypCd = e.getFinancialBalanceTypeCode();
2408:                    fdocTypCd = e.getFinancialDocumentTypeCode();
2409:                    fsOriginCd = e.getFinancialSystemOriginationCode();
2410:                    fdocNbr = e.getDocumentNumber();
2411:                    fdocReversalDt = e.getFinancialDocumentReversalDate();
2412:                    univFiscalPrdCd = e.getUniversityFiscalPeriodCode();
2413:                }
2414:
2415:                /**
2416:                 * Determines if an entry belongs to this unit of work
2417:                 * 
2418:                 * @param e the entry to check
2419:                 * @return true if it belongs to this unit of work, false otherwise
2420:                 */
2421:                public boolean isSameUnitOfWork(OriginEntry e) {
2422:                    // Compare the key fields
2423:                    return univFiscalYr.equals(e.getUniversityFiscalYear())
2424:                            && finCoaCd.equals(e.getChartOfAccountsCode())
2425:                            && accountNbr.equals(e.getAccountNumber())
2426:                            && subAcctNbr.equals(e.getSubAccountNumber())
2427:                            && finBalanceTypCd.equals(e
2428:                                    .getFinancialBalanceTypeCode())
2429:                            && fdocTypCd.equals(e
2430:                                    .getFinancialDocumentTypeCode())
2431:                            && fsOriginCd.equals(e
2432:                                    .getFinancialSystemOriginationCode())
2433:                            && fdocNbr.equals(e.getDocumentNumber())
2434:                            && ObjectHelper.isEqual(fdocReversalDt, e
2435:                                    .getFinancialDocumentReversalDate())
2436:                            && univFiscalPrdCd.equals(e
2437:                                    .getUniversityFiscalPeriodCode());
2438:                }
2439:
2440:                /**
2441:                 * Converts this unit of work info to a String
2442:                 * @return a String representation of this UnitOfWorkInfo
2443:                 * @see java.lang.Object#toString()
2444:                 */
2445:                public String toString() {
2446:                    return univFiscalYr + finCoaCd + accountNbr + subAcctNbr
2447:                            + finBalanceTypCd + fdocTypCd + fsOriginCd
2448:                            + fdocNbr + fdocReversalDt + univFiscalPrdCd;
2449:                }
2450:
2451:                /**
2452:                 * Generates the beginning of an OriginEntryFull, based on the unit of work info
2453:                 * 
2454:                 * @return a partially initialized OriginEntryFull
2455:                 */
2456:                public OriginEntryFull getOffsetTemplate() {
2457:                    OriginEntryFull e = new OriginEntryFull();
2458:                    e.setUniversityFiscalYear(univFiscalYr);
2459:                    e.setChartOfAccountsCode(finCoaCd);
2460:                    e.setAccountNumber(accountNbr);
2461:                    e.setSubAccountNumber(subAcctNbr);
2462:                    e.setFinancialBalanceTypeCode(finBalanceTypCd);
2463:                    e.setFinancialDocumentTypeCode(fdocTypCd);
2464:                    e.setFinancialSystemOriginationCode(fsOriginCd);
2465:                    e.setDocumentNumber(fdocNbr);
2466:                    e.setFinancialDocumentReversalDate(fdocReversalDt);
2467:                    e.setUniversityFiscalPeriodCode(univFiscalPrdCd);
2468:                    return e;
2469:                }
2470:            }
2471:
2472:            /**
2473:             * An internal class to hold errors encountered by the scrubber
2474:             */
2475:            class TransactionError {
2476:                public Transaction transaction;
2477:                public Message message;
2478:
2479:                /**
2480:                 * Constructs a ScrubberProcess.TransactionError instance
2481:                 * @param t the transaction that had the error
2482:                 * @param m a message about the error
2483:                 */
2484:                public TransactionError(Transaction t, Message m) {
2485:                    transaction = t;
2486:                    message = m;
2487:                }
2488:            }
2489:
2490:            /**
2491:             * This method modifies the run date if it is before the cutoff time specified by the RunTimeService See
2492:             * KULRNE-70 This method is public to facilitate unit testing
2493:             * 
2494:             * @param currentDate the date the scrubber should report as having run on
2495:             * @return the run date
2496:             */
2497:            public Date calculateRunDate(java.util.Date currentDate) {
2498:                return new Date(runDateService.calculateRunDate(currentDate)
2499:                        .getTime());
2500:            }
2501:
2502:            /**
2503:             * Sets the referenceLookup attribute value.
2504:             * 
2505:             * @param referenceLookup The referenceLookup to set.
2506:             */
2507:            public void setReferenceLookup(
2508:                    OriginEntryLookupService referenceLookup) {
2509:                this.referenceLookup.set(referenceLookup);
2510:                this.scrubberValidator.setReferenceLookup(referenceLookup);
2511:            }
2512:
2513:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.