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: }
|