Source Code Cross Referenced for ScrubberValidatorImpl.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.SimpleDateFormat;
0020:        import java.util.ArrayList;
0021:        import java.util.Calendar;
0022:        import java.util.List;
0023:
0024:        import org.apache.commons.lang.ArrayUtils;
0025:        import org.kuali.core.bo.DocumentType;
0026:        import org.kuali.core.service.KualiConfigurationService;
0027:        import org.kuali.core.service.PersistenceService;
0028:        import org.kuali.core.service.PersistenceStructureService;
0029:        import org.kuali.core.util.KualiDecimal;
0030:        import org.kuali.kfs.KFSConstants;
0031:        import org.kuali.kfs.KFSKeyConstants;
0032:        import org.kuali.kfs.bo.GeneralLedgerPendingEntry;
0033:        import org.kuali.kfs.bo.Options;
0034:        import org.kuali.kfs.bo.OriginationCode;
0035:        import org.kuali.kfs.context.SpringContext;
0036:        import org.kuali.kfs.service.OriginationCodeService;
0037:        import org.kuali.kfs.service.ParameterService;
0038:        import org.kuali.kfs.service.impl.ParameterConstants;
0039:        import org.kuali.module.chart.bo.Account;
0040:        import org.kuali.module.chart.bo.AccountingPeriod;
0041:        import org.kuali.module.chart.bo.Chart;
0042:        import org.kuali.module.chart.bo.ObjectCode;
0043:        import org.kuali.module.chart.bo.ObjectType;
0044:        import org.kuali.module.chart.bo.ProjectCode;
0045:        import org.kuali.module.chart.bo.SubAccount;
0046:        import org.kuali.module.chart.bo.SubObjCd;
0047:        import org.kuali.module.chart.bo.codes.BalanceTyp;
0048:        import org.kuali.module.chart.service.AccountService;
0049:        import org.kuali.module.chart.service.BalanceTypService;
0050:        import org.kuali.module.chart.service.ObjectTypeService;
0051:        import org.kuali.module.financial.service.UniversityDateService;
0052:        import org.kuali.module.gl.GLConstants;
0053:        import org.kuali.module.gl.batch.ScrubberStep;
0054:        import org.kuali.module.gl.bo.OriginEntry;
0055:        import org.kuali.module.gl.bo.UniversityDate;
0056:        import org.kuali.module.gl.dao.UniversityDateDao;
0057:        import org.kuali.module.gl.service.OriginEntryLookupService;
0058:        import org.kuali.module.gl.service.ScrubberValidator;
0059:        import org.kuali.module.gl.util.Message;
0060:        import org.kuali.module.gl.util.ObjectHelper;
0061:        import org.kuali.module.gl.util.StringHelper;
0062:        import org.kuali.module.labor.LaborConstants;
0063:        import org.kuali.module.labor.batch.LaborScrubberStep;
0064:        import org.springframework.transaction.annotation.Transactional;
0065:        import org.springframework.util.StringUtils;
0066:
0067:        /**
0068:         * The default GL implementation of ScrubberValidator
0069:         */
0070:        @Transactional
0071:        public class ScrubberValidatorImpl implements  ScrubberValidator {
0072:            private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
0073:                    .getLogger(ScrubberValidatorImpl.class);
0074:
0075:            private KualiConfigurationService kualiConfigurationService;
0076:            private ParameterService parameterService;
0077:            private PersistenceService persistenceService;
0078:            private UniversityDateDao universityDateDao;
0079:            private AccountService accountService;
0080:            private OriginationCodeService originationCodeService;
0081:            private PersistenceStructureService persistenceStructureService;
0082:            private ThreadLocal<OriginEntryLookupService> referenceLookup = new ThreadLocal<OriginEntryLookupService>();
0083:            private BalanceTypService balanceTypService;
0084:
0085:            public static final String DATE_FORMAT_STRING = "yyyy-MM-dd";
0086:
0087:            private static String[] debitOrCredit = new String[] {
0088:                    KFSConstants.GL_DEBIT_CODE, KFSConstants.GL_CREDIT_CODE };
0089:
0090:            /**
0091:             * Constructs a ScrubberValidatorImpl instance
0092:             */
0093:            public ScrubberValidatorImpl() {
0094:            }
0095:
0096:            private static int count = 0;
0097:
0098:            /**
0099:             * Validate a transaction for use in balance inquiry
0100:             * 
0101:             * @param entry Input transaction
0102:             * @see org.kuali.module.gl.service.ScrubberValidator#validateForInquiry(org.kuali.kfs.bo.GeneralLedgerPendingEntry)
0103:             */
0104:            public void validateForInquiry(GeneralLedgerPendingEntry entry) {
0105:                LOG.debug("validateForInquiry() started");
0106:
0107:                UniversityDate today = null;
0108:
0109:                if (entry.getUniversityFiscalYear() == null) {
0110:                    today = SpringContext.getBean(UniversityDateService.class)
0111:                            .getCurrentUniversityDate();
0112:                    entry.setUniversityFiscalYear(today
0113:                            .getUniversityFiscalYear());
0114:                }
0115:
0116:                if (entry.getUniversityFiscalPeriodCode() == null) {
0117:                    if (today == null) {
0118:                        today = SpringContext.getBean(
0119:                                UniversityDateService.class)
0120:                                .getCurrentUniversityDate();
0121:                    }
0122:                    entry.setUniversityFiscalPeriodCode(today
0123:                            .getUniversityFiscalAccountingPeriod());
0124:                }
0125:
0126:                if ((entry.getSubAccountNumber() == null)
0127:                        || (!StringUtils.hasText(entry.getSubAccountNumber()))) {
0128:                    entry.setSubAccountNumber(KFSConstants
0129:                            .getDashSubAccountNumber());
0130:                }
0131:                if ((entry.getFinancialSubObjectCode() == null)
0132:                        || (!StringUtils.hasText(entry
0133:                                .getFinancialSubObjectCode()))) {
0134:                    entry.setFinancialSubObjectCode(KFSConstants
0135:                            .getDashFinancialSubObjectCode());
0136:                }
0137:                if ((entry.getProjectCode() == null)
0138:                        || (!StringUtils.hasText(entry.getProjectCode()))) {
0139:                    entry.setProjectCode(KFSConstants.getDashProjectCode());
0140:                }
0141:            }
0142:
0143:            /**
0144:             * Validate a transaction in the scrubber
0145:             * 
0146:             * @param originEntry Input transaction (never changed)
0147:             * @param scrubbedEntry Output transaction (scrubbed version of input transaction)
0148:             * @param universityRunDate Date of scrubber run
0149:             * @return List of Message objects based for warnings or errors that happened when validating the transaction
0150:             * @see org.kuali.module.gl.service.ScrubberValidator#validateTransaction(org.kuali.module.gl.bo.OriginEntry, org.kuali.module.gl.bo.OriginEntry, org.kuali.module.gl.bo.UniversityDate, boolean)
0151:             */
0152:            public List<Message> validateTransaction(OriginEntry originEntry,
0153:                    OriginEntry scrubbedEntry,
0154:                    UniversityDate universityRunDate, boolean laborIndicator) {
0155:                LOG.debug("validateTransaction() started");
0156:
0157:                List<Message> errors = new ArrayList<Message>();
0158:
0159:                count++;
0160:                if (count % 100 == 0) {
0161:                    LOG.debug(count + " " + originEntry.getLine());
0162:                }
0163:
0164:                // The cobol checks fdoc_nbr, trn_ldgr_entr_desc, org_doc_nbr, org_reference_id, and fdoc_ref_nbr for characters less than
0165:                // ascii 32 or '~'. If found, it replaces that character with a space and reports a warning. This code does the ~, but not
0166:                // the
0167:                // less than 32 part.
0168:                if ((originEntry.getDocumentNumber() != null)
0169:                        && (originEntry.getDocumentNumber().indexOf("~") > -1)) {
0170:                    String d = originEntry.getDocumentNumber();
0171:                    scrubbedEntry.setDocumentNumber(d.replaceAll("~", " "));
0172:                    errors.add(new Message("** INVALID CHARACTER EDITED",
0173:                            Message.TYPE_WARNING));
0174:                }
0175:                if ((originEntry.getTransactionLedgerEntryDescription() != null)
0176:                        && (originEntry.getTransactionLedgerEntryDescription()
0177:                                .indexOf("~") > -1)) {
0178:                    String d = originEntry
0179:                            .getTransactionLedgerEntryDescription();
0180:                    scrubbedEntry.setTransactionLedgerEntryDescription(d
0181:                            .replaceAll("~", " "));
0182:                    errors.add(new Message("** INVALID CHARACTER EDITED",
0183:                            Message.TYPE_WARNING));
0184:                }
0185:                if ((originEntry.getOrganizationDocumentNumber() != null)
0186:                        && (originEntry.getOrganizationDocumentNumber()
0187:                                .indexOf("~") > -1)) {
0188:                    String d = originEntry.getOrganizationDocumentNumber();
0189:                    scrubbedEntry.setOrganizationDocumentNumber(d.replaceAll(
0190:                            "~", " "));
0191:                    errors.add(new Message("** INVALID CHARACTER EDITED",
0192:                            Message.TYPE_WARNING));
0193:                }
0194:                if ((originEntry.getOrganizationReferenceId() != null)
0195:                        && (originEntry.getOrganizationReferenceId().indexOf(
0196:                                "~") > -1)) {
0197:                    String d = originEntry.getOrganizationReferenceId();
0198:                    scrubbedEntry.setOrganizationReferenceId(d.replaceAll("~",
0199:                            " "));
0200:                    errors.add(new Message("** INVALID CHARACTER EDITED",
0201:                            Message.TYPE_WARNING));
0202:                }
0203:                if ((originEntry.getReferenceFinancialDocumentNumber() != null)
0204:                        && (originEntry.getReferenceFinancialDocumentNumber()
0205:                                .indexOf("~") > -1)) {
0206:                    String d = originEntry
0207:                            .getReferenceFinancialDocumentNumber();
0208:                    scrubbedEntry.setReferenceFinancialDocumentNumber(d
0209:                            .replaceAll("~", " "));
0210:                    errors.add(new Message("** INVALID CHARACTER EDITED",
0211:                            Message.TYPE_WARNING));
0212:                }
0213:
0214:                // It's important that this check come before the checks for object, sub-object and accountingPeriod
0215:                // because this validation method will set the fiscal year and reload those three objects if the fiscal
0216:                // year was invalid. This will also set originEntry.getOption and workingEntry.getOption. So, it's
0217:                // probably a good idea to validate the fiscal year first thing.
0218:                Message err = validateFiscalYear(originEntry, scrubbedEntry,
0219:                        universityRunDate);
0220:                if (err != null) {
0221:                    errors.add(err);
0222:                }
0223:
0224:                err = validateBalanceType(originEntry, scrubbedEntry);
0225:                if (err != null) {
0226:                    errors.add(err);
0227:                }
0228:
0229:                err = validateTransactionDate(originEntry, scrubbedEntry,
0230:                        universityRunDate);
0231:                if (err != null) {
0232:                    errors.add(err);
0233:                }
0234:
0235:                err = validateTransactionAmount(originEntry, scrubbedEntry);
0236:                if (err != null) {
0237:                    errors.add(err);
0238:                }
0239:
0240:                err = validateChart(originEntry, scrubbedEntry);
0241:                if (err != null) {
0242:                    errors.add(err);
0243:                }
0244:
0245:                // Labor Scrubber doesn't validate Account here.
0246:                if (!laborIndicator) {
0247:                    err = validateAccount(originEntry, scrubbedEntry,
0248:                            universityRunDate);
0249:                    if (err != null) {
0250:                        errors.add(err);
0251:                    }
0252:                }
0253:
0254:                err = validateSubAccount(originEntry, scrubbedEntry);
0255:                if (err != null) {
0256:                    errors.add(err);
0257:                }
0258:
0259:                err = validateProjectCode(originEntry, scrubbedEntry);
0260:                if (err != null) {
0261:                    errors.add(err);
0262:                }
0263:
0264:                err = validateDocumentType(originEntry, scrubbedEntry);
0265:                if (err != null) {
0266:                    errors.add(err);
0267:                }
0268:
0269:                err = validateOrigination(originEntry, scrubbedEntry);
0270:                if (err != null) {
0271:                    errors.add(err);
0272:                }
0273:
0274:                err = validateDocumentNumber(originEntry, scrubbedEntry);
0275:                if (err != null) {
0276:                    errors.add(err);
0277:                }
0278:
0279:                err = validateObjectCode(originEntry, scrubbedEntry);
0280:                if (err != null) {
0281:                    errors.add(err);
0282:                }
0283:
0284:                // If object code is invalid, we can't check the object type
0285:                if (err == null) {
0286:                    err = validateObjectType(originEntry, scrubbedEntry);
0287:                    if (err != null) {
0288:                        errors.add(err);
0289:                    }
0290:                }
0291:
0292:                err = validateSubObjectCode(originEntry, scrubbedEntry);
0293:                if (err != null) {
0294:                    errors.add(err);
0295:                }
0296:
0297:                err = validateReferenceDocumentFields(originEntry,
0298:                        scrubbedEntry);
0299:                if (err != null) {
0300:                    errors.add(err);
0301:                }
0302:
0303:                err = validateUniversityFiscalPeriodCode(originEntry,
0304:                        scrubbedEntry, universityRunDate);
0305:                if (err != null) {
0306:                    errors.add(err);
0307:                }
0308:
0309:                err = validateReversalDate(originEntry, scrubbedEntry);
0310:                if (err != null) {
0311:                    errors.add(err);
0312:                }
0313:
0314:                return errors;
0315:            }
0316:
0317:            /**
0318:             * Validates the account of an origin entry 
0319:             * 
0320:             * @param originEntry the origin entry to find the account of
0321:             * @param workingEntry the copy of the entry to move the account over to if it is valid
0322:             * @param universityRunDate the run date of the scrubber process
0323:             * @return a Message if the account was invalid, or null if no error was encountered
0324:             */
0325:            private Message validateAccount(OriginEntry originEntry,
0326:                    OriginEntry workingEntry, UniversityDate universityRunDate) {
0327:                LOG.debug("validateAccount() started");
0328:
0329:                Account originEntryAccount = referenceLookup.get().getAccount(
0330:                        originEntry);
0331:                if (originEntryAccount == null) {
0332:                    return new Message(
0333:                            kualiConfigurationService
0334:                                    .getPropertyString(KFSKeyConstants.ERROR_ACCOUNT_NOT_FOUND)
0335:                                    + "("
0336:                                    + originEntry.getChartOfAccountsCode()
0337:                                    + "-"
0338:                                    + originEntry.getAccountNumber()
0339:                                    + ")", Message.TYPE_FATAL);
0340:                }
0341:
0342:                if (parameterService
0343:                        .getParameterValue(
0344:                                ParameterConstants.GENERAL_LEDGER_BATCH.class,
0345:                                KFSConstants.SystemGroupParameterNames.GL_ANNUAL_CLOSING_DOC_TYPE)
0346:                        .equals(originEntry.getFinancialDocumentTypeCode())) {
0347:                    workingEntry.setAccountNumber(originEntry
0348:                            .getAccountNumber());
0349:                    return null;
0350:                }
0351:
0352:                if ((originEntryAccount.getAccountExpirationDate() == null)
0353:                        && !originEntryAccount.isAccountClosedIndicator()) {
0354:                    // account is neither closed nor expired
0355:                    workingEntry.setAccountNumber(originEntry
0356:                            .getAccountNumber());
0357:                    return null;
0358:                }
0359:
0360:                String[] continuationAccountBypassOriginationCodes = parameterService
0361:                        .getParameterValues(
0362:                                ScrubberStep.class,
0363:                                GLConstants.GlScrubberGroupRules.CONTINUATION_ACCOUNT_BYPASS_ORIGINATION_CODES)
0364:                        .toArray(new String[] {});
0365:
0366:                ObjectTypeService objectTypeService = (ObjectTypeService) SpringContext
0367:                        .getBean(ObjectTypeService.class);
0368:                String[] continuationAccountBypassBalanceTypeCodes = balanceTypService
0369:                        .getContinuationAccountBypassBalanceTypeCodes(
0370:                                universityRunDate.getUniversityFiscalYear())
0371:                        .toArray(new String[] {});
0372:                String[] continuationAccountBypassDocumentTypeCodes = parameterService
0373:                        .getParameterValues(
0374:                                ScrubberStep.class,
0375:                                GLConstants.GlScrubberGroupRules.CONTINUATION_ACCOUNT_BYPASS_DOCUMENT_TYPE_CODES)
0376:                        .toArray(new String[] {});
0377:
0378:                // Has an expiration date or is closed
0379:                if ((ArrayUtils.contains(
0380:                        continuationAccountBypassOriginationCodes, originEntry
0381:                                .getFinancialSystemOriginationCode()))
0382:                        && originEntryAccount.isAccountClosedIndicator()) {
0383:                    return new Message(
0384:                            kualiConfigurationService
0385:                                    .getPropertyString(KFSKeyConstants.ERROR_ORIGIN_CODE_CANNOT_HAVE_CLOSED_ACCOUNT)
0386:                                    + " ("
0387:                                    + originEntryAccount
0388:                                            .getChartOfAccountsCode()
0389:                                    + "-"
0390:                                    + originEntry.getAccountNumber() + ")",
0391:                            Message.TYPE_FATAL);
0392:                }
0393:
0394:                if ((ArrayUtils.contains(
0395:                        continuationAccountBypassOriginationCodes, originEntry
0396:                                .getFinancialSystemOriginationCode())
0397:                        || ArrayUtils.contains(
0398:                                continuationAccountBypassBalanceTypeCodes,
0399:                                originEntry.getFinancialBalanceTypeCode()) || ArrayUtils
0400:                        .contains(continuationAccountBypassDocumentTypeCodes,
0401:                                originEntry.getFinancialDocumentTypeCode()
0402:                                        .trim()))
0403:                        && !originEntryAccount.isAccountClosedIndicator()) {
0404:                    workingEntry.setAccountNumber(originEntry
0405:                            .getAccountNumber());
0406:                    return null;
0407:                }
0408:
0409:                Calendar today = Calendar.getInstance();
0410:                today.setTime(universityRunDate.getUniversityDate());
0411:
0412:                long offsetAccountExpirationTime = getAdjustedAccountExpirationDate(originEntryAccount);
0413:
0414:                if (isExpired(offsetAccountExpirationTime, today)
0415:                        || originEntryAccount.isAccountClosedIndicator()) {
0416:                    Message error = continuationAccountLogic(originEntry,
0417:                            workingEntry, today);
0418:                    if (error != null) {
0419:                        return error;
0420:                    }
0421:                }
0422:
0423:                workingEntry.setAccountNumber(originEntry.getAccountNumber());
0424:                return null;
0425:            }
0426:
0427:            /**
0428:             * Called when the account of the origin entry is expired or closed, this validates the continuation account
0429:             * 
0430:             * @param originEntry the origin entry being scrubbed
0431:             * @param workingEntry the scrubbed version of the origin entry
0432:             * @param today the run date of the scrubber (to test against expiration dates)
0433:             * @return a Message if an error was encountered, otherwise null
0434:             */
0435:            private Message continuationAccountLogic(OriginEntry originEntry,
0436:                    OriginEntry workingEntry, Calendar today) {
0437:
0438:                List checkedAccountNumbers = new ArrayList();
0439:
0440:                Account continuationAccount = null;
0441:                Account originEntryAccount = referenceLookup.get().getAccount(
0442:                        originEntry);
0443:
0444:                String chartCode = originEntryAccount
0445:                        .getContinuationFinChrtOfAcctCd();
0446:                String accountNumber = originEntryAccount
0447:                        .getContinuationAccountNumber();
0448:
0449:                for (int i = 0; i < 10; ++i) {
0450:                    if (checkedAccountNumbers.contains(chartCode
0451:                            + accountNumber)) {
0452:                        // Something is really wrong with the data because this account has already been evaluated.
0453:                        return new Message(
0454:                                kualiConfigurationService
0455:                                        .getPropertyString(KFSKeyConstants.ERROR_CIRCULAR_DEPENDENCY_IN_CONTINUATION_ACCOUNT_LOGIC),
0456:                                Message.TYPE_FATAL);
0457:                    }
0458:
0459:                    if ((chartCode == null) || (accountNumber == null)) {
0460:                        return new Message(
0461:                                kualiConfigurationService
0462:                                        .getPropertyString(KFSKeyConstants.ERROR_CONTINUATION_ACCOUNT_NOT_FOUND),
0463:                                Message.TYPE_FATAL);
0464:                    }
0465:
0466:                    // Lookup the account
0467:                    continuationAccount = accountService.getByPrimaryId(
0468:                            chartCode, accountNumber);
0469:                    if (null == continuationAccount) {
0470:                        // account not found
0471:                        return new Message(
0472:                                kualiConfigurationService
0473:                                        .getPropertyString(KFSKeyConstants.ERROR_CONTINUATION_ACCOUNT_NOT_FOUND),
0474:                                Message.TYPE_FATAL);
0475:                    } else {
0476:                        // the account exists
0477:                        if (continuationAccount.getAccountExpirationDate() == null) {
0478:                            // No expiration date
0479:                            workingEntry.setAccountNumber(accountNumber);
0480:                            workingEntry.setChartOfAccountsCode(chartCode);
0481:
0482:                            workingEntry
0483:                                    .setTransactionLedgerEntryDescription(kualiConfigurationService
0484:                                            .getPropertyString(KFSKeyConstants.MSG_AUTO_FORWARD)
0485:                                            + " "
0486:                                            + originEntry
0487:                                                    .getChartOfAccountsCode()
0488:                                            + originEntry.getAccountNumber()
0489:                                            + originEntry
0490:                                                    .getTransactionLedgerEntryDescription());
0491:                            return new Message(
0492:                                    kualiConfigurationService
0493:                                            .getPropertyString(KFSKeyConstants.MSG_ACCOUNT_CLOSED_TO)
0494:                                            + " "
0495:                                            + workingEntry
0496:                                                    .getChartOfAccountsCode()
0497:                                            + workingEntry.getAccountNumber(),
0498:                                    Message.TYPE_WARNING);
0499:                        } else {
0500:                            // the account does have an expiration date.
0501:                            // This is the only case in which we might go
0502:                            // on for another iteration of the loop.
0503:                            checkedAccountNumbers
0504:                                    .add(chartCode + accountNumber);
0505:
0506:                            // Add 3 months to the expiration date if it's a contract and grant account.
0507:                            long offsetAccountExpirationTime = getAdjustedAccountExpirationDate(continuationAccount);
0508:
0509:                            // Check that the account has not expired.
0510:
0511:                            // If the account has expired go around for another iteration.
0512:                            if (isExpired(offsetAccountExpirationTime, today)) {
0513:                                chartCode = continuationAccount
0514:                                        .getContinuationFinChrtOfAcctCd();
0515:                                accountNumber = continuationAccount
0516:                                        .getContinuationAccountNumber();
0517:                            } else {
0518:                                workingEntry.setAccountNumber(accountNumber);
0519:                                workingEntry.setChartOfAccountsCode(chartCode);
0520:
0521:                                workingEntry
0522:                                        .setTransactionLedgerEntryDescription(kualiConfigurationService
0523:                                                .getPropertyString(KFSKeyConstants.MSG_AUTO_FORWARD)
0524:                                                + originEntry
0525:                                                        .getChartOfAccountsCode()
0526:                                                + originEntry
0527:                                                        .getAccountNumber()
0528:                                                + originEntry
0529:                                                        .getTransactionLedgerEntryDescription());
0530:                                return new Message(
0531:                                        kualiConfigurationService
0532:                                                .getPropertyString(KFSKeyConstants.MSG_ACCOUNT_CLOSED_TO)
0533:                                                + workingEntry
0534:                                                        .getChartOfAccountsCode()
0535:                                                + workingEntry
0536:                                                        .getAccountNumber(),
0537:                                        Message.TYPE_WARNING);
0538:                            }
0539:                        }
0540:                    }
0541:                }
0542:
0543:                // We failed to find a valid continuation account.
0544:                return new Message(
0545:                        kualiConfigurationService
0546:                                .getPropertyString(KFSKeyConstants.ERROR_CONTINUATION_ACCOUNT_LIMIT_REACHED),
0547:                        Message.TYPE_FATAL);
0548:            }
0549:
0550:            /**
0551:             * Calculates the expiration date of an adjusted account
0552:             * 
0553:             * @param account the expired account
0554:             * @return the timestamp of the adjusted date
0555:             */
0556:            private long getAdjustedAccountExpirationDate(Account account) {
0557:                long offsetAccountExpirationTime = account
0558:                        .getAccountExpirationDate().getTime();
0559:
0560:                if (account.isForContractsAndGrants()
0561:                        && (!account.isAccountClosedIndicator())) {
0562:
0563:                    String daysOffset = parameterService
0564:                            .getParameterValue(
0565:                                    ScrubberStep.class,
0566:                                    KFSConstants.SystemGroupParameterNames.GL_SCRUBBER_VALIDATION_DAYS_OFFSET);
0567:                    int daysOffsetInt = 3 * 30; // default to 90 days (approximately 3 months)
0568:
0569:                    if (daysOffset.trim().length() > 0) {
0570:
0571:                        daysOffsetInt = new Integer(daysOffset).intValue();
0572:                    }
0573:
0574:                    Calendar tempCal = Calendar.getInstance();
0575:                    tempCal.setTimeInMillis(offsetAccountExpirationTime);
0576:                    tempCal.add(Calendar.DAY_OF_MONTH, daysOffsetInt);
0577:                    offsetAccountExpirationTime = tempCal.getTimeInMillis();
0578:                }
0579:
0580:                return offsetAccountExpirationTime;
0581:            }
0582:
0583:            /**
0584:             * Validates the reversal date of the origin entry
0585:             * 
0586:             * @param originEntry the origin entry being scrubbed
0587:             * @param workingEntry the scrubbed version of the origin entry
0588:             * @return a Message if an error was encountered, otherwise null
0589:             */
0590:            private Message validateReversalDate(OriginEntry originEntry,
0591:                    OriginEntry workingEntry) {
0592:                LOG.debug("validateReversalDate() started");
0593:
0594:                if (originEntry.getFinancialDocumentReversalDate() != null) {
0595:                    UniversityDate universityDate = universityDateDao
0596:                            .getByPrimaryKey(originEntry
0597:                                    .getFinancialDocumentReversalDate());
0598:                    if (universityDate == null) {
0599:                        Date reversalDate = originEntry
0600:                                .getFinancialDocumentReversalDate();
0601:                        SimpleDateFormat format = new SimpleDateFormat(
0602:                                DATE_FORMAT_STRING);
0603:                        return new Message(
0604:                                kualiConfigurationService
0605:                                        .getPropertyString(KFSKeyConstants.ERROR_REVERSAL_DATE_NOT_FOUND)
0606:                                        + "("
0607:                                        + format.format(reversalDate)
0608:                                        + ")", Message.TYPE_FATAL);
0609:                    } else {
0610:                        workingEntry
0611:                                .setFinancialDocumentReversalDate(originEntry
0612:                                        .getFinancialDocumentReversalDate());
0613:                    }
0614:                }
0615:                return null;
0616:            }
0617:
0618:            /**
0619:             * Validates the sub account of the origin entry
0620:             * 
0621:             * @param originEntry the origin entry being scrubbed
0622:             * @param workingEntry the scrubbed version of the origin entry
0623:             * @return a Message if an error was encountered, otherwise null
0624:             */
0625:            private Message validateSubAccount(OriginEntry originEntry,
0626:                    OriginEntry workingEntry) {
0627:                LOG.debug("validateSubAccount() started");
0628:
0629:                // If the sub account number is empty, set it to dashes.
0630:                // Otherwise set the workingEntry sub account number to the
0631:                // sub account number of the input origin entry.
0632:                if (StringUtils.hasText(originEntry.getSubAccountNumber())) {
0633:                    // sub account IS specified
0634:                    SubAccount originEntrySubAccount = referenceLookup.get()
0635:                            .getSubAccount(originEntry);
0636:                    if (!KFSConstants.getDashSubAccountNumber().equals(
0637:                            originEntry.getSubAccountNumber())) {
0638:                        if (originEntrySubAccount == null) {
0639:                            // sub account is not valid
0640:                            return new Message(
0641:                                    kualiConfigurationService
0642:                                            .getPropertyString(KFSKeyConstants.ERROR_SUB_ACCOUNT_NOT_FOUND)
0643:                                            + "("
0644:                                            + originEntry
0645:                                                    .getChartOfAccountsCode()
0646:                                            + "-"
0647:                                            + originEntry.getAccountNumber()
0648:                                            + "-"
0649:                                            + originEntry.getSubAccountNumber()
0650:                                            + ")", Message.TYPE_FATAL);
0651:                        } else {
0652:                            // sub account IS valid
0653:                            if (originEntrySubAccount
0654:                                    .isSubAccountActiveIndicator()) {
0655:                                // sub account IS active
0656:                                workingEntry.setSubAccountNumber(originEntry
0657:                                        .getSubAccountNumber());
0658:                            } else {
0659:                                // sub account IS NOT active
0660:                                if (parameterService
0661:                                        .getParameterValue(
0662:                                                ParameterConstants.GENERAL_LEDGER_BATCH.class,
0663:                                                KFSConstants.SystemGroupParameterNames.GL_ANNUAL_CLOSING_DOC_TYPE)
0664:                                        .equals(
0665:                                                originEntry
0666:                                                        .getFinancialDocumentTypeCode())) {
0667:                                    // document IS annual closing
0668:                                    workingEntry
0669:                                            .setSubAccountNumber(originEntry
0670:                                                    .getSubAccountNumber());
0671:                                } else {
0672:                                    // document is NOT annual closing
0673:                                    return new Message(
0674:                                            kualiConfigurationService
0675:                                                    .getPropertyString(KFSKeyConstants.ERROR_SUB_ACCOUNT_NOT_ACTIVE)
0676:                                                    + "("
0677:                                                    + originEntry
0678:                                                            .getChartOfAccountsCode()
0679:                                                    + "-"
0680:                                                    + originEntry
0681:                                                            .getAccountNumber()
0682:                                                    + "-"
0683:                                                    + originEntry
0684:                                                            .getSubAccountNumber()
0685:                                                    + ")", Message.TYPE_FATAL);
0686:                                }
0687:                            }
0688:                        }
0689:                    } else {
0690:                        // the sub account is dashes
0691:                        workingEntry.setSubAccountNumber(KFSConstants
0692:                                .getDashSubAccountNumber());
0693:                    }
0694:                } else {
0695:                    // No sub account is specified.
0696:                    workingEntry.setSubAccountNumber(KFSConstants
0697:                            .getDashSubAccountNumber());
0698:                }
0699:                return null;
0700:            }
0701:
0702:            /**
0703:             * Validates the project code of the origin entry
0704:             * 
0705:             * @param originEntry the origin entry being scrubbed
0706:             * @param workingEntry the scrubbed version of the origin entry
0707:             * @return a Message if an error was encountered, otherwise null
0708:             */
0709:            private Message validateProjectCode(OriginEntry originEntry,
0710:                    OriginEntry workingEntry) {
0711:                LOG.debug("validateProjectCode() started");
0712:
0713:                if (StringUtils.hasText(originEntry.getProjectCode())
0714:                        && !KFSConstants.getDashProjectCode().equals(
0715:                                originEntry.getProjectCode())) {
0716:                    ProjectCode originEntryProject = referenceLookup.get()
0717:                            .getProjectCode(originEntry);
0718:                    if (originEntryProject == null) {
0719:                        return new Message(
0720:                                kualiConfigurationService
0721:                                        .getPropertyString(KFSKeyConstants.ERROR_PROJECT_CODE_NOT_FOUND)
0722:                                        + " ("
0723:                                        + originEntry.getProjectCode()
0724:                                        + ")", Message.TYPE_FATAL);
0725:                    } else {
0726:                        if (originEntryProject.isActive()) {
0727:                            workingEntry.setProjectCode(originEntry
0728:                                    .getProjectCode());
0729:                        } else {
0730:                            return new Message(
0731:                                    kualiConfigurationService
0732:                                            .getPropertyString(KFSKeyConstants.ERROR_PROJECT_CODE_MUST_BE_ACTIVE)
0733:                                            + " ("
0734:                                            + originEntry.getProjectCode()
0735:                                            + ")", Message.TYPE_FATAL);
0736:                        }
0737:                    }
0738:                } else {
0739:                    workingEntry.setProjectCode(KFSConstants
0740:                            .getDashProjectCode());
0741:                }
0742:
0743:                return null;
0744:            }
0745:
0746:            /**
0747:             * Validates the fiscal year of the origin entry
0748:             * 
0749:             * @param originEntry the origin entry being scrubbed
0750:             * @param workingEntry the scrubbed version of the origin entry
0751:             * @param universityRunDate the university date when this scrubber process is being run
0752:             * @return a Message if an error was encountered, otherwise null
0753:             */
0754:            private Message validateFiscalYear(OriginEntry originEntry,
0755:                    OriginEntry workingEntry, UniversityDate universityRunDate) {
0756:                LOG.debug("validateFiscalYear() started");
0757:
0758:                if ((originEntry.getUniversityFiscalYear() == null)
0759:                        || (originEntry.getUniversityFiscalYear().intValue() == 0)) {
0760:                    originEntry.setUniversityFiscalYear(universityRunDate
0761:                            .getUniversityFiscalYear());
0762:                    workingEntry.setUniversityFiscalYear(universityRunDate
0763:                            .getUniversityFiscalYear());
0764:                } else {
0765:                    workingEntry.setUniversityFiscalYear(originEntry
0766:                            .getUniversityFiscalYear());
0767:                }
0768:
0769:                Options originEntryOption = referenceLookup.get().getOption(
0770:                        originEntry);
0771:                if (originEntryOption == null) {
0772:                    return new Message(
0773:                            kualiConfigurationService
0774:                                    .getPropertyString(KFSKeyConstants.ERROR_UNIV_FISCAL_YR_NOT_FOUND)
0775:                                    + " ("
0776:                                    + originEntry.getUniversityFiscalYear()
0777:                                    + ")", Message.TYPE_FATAL);
0778:                }
0779:                return null;
0780:            }
0781:
0782:            /**
0783:             * Validates the transaction date of the origin entry, make sure it is a valid university date
0784:             * 
0785:             * @param originEntry the origin entry being scrubbed
0786:             * @param workingEntry the scrubbed version of the origin entry
0787:             * @param universityRunDate the university date when this scrubber process is being run
0788:             * @return a Message if an error was encountered, otherwise null
0789:             */
0790:            private Message validateTransactionDate(OriginEntry originEntry,
0791:                    OriginEntry workingEntry, UniversityDate universityRunDate) {
0792:                LOG.debug("validateTransactionDate() started");
0793:
0794:                if (originEntry.getTransactionDate() == null) {
0795:                    Date transactionDate = new Date(universityRunDate
0796:                            .getUniversityDate().getTime());
0797:
0798:                    // Set the transaction date to the run date.
0799:                    originEntry.setTransactionDate(transactionDate);
0800:                    workingEntry.setTransactionDate(transactionDate);
0801:                } else {
0802:                    workingEntry.setTransactionDate(originEntry
0803:                            .getTransactionDate());
0804:                }
0805:
0806:                // Next, we have to validate the transaction date against the university date table.
0807:                if (universityDateDao.getByPrimaryKey(originEntry
0808:                        .getTransactionDate()) == null) {
0809:                    return new Message(
0810:                            kualiConfigurationService
0811:                                    .getPropertyString(KFSKeyConstants.ERROR_TRANSACTION_DATE_INVALID)
0812:                                    + " ("
0813:                                    + originEntry.getTransactionDate()
0814:                                    + ")", Message.TYPE_FATAL);
0815:                }
0816:                return null;
0817:            }
0818:
0819:            /**
0820:             * Valides the document type of an origin entry 
0821:             * @param originEntry the origin entry to check
0822:             * @param workingEntryInfo the copy of that entry to move good data over to
0823:             * @return a Message if the document type is invalid, otherwise if valid, null
0824:             */
0825:            private Message validateDocumentType(OriginEntry originEntry,
0826:                    OriginEntry workingEntry) {
0827:                LOG.debug("validateDocumentType() started");
0828:
0829:                DocumentType originEntryDocumentType = referenceLookup.get()
0830:                        .getDocumentType(originEntry);
0831:                if (originEntryDocumentType == null) {
0832:                    return new Message(
0833:                            kualiConfigurationService
0834:                                    .getPropertyString(KFSKeyConstants.ERROR_DOCUMENT_TYPE_NOT_FOUND)
0835:                                    + " ("
0836:                                    + originEntry
0837:                                            .getFinancialDocumentTypeCode()
0838:                                    + ")", Message.TYPE_FATAL);
0839:                }
0840:
0841:                workingEntry.setFinancialDocumentTypeCode(originEntry
0842:                        .getFinancialDocumentTypeCode());
0843:                return null;
0844:            }
0845:
0846:            /**
0847:             * Validates the origination code of the origin entry
0848:             * 
0849:             * @param originEntry the origin entry being scrubbed
0850:             * @param workingEntry the scrubbed version of the origin entry
0851:             * @return a Message if an error was encountered, otherwise null
0852:             */
0853:            private Message validateOrigination(OriginEntry originEntry,
0854:                    OriginEntry workingEntry) {
0855:                LOG.debug("validateOrigination() started");
0856:
0857:                if (StringUtils.hasText(originEntry
0858:                        .getFinancialSystemOriginationCode())) {
0859:                    OriginationCode originEntryOrigination = referenceLookup
0860:                            .get().getOriginationCode(originEntry);
0861:                    if (originEntryOrigination == null) {
0862:                        return new Message(
0863:                                kualiConfigurationService
0864:                                        .getPropertyString(KFSKeyConstants.ERROR_ORIGIN_CODE_NOT_FOUND)
0865:                                        + " ("
0866:                                        + originEntry
0867:                                                .getFinancialSystemOriginationCode()
0868:                                        + ")", Message.TYPE_FATAL);
0869:                    } else {
0870:                        workingEntry
0871:                                .setFinancialSystemOriginationCode(originEntry
0872:                                        .getFinancialSystemOriginationCode());
0873:                    }
0874:                } else {
0875:                    return new Message(
0876:                            kualiConfigurationService
0877:                                    .getPropertyString(KFSKeyConstants.ERROR_ORIGIN_CODE_NOT_FOUND)
0878:                                    + " ("
0879:                                    + originEntry
0880:                                            .getFinancialSystemOriginationCode()
0881:                                    + ")", Message.TYPE_FATAL);
0882:                }
0883:                return null;
0884:            }
0885:
0886:            /**
0887:             * Validates the document number of the origin entry
0888:             * 
0889:             * @param originEntry the origin entry being scrubbed
0890:             * @param workingEntry the scrubbed version of the origin entry
0891:             * @return a Message if an error was encountered, otherwise null
0892:             */
0893:            private Message validateDocumentNumber(OriginEntry originEntry,
0894:                    OriginEntry workingEntry) {
0895:                LOG.debug("validateDocumentNumber() started");
0896:
0897:                if (!StringUtils.hasText(originEntry.getDocumentNumber())) {
0898:                    return new Message(
0899:                            kualiConfigurationService
0900:                                    .getPropertyString(KFSKeyConstants.ERROR_DOCUMENT_NUMBER_REQUIRED),
0901:                            Message.TYPE_FATAL);
0902:                } else {
0903:                    workingEntry.setDocumentNumber(originEntry
0904:                            .getDocumentNumber());
0905:                    return null;
0906:                }
0907:            }
0908:
0909:            /**
0910:             * Validates the chart of the origin entry
0911:             * 
0912:             * @param originEntry the origin entry being scrubbed
0913:             * @param workingEntry the scrubbed version of the origin entry
0914:             * @return a Message if an error was encountered, otherwise null
0915:             */
0916:            private Message validateChart(OriginEntry originEntry,
0917:                    OriginEntry workingEntry) {
0918:                LOG.debug("validateChart() started");
0919:
0920:                Chart originEntryChart = referenceLookup.get().getChart(
0921:                        originEntry);
0922:                if (originEntryChart == null) {
0923:                    return new Message(
0924:                            kualiConfigurationService
0925:                                    .getPropertyString(KFSKeyConstants.ERROR_CHART_NOT_FOUND)
0926:                                    + " ("
0927:                                    + originEntry.getChartOfAccountsCode()
0928:                                    + ")", Message.TYPE_FATAL);
0929:                }
0930:
0931:                if (!originEntryChart.isFinChartOfAccountActiveIndicator()) {
0932:                    return new Message(
0933:                            kualiConfigurationService
0934:                                    .getPropertyString(KFSKeyConstants.ERROR_CHART_NOT_ACTIVE)
0935:                                    + " ("
0936:                                    + originEntry.getChartOfAccountsCode()
0937:                                    + ")", Message.TYPE_FATAL);
0938:                }
0939:
0940:                workingEntry.setChartOfAccountsCode(originEntry
0941:                        .getChartOfAccountsCode());
0942:                return null;
0943:            }
0944:
0945:            /**
0946:             * Validates the object code of the origin entry
0947:             * 
0948:             * @param originEntry the origin entry being scrubbed
0949:             * @param workingEntry the scrubbed version of the origin entry
0950:             * @return a Message if an error was encountered, otherwise null
0951:             */
0952:            private Message validateObjectCode(OriginEntry originEntry,
0953:                    OriginEntry workingEntry) {
0954:                LOG.debug("validateObjectCode() started");
0955:
0956:                if (!StringUtils.hasText(originEntry.getFinancialObjectCode())) {
0957:                    return new Message(
0958:                            kualiConfigurationService
0959:                                    .getPropertyString(KFSKeyConstants.ERROR_OBJECT_CODE_EMPTY),
0960:                            Message.TYPE_FATAL);
0961:                }
0962:
0963:                // We're checking the object code based on the year & chart from the working entry.
0964:                workingEntry.setFinancialObjectCode(originEntry
0965:                        .getFinancialObjectCode());
0966:
0967:                // the fiscal year can be blank in originEntry, but we're assuming that the year attribute is populated by the validate year
0968:                // method
0969:                ObjectCode workingEntryFinancialObject = referenceLookup.get()
0970:                        .getFinancialObject(workingEntry);
0971:                if (workingEntryFinancialObject == null) {
0972:                    return new Message(
0973:                            kualiConfigurationService
0974:                                    .getPropertyString(KFSKeyConstants.ERROR_OBJECT_CODE_NOT_FOUND)
0975:                                    + " ("
0976:                                    + originEntry.getUniversityFiscalYear()
0977:                                    + "-"
0978:                                    + originEntry.getChartOfAccountsCode()
0979:                                    + "-"
0980:                                    + originEntry.getFinancialObjectCode()
0981:                                    + ")", Message.TYPE_FATAL);
0982:                }
0983:
0984:                return null;
0985:            }
0986:
0987:            /**
0988:             * Assuming that the object code has been validated first, validates the object type of the entry
0989:             * 
0990:             * @param originEntry the origin entry being scrubbed
0991:             * @param workingEntry the scrubbed version of the origin entry
0992:             * @return a Message if an error was encountered, otherwise null
0993:             * @see org.kuali.module.gl.service.ScrubberValidator#validateObjectType(org.kuali.module.gl.bo.OriginEntryFull,
0994:             *      org.kuali.module.gl.bo.OriginEntryFull)
0995:             */
0996:            private Message validateObjectType(OriginEntry originEntry,
0997:                    OriginEntry workingEntry) {
0998:                LOG.debug("validateObjectType() started");
0999:
1000:                if (!StringUtils.hasText(originEntry
1001:                        .getFinancialObjectTypeCode())) {
1002:                    // If not specified, use the object type from the object code
1003:                    ObjectCode workingEntryFinancialObject = referenceLookup
1004:                            .get().getFinancialObject(workingEntry);
1005:                    workingEntry
1006:                            .setFinancialObjectTypeCode(workingEntryFinancialObject
1007:                                    .getFinancialObjectTypeCode());
1008:                } else {
1009:                    workingEntry.setFinancialObjectTypeCode(originEntry
1010:                            .getFinancialObjectTypeCode());
1011:                }
1012:
1013:                ObjectType workingEntryObjectType = referenceLookup.get()
1014:                        .getObjectType(workingEntry);
1015:                if (workingEntryObjectType == null) {
1016:                    return new Message(
1017:                            kualiConfigurationService
1018:                                    .getPropertyString(KFSKeyConstants.ERROR_OBJECT_TYPE_NOT_FOUND)
1019:                                    + " ("
1020:                                    + originEntry.getFinancialObjectTypeCode()
1021:                                    + ")", Message.TYPE_FATAL);
1022:                }
1023:                return null;
1024:            }
1025:
1026:            /**
1027:             * Validates the sub object code of the origin entry
1028:             * 
1029:             * @param originEntry the origin entry being scrubbed
1030:             * @param workingEntry the scrubbed version of the origin entry
1031:             * @return a Message if an error was encountered, otherwise null
1032:             */
1033:            private Message validateSubObjectCode(OriginEntry originEntry,
1034:                    OriginEntry workingEntry) {
1035:                LOG.debug("validateFinancialSubObjectCode() started");
1036:
1037:                if (!StringUtils.hasText(originEntry
1038:                        .getFinancialSubObjectCode())) {
1039:                    workingEntry.setFinancialSubObjectCode(KFSConstants
1040:                            .getDashFinancialSubObjectCode());
1041:                    return null;
1042:                }
1043:
1044:                if (!KFSConstants.getDashFinancialSubObjectCode().equals(
1045:                        originEntry.getFinancialSubObjectCode())) {
1046:                    SubObjCd originEntrySubObject = referenceLookup.get()
1047:                            .getFinancialSubObject(originEntry);
1048:                    if (originEntrySubObject != null) {
1049:                        // Exists
1050:                        if (!originEntrySubObject
1051:                                .isFinancialSubObjectActiveIndicator()) {
1052:                            // if NOT active, set it to dashes
1053:                            workingEntry.setFinancialSubObjectCode(KFSConstants
1054:                                    .getDashFinancialSubObjectCode());
1055:                            return null;
1056:                        }
1057:                    } else {
1058:                        // Doesn't exist
1059:                        workingEntry.setFinancialSubObjectCode(KFSConstants
1060:                                .getDashFinancialSubObjectCode());
1061:                        return null;
1062:                    }
1063:                }
1064:                workingEntry.setFinancialSubObjectCode(originEntry
1065:                        .getFinancialSubObjectCode());
1066:                return null;
1067:            }
1068:
1069:            /**
1070:             * Validates the balance type of the origin entry
1071:             * 
1072:             * @param originEntry the origin entry being scrubbed
1073:             * @param workingEntry the scrubbed version of the origin entry
1074:             * @return a Message if an error was encountered, otherwise null
1075:             */
1076:            private Message validateBalanceType(OriginEntry originEntry,
1077:                    OriginEntry workingEntry) {
1078:                LOG.debug("validateBalanceType() started");
1079:
1080:                if (StringUtils.hasText(originEntry
1081:                        .getFinancialBalanceTypeCode())) {
1082:                    // balance type IS NOT empty
1083:                    BalanceTyp originEntryBalanceType = referenceLookup.get()
1084:                            .getBalanceType(originEntry);
1085:                    if (originEntryBalanceType == null) {
1086:                        // balance type IS NOT valid
1087:                        return new Message(
1088:                                kualiConfigurationService
1089:                                        .getPropertyString(KFSKeyConstants.ERROR_BALANCE_TYPE_NOT_FOUND)
1090:                                        + " ("
1091:                                        + originEntry
1092:                                                .getFinancialBalanceTypeCode()
1093:                                        + ")", Message.TYPE_FATAL);
1094:                    } else {
1095:                        // balance type IS valid
1096:                        if (originEntryBalanceType
1097:                                .isFinancialOffsetGenerationIndicator()) {
1098:                            // entry IS an offset
1099:                            if (originEntry.getTransactionLedgerEntryAmount()
1100:                                    .isNegative()) {
1101:                                // it's an INVALID non-budget transaction
1102:                                return new Message(
1103:                                        kualiConfigurationService
1104:                                                .getPropertyString(KFSKeyConstants.ERROR_TRANS_CANNOT_BE_NEGATIVE_IF_OFFSET),
1105:                                        Message.TYPE_FATAL);
1106:                            } else {
1107:                                // it's a VALID non-budget transaction
1108:                                if (!originEntry.isCredit()
1109:                                        && !originEntry.isDebit()) { // entries requiring an offset must be either a
1110:                                    // debit or a credit
1111:                                    return new Message(
1112:                                            kualiConfigurationService
1113:                                                    .getPropertyString(KFSKeyConstants.ERROR_DC_INDICATOR_MUST_BE_D_OR_C)
1114:                                                    + " ("
1115:                                                    + originEntry
1116:                                                            .getTransactionDebitCreditCode()
1117:                                                    + ")", Message.TYPE_FATAL);
1118:                                } else {
1119:                                    workingEntry
1120:                                            .setFinancialBalanceTypeCode(originEntry
1121:                                                    .getFinancialBalanceTypeCode());
1122:                                }
1123:                            }
1124:                        } else {
1125:                            // entry IS NOT an offset, means it's a budget transaction
1126:                            if (StringUtils.hasText(originEntry
1127:                                    .getTransactionDebitCreditCode())) {
1128:                                return new Message(
1129:                                        kualiConfigurationService
1130:                                                .getPropertyString(KFSKeyConstants.ERROR_DC_INDICATOR_MUST_BE_EMPTY)
1131:                                                + " ("
1132:                                                + originEntry
1133:                                                        .getTransactionDebitCreditCode()
1134:                                                + ")", Message.TYPE_FATAL);
1135:                            } else {
1136:                                if (originEntry.isCredit()
1137:                                        || originEntry.isDebit()) {
1138:                                    // budget transactions must be neither debit nor credit
1139:                                    return new Message(
1140:                                            kualiConfigurationService
1141:                                                    .getPropertyString(KFSKeyConstants.ERROR_DC_INDICATOR_MUST_BE_NEITHER_D_NOR_C)
1142:                                                    + " ("
1143:                                                    + originEntry
1144:                                                            .getTransactionDebitCreditCode()
1145:                                                    + ")", Message.TYPE_FATAL);
1146:                                } else {
1147:                                    // it's a valid budget transaction
1148:                                    workingEntry
1149:                                            .setFinancialBalanceTypeCode(originEntry
1150:                                                    .getFinancialBalanceTypeCode());
1151:                                }
1152:                            }
1153:                        }
1154:                    }
1155:                } else {
1156:                    // balance type IS empty. We can't set it if the year isn't set
1157:                    Options workingEntryOption = referenceLookup.get()
1158:                            .getOption(workingEntry);
1159:                    if (workingEntryOption != null) {
1160:                        workingEntry
1161:                                .setFinancialBalanceTypeCode(workingEntryOption
1162:                                        .getActualFinancialBalanceTypeCd());
1163:                    } else {
1164:                        return new Message(
1165:                                "Unable to set balance type code when year is unknown: "
1166:                                        + workingEntry
1167:                                                .getUniversityFiscalYear(),
1168:                                Message.TYPE_FATAL);
1169:                    }
1170:                }
1171:                return null;
1172:            }
1173:
1174:            /**
1175:             * Validates the period code of the origin entry
1176:             * 
1177:             * @param originEntry the origin entry being scrubbed
1178:             * @param workingEntry the scrubbed version of the origin entry
1179:             * @param universityRunDate the university date when this scrubber process is being run
1180:             * @return a Message if an error was encountered, otherwise null
1181:             */
1182:            private Message validateUniversityFiscalPeriodCode(
1183:                    OriginEntry originEntry, OriginEntry workingEntry,
1184:                    UniversityDate universityRunDate) {
1185:                LOG.debug("validateUniversityFiscalPeriodCode() started");
1186:
1187:                if (!StringUtils.hasText(originEntry
1188:                        .getUniversityFiscalPeriodCode())) {
1189:                    if (universityRunDate.getAccountingPeriod().isOpen()) {
1190:                        workingEntry
1191:                                .setUniversityFiscalPeriodCode(universityRunDate
1192:                                        .getUniversityFiscalAccountingPeriod());
1193:                        workingEntry.setUniversityFiscalYear(universityRunDate
1194:                                .getUniversityFiscalYear());
1195:                    } else {
1196:                        return new Message(
1197:                                kualiConfigurationService
1198:                                        .getPropertyString(KFSKeyConstants.ERROR_ACCOUNTING_PERIOD_CLOSED)
1199:                                        + " (year "
1200:                                        + universityRunDate
1201:                                                .getUniversityFiscalYear()
1202:                                        + ", period "
1203:                                        + universityRunDate
1204:                                                .getUniversityFiscalAccountingPeriod()
1205:                                        + ")", Message.TYPE_FATAL);
1206:                    }
1207:
1208:                } else {
1209:                    AccountingPeriod originEntryAccountingPeriod = referenceLookup
1210:                            .get().getAccountingPeriod(originEntry);
1211:                    if (originEntryAccountingPeriod == null) {
1212:                        return new Message(
1213:                                kualiConfigurationService
1214:                                        .getPropertyString(KFSKeyConstants.ERROR_ACCOUNTING_PERIOD_NOT_FOUND)
1215:                                        + " ("
1216:                                        + originEntry
1217:                                                .getUniversityFiscalPeriodCode()
1218:                                        + ")", Message.TYPE_FATAL);
1219:                    } else if (KFSConstants.ACCOUNTING_PERIOD_STATUS_CLOSED
1220:                            .equals(originEntryAccountingPeriod
1221:                                    .getUniversityFiscalPeriodStatusCode())) {
1222:                        // KULLAB-510
1223:                        // Scrubber accepts closed fiscal periods for certain Balance Types(A2)
1224:                        String bypassBalanceType = SpringContext
1225:                                .getBean(ParameterService.class)
1226:                                .getParameterValue(
1227:                                        LaborScrubberStep.class,
1228:                                        LaborConstants.Scrubber.CLOSED_FISCAL_PERIOD_BYPASS_BALANCE_TYPES);
1229:                        if (!workingEntry.getFinancialBalanceTypeCode().equals(
1230:                                bypassBalanceType)) {
1231:                            return new Message(
1232:                                    kualiConfigurationService
1233:                                            .getPropertyString(KFSKeyConstants.ERROR_FISCAL_PERIOD_CLOSED)
1234:                                            + " ("
1235:                                            + originEntry
1236:                                                    .getUniversityFiscalPeriodCode()
1237:                                            + ")", Message.TYPE_FATAL);
1238:                        }
1239:                    }
1240:
1241:                    workingEntry.setUniversityFiscalPeriodCode(originEntry
1242:                            .getUniversityFiscalPeriodCode());
1243:                }
1244:
1245:                return null;
1246:            }
1247:
1248:            /**
1249:             * If the encumbrance update code = R, ref doc number must exist, ref doc type must be valid and ref origin code must be valid.
1250:             * If encumbrance update code is not R, and ref doc number is empty, make sure ref doc number, ref doc type and ref origin code
1251:             * are null. If encumbrance update code is not R and the ref doc number has a value, ref doc type must be valid and ref origin
1252:             * code must be valid.
1253:             * 
1254:             * @param originEntry the origin entry to check
1255:             * @param workingEntryInfo the copy of the entry to move valid data into
1256:             * @return a Message if an error was encountered, otherwise null
1257:             */
1258:            private Message validateReferenceDocumentFields(
1259:                    OriginEntry originEntry, OriginEntry workingEntry) {
1260:                LOG.debug("validateReferenceDocument() started");
1261:
1262:                // 3148 of cobol
1263:
1264:                boolean editReference = true;
1265:                if (!StringUtils.hasText(originEntry
1266:                        .getReferenceFinancialDocumentNumber())) {
1267:                    workingEntry.setReferenceFinancialDocumentNumber(null);
1268:                    workingEntry.setReferenceFinancialDocumentTypeCode(null);
1269:                    workingEntry
1270:                            .setReferenceFinancialSystemOriginationCode(null);
1271:
1272:                    if (KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD
1273:                            .equals(originEntry
1274:                                    .getTransactionEncumbranceUpdateCode())) {
1275:                        return new Message(
1276:                                kualiConfigurationService
1277:                                        .getPropertyString(KFSKeyConstants.ERROR_REF_DOC_NOT_BE_SPACE),
1278:                                Message.TYPE_FATAL);
1279:                    }
1280:                } else {
1281:                    workingEntry
1282:                            .setReferenceFinancialDocumentNumber(originEntry
1283:                                    .getReferenceFinancialDocumentNumber());
1284:
1285:                    // Validate reference document type
1286:                    DocumentType originEntryReferenceDocumentType = referenceLookup
1287:                            .get().getReferenceDocumentType(originEntry);
1288:                    if (originEntryReferenceDocumentType != null) {
1289:                        workingEntry
1290:                                .setReferenceFinancialDocumentTypeCode(originEntry
1291:                                        .getReferenceFinancialDocumentTypeCode());
1292:                    } else {
1293:                        return new Message(
1294:                                kualiConfigurationService
1295:                                        .getPropertyString(KFSKeyConstants.ERROR_REFERENCE_DOCUMENT_TYPE_NOT_FOUND)
1296:                                        + " ("
1297:                                        + originEntry
1298:                                                .getReferenceFinancialDocumentTypeCode()
1299:                                        + ")", Message.TYPE_FATAL);
1300:                    }
1301:
1302:                    // Validate reference origin code
1303:                    OriginationCode oc = originationCodeService
1304:                            .getByPrimaryKey(originEntry
1305:                                    .getReferenceFinancialSystemOriginationCode());
1306:                    if (oc != null) {
1307:                        workingEntry
1308:                                .setReferenceFinancialSystemOriginationCode(originEntry
1309:                                        .getReferenceFinancialSystemOriginationCode());
1310:                    } else {
1311:                        return new Message(
1312:                                kualiConfigurationService
1313:                                        .getPropertyString(KFSKeyConstants.ERROR_REFERENCE_ORIGINATION_CODE_NOT_FOUND)
1314:                                        + " ("
1315:                                        + originEntry
1316:                                                .getReferenceFinancialSystemOriginationCode()
1317:                                        + ")", Message.TYPE_FATAL);
1318:                    }
1319:                }
1320:
1321:                BalanceTyp workingEntryBalanceType = referenceLookup.get()
1322:                        .getBalanceType(workingEntry);
1323:                ObjectType workingEntryObjectType = referenceLookup.get()
1324:                        .getObjectType(workingEntry);
1325:                if (workingEntryBalanceType == null
1326:                        || workingEntryObjectType == null) {
1327:                    // We are unable to check this because the balance type or object type is invalid.
1328:                    // It would be nice if we could still validate the entry, but we can't.
1329:                    return null;
1330:                }
1331:
1332:                if (workingEntryBalanceType.isFinBalanceTypeEncumIndicator()
1333:                        && !workingEntryObjectType.isFundBalanceIndicator()) {
1334:                    if ((KFSConstants.ENCUMB_UPDT_DOCUMENT_CD
1335:                            .equals(originEntry
1336:                                    .getTransactionEncumbranceUpdateCode()))
1337:                            || (KFSConstants.ENCUMB_UPDT_NO_ENCUMBRANCE_CD
1338:                                    .equals(originEntry
1339:                                            .getTransactionEncumbranceUpdateCode()))
1340:                            || (KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD
1341:                                    .equals(originEntry
1342:                                            .getTransactionEncumbranceUpdateCode()))) {
1343:                        workingEntry
1344:                                .setTransactionEncumbranceUpdateCode(originEntry
1345:                                        .getTransactionEncumbranceUpdateCode());
1346:                    } else {
1347:                        return new Message(
1348:                                kualiConfigurationService
1349:                                        .getPropertyString(KFSKeyConstants.ERROR_ENC_UPDATE_CODE_NOT_DRN)
1350:                                        + " ("
1351:                                        + originEntry
1352:                                                .getTransactionEncumbranceUpdateCode()
1353:                                        + ")", Message.TYPE_FATAL);
1354:                    }
1355:                } else {
1356:                    workingEntry.setTransactionEncumbranceUpdateCode(null);
1357:                }
1358:                return null;
1359:            }
1360:
1361:            /**
1362:             * Validates the entry's transaction amount
1363:             * 
1364:             * @param originEntry the origin entry being scrubbed
1365:             * @param workingEntry the scrubbed version of the origin entry
1366:             * @return a Message if an error was encountered, otherwise null
1367:             */
1368:            private Message validateTransactionAmount(OriginEntry originEntry,
1369:                    OriginEntry workingEntry) {
1370:                LOG.debug("validateTransactionAmount() started");
1371:
1372:                KualiDecimal amount = originEntry
1373:                        .getTransactionLedgerEntryAmount();
1374:                BalanceTyp originEntryBalanceType = referenceLookup.get()
1375:                        .getBalanceType(originEntry);
1376:                if (originEntryBalanceType == null) {
1377:                    // We can't validate the amount without a balance type code
1378:                    return null;
1379:                }
1380:
1381:                if (originEntryBalanceType
1382:                        .isFinancialOffsetGenerationIndicator()) {
1383:                    if (amount.isPositive() || amount.isZero()) {
1384:                        workingEntry
1385:                                .setTransactionLedgerEntryAmount(originEntry
1386:                                        .getTransactionLedgerEntryAmount());
1387:                    } else {
1388:                        return new Message(
1389:                                kualiConfigurationService
1390:                                        .getPropertyString(KFSKeyConstants.ERROR_NEGATIVE_AMOUNT)
1391:                                        + " (" + amount.toString() + ")",
1392:                                Message.TYPE_FATAL);
1393:                    }
1394:                    if (StringHelper.isEmpty(originEntry
1395:                            .getTransactionDebitCreditCode())) {
1396:                        return new Message(
1397:                                kualiConfigurationService
1398:                                        .getPropertyString(KFSKeyConstants.ERROR_DEBIT_CREDIT_INDICATOR_NEITHER_D_NOR_C)
1399:                                        + " ("
1400:                                        + originEntry
1401:                                                .getTransactionDebitCreditCode()
1402:                                        + ")", Message.TYPE_FATAL);
1403:                    }
1404:                    if (ObjectHelper.isOneOf(originEntry
1405:                            .getTransactionDebitCreditCode(), debitOrCredit)) {
1406:                        workingEntry.setTransactionDebitCreditCode(originEntry
1407:                                .getTransactionDebitCreditCode());
1408:                    } else {
1409:                        return new Message(
1410:                                kualiConfigurationService
1411:                                        .getPropertyString(KFSKeyConstants.ERROR_DEBIT_CREDIT_INDICATOR_NEITHER_D_NOR_C)
1412:                                        + " ("
1413:                                        + originEntry
1414:                                                .getTransactionDebitCreditCode()
1415:                                        + ")", Message.TYPE_FATAL);
1416:                    }
1417:                } else {
1418:                    if ((originEntry.getTransactionDebitCreditCode() == null)
1419:                            || (" ".equals(originEntry
1420:                                    .getTransactionDebitCreditCode()))
1421:                            || ("".equals(originEntry
1422:                                    .getTransactionDebitCreditCode()))) {
1423:                        workingEntry
1424:                                .setTransactionDebitCreditCode(KFSConstants.GL_BUDGET_CODE);
1425:                    } else {
1426:                        return new Message(
1427:                                kualiConfigurationService
1428:                                        .getPropertyString(KFSKeyConstants.ERROR_DEBIT_CREDIT_INDICATOR_MUST_BE_SPACE)
1429:                                        + " ("
1430:                                        + originEntry
1431:                                                .getTransactionDebitCreditCode()
1432:                                        + ")", Message.TYPE_FATAL);
1433:                    }
1434:                }
1435:                return null;
1436:            }
1437:
1438:            /**
1439:             * 
1440:             * This method...
1441:             * @param offsetAccountExpirationTime
1442:             * @param runCalendar
1443:             * @return
1444:             */
1445:            private boolean isExpired(long offsetAccountExpirationTime,
1446:                    Calendar runCalendar) {
1447:
1448:                Calendar expirationDate = Calendar.getInstance();
1449:                expirationDate.setTimeInMillis(offsetAccountExpirationTime);
1450:
1451:                int expirationYear = expirationDate.get(Calendar.YEAR);
1452:                int runYear = runCalendar.get(Calendar.YEAR);
1453:                int expirationDoy = expirationDate.get(Calendar.DAY_OF_YEAR);
1454:                int runDoy = runCalendar.get(Calendar.DAY_OF_YEAR);
1455:
1456:                return (expirationYear < runYear)
1457:                        || (expirationYear == runYear && expirationDoy < runDoy);
1458:            }
1459:
1460:            public void setUniversityDateDao(UniversityDateDao udd) {
1461:                universityDateDao = udd;
1462:            }
1463:
1464:            public void setKualiConfigurationService(
1465:                    KualiConfigurationService service) {
1466:                kualiConfigurationService = service;
1467:            }
1468:
1469:            public void setPersistenceService(PersistenceService ps) {
1470:                persistenceService = ps;
1471:            }
1472:
1473:            public void setAccountService(AccountService as) {
1474:                accountService = as;
1475:            }
1476:
1477:            public void setOriginationCodeService(OriginationCodeService ocs) {
1478:                originationCodeService = ocs;
1479:            }
1480:
1481:            public void setPersistenceStructureService(
1482:                    PersistenceStructureService persistenceStructureService) {
1483:                this .persistenceStructureService = persistenceStructureService;
1484:            }
1485:
1486:            /**
1487:             * Sets a service that allows origin entries to retrieve references
1488:             * @param the implementation of OriginEntryLookupService to set
1489:             * @see org.kuali.module.gl.service.ScrubberValidator#setReferenceLookup(org.kuali.module.gl.service.OriginEntryLookupService)
1490:             */
1491:            public void setReferenceLookup(
1492:                    OriginEntryLookupService originEntryLookupService) {
1493:                this .referenceLookup.set(originEntryLookupService);
1494:            }
1495:
1496:            public void setParameterService(ParameterService parameterService) {
1497:                this .parameterService = parameterService;
1498:            }
1499:
1500:            public void setBalanceTypService(BalanceTypService balanceTypService) {
1501:                this.balanceTypService = balanceTypService;
1502:            }
1503:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.