001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.module.financial.rules;
017:
018: import static org.kuali.kfs.KFSConstants.AMOUNT_PROPERTY_NAME;
019: import static org.kuali.kfs.KFSConstants.BALANCE_TYPE_BASE_BUDGET;
020: import static org.kuali.kfs.KFSConstants.BALANCE_TYPE_BUDGET_STATISTICS;
021: import static org.kuali.kfs.KFSConstants.BALANCE_TYPE_CURRENT_BUDGET;
022: import static org.kuali.kfs.KFSConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE;
023: import static org.kuali.kfs.KFSConstants.BALANCE_TYPE_MONTHLY_BUDGET;
024: import static org.kuali.kfs.KFSConstants.BLANK_SPACE;
025: import static org.kuali.kfs.KFSConstants.CREDIT_AMOUNT_PROPERTY_NAME;
026: import static org.kuali.kfs.KFSConstants.DEBIT_AMOUNT_PROPERTY_NAME;
027: import static org.kuali.kfs.KFSConstants.GENERIC_CODE_PROPERTY_NAME;
028: import static org.kuali.kfs.KFSConstants.GL_DEBIT_CODE;
029: import static org.kuali.kfs.KFSConstants.JOURNAL_LINE_HELPER_PROPERTY_NAME;
030: import static org.kuali.kfs.KFSConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME;
031: import static org.kuali.kfs.KFSConstants.OBJECT_TYPE_CODE_PROPERTY_NAME;
032: import static org.kuali.kfs.KFSConstants.SQUARE_BRACKET_LEFT;
033: import static org.kuali.kfs.KFSConstants.SQUARE_BRACKET_RIGHT;
034: import static org.kuali.kfs.KFSConstants.VOUCHER_LINE_HELPER_CREDIT_PROPERTY_NAME;
035: import static org.kuali.kfs.KFSConstants.VOUCHER_LINE_HELPER_DEBIT_PROPERTY_NAME;
036: import static org.kuali.kfs.KFSKeyConstants.ERROR_DOCUMENT_SINGLE_SECTION_NO_ACCOUNTING_LINES;
037: import static org.kuali.kfs.KFSKeyConstants.ERROR_REQUIRED;
038: import static org.kuali.kfs.KFSKeyConstants.ERROR_ZERO_AMOUNT;
039: import static org.kuali.kfs.KFSKeyConstants.ERROR_ZERO_OR_NEGATIVE_AMOUNT;
040: import static org.kuali.kfs.KFSKeyConstants.JournalVoucher.ERROR_NEGATIVE_NON_BUDGET_AMOUNTS;
041: import static org.kuali.kfs.KFSPropertyConstants.ACCOUNTING_PERIOD;
042: import static org.kuali.kfs.KFSPropertyConstants.BALANCE_TYPE;
043: import static org.kuali.kfs.KFSPropertyConstants.BALANCE_TYPE_CODE;
044: import static org.kuali.kfs.KFSPropertyConstants.REFERENCE_NUMBER;
045: import static org.kuali.kfs.KFSPropertyConstants.REFERENCE_ORIGIN_CODE;
046: import static org.kuali.kfs.KFSPropertyConstants.REFERENCE_TYPE_CODE;
047: import static org.kuali.kfs.KFSPropertyConstants.REVERSAL_DATE;
048: import static org.kuali.kfs.KFSPropertyConstants.SELECTED_ACCOUNTING_PERIOD;
049: import static org.kuali.kfs.rules.AccountingDocumentRuleBaseConstants.ERROR_PATH.DOCUMENT_ERROR_PREFIX;
050:
051: import org.apache.commons.lang.StringUtils;
052: import org.kuali.core.datadictionary.BusinessObjectEntry;
053: import org.kuali.core.document.Document;
054: import org.kuali.core.service.DataDictionaryService;
055: import org.kuali.core.util.GeneralLedgerPendingEntrySequenceHelper;
056: import org.kuali.core.util.GlobalVariables;
057: import org.kuali.core.util.KualiDecimal;
058: import org.kuali.kfs.bo.AccountingLine;
059: import org.kuali.kfs.bo.GeneralLedgerPendingEntry;
060: import org.kuali.kfs.context.SpringContext;
061: import org.kuali.kfs.document.AccountingDocument;
062: import org.kuali.kfs.rules.AccountingDocumentRuleBase;
063: import org.kuali.kfs.rules.AccountingDocumentRuleUtil;
064: import org.kuali.kfs.service.OptionsService;
065: import org.kuali.module.chart.bo.AccountingPeriod;
066: import org.kuali.module.chart.bo.ObjectType;
067: import org.kuali.module.chart.bo.codes.BalanceTyp;
068: import org.kuali.module.financial.bo.VoucherSourceAccountingLine;
069: import org.kuali.module.financial.document.JournalVoucherDocument;
070:
071: /**
072: * This class holds document specific business rules for the Journal Voucher. It overrides methods in the base rule class to apply
073: * specific checks.
074: */
075: public class JournalVoucherDocumentRule extends
076: AccountingDocumentRuleBase {
077:
078: /**
079: * Constructs a JournalVoucherDocumentRule instance.
080: */
081: public JournalVoucherDocumentRule() {
082: }
083:
084: /**
085: * Performs additional Journal Voucher specific checks every time an accounting line is added. These include
086: * checking to make sure that encumbrance reference fields are filled in under certain circumstances.
087: *
088: * @param financialDocument The document the new line is being added to.
089: * @param accountingLine The new accounting line being added.
090: * @return True if the business rules all pass, false otherwise.
091: *
092: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#processCustomAddAccountingLineBusinessRules(org.kuali.core.document.FinancialDocument,
093: * org.kuali.core.bo.AccountingLine)
094: */
095: @Override
096: public boolean processCustomAddAccountingLineBusinessRules(
097: AccountingDocument document, AccountingLine accountingLine) {
098: return super .processCustomAddAccountingLineBusinessRules(
099: document, accountingLine)
100: && validateAccountingLine(accountingLine);
101: }
102:
103: /**
104: * This method performs business rule checks on the accounting line being provided to ensure the accounting line
105: * is valid and appropriate for the document.
106: *
107: * @param transactionalDocument The document associated with the accounting line being validated.
108: * @param accountingLine The accounting line being validated.
109: * @return True if the business rules all pass, false otherwise.
110: *
111: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#processCustomReviewAccountingLineBusinessRules(org.kuali.core.document.FinancialDocument,
112: * org.kuali.core.bo.AccountingLine)
113: */
114: @Override
115: public boolean processCustomReviewAccountingLineBusinessRules(
116: AccountingDocument document, AccountingLine accountingLine) {
117: return super .processCustomReviewAccountingLineBusinessRules(
118: document, accountingLine)
119: && validateAccountingLine(accountingLine);
120: }
121:
122: /**
123: * This method performs business rule checks on the accounting line being updated to the document to ensure the accounting line
124: * is valid and appropriate for the document. Performs additional Journal Voucher specific checks every time an accounting
125: * line is updated.
126: *
127: * @param transactionalDocument The document the accounting line being updated resides within.
128: * @param accountingLine The original accounting line.
129: * @param updatedAccoutingLine The updated version of the accounting line.
130: * @return True if the business rules all pass for the update, false otherwise.
131: *
132: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#processCustomUpdateAccountingLineBusinessRules(org.kuali.core.document.FinancialDocument,
133: * org.kuali.core.bo.AccountingLine, org.kuali.core.bo.AccountingLine)
134: */
135: @Override
136: public boolean processCustomUpdateAccountingLineBusinessRules(
137: AccountingDocument financialDocument,
138: AccountingLine originalAccountingLine,
139: AccountingLine updatedAccountingLine) {
140: return super .processCustomUpdateAccountingLineBusinessRules(
141: financialDocument, originalAccountingLine,
142: updatedAccountingLine)
143: && validateAccountingLine(updatedAccountingLine);
144: }
145:
146: /**
147: * Implements Journal Voucher specific accountingLine validity checks. These include checking to make sure that encumbrance
148: * reference fields are filled in under certain circumstances.
149: *
150: * @param accountingLine The accounting line to be validated.
151: * @return True if the given accountingLine is valid, false otherwise.
152: *
153: * @see #isExternalEncumbranceSpecificBusinessRulesValid(AccountingLine)
154: */
155: boolean validateAccountingLine(AccountingLine accountingLine) {
156: // validate business rules specific to having the balance type set to EXTERNAL ENCUMBRANCE
157: return isExternalEncumbranceSpecificBusinessRulesValid(accountingLine);
158: }
159:
160: /**
161: * Performs Journal Voucher document specific save rules. These include checking to make sure that a valid and
162: * active balance type is chosen and that a valid open accounting period is chosen.
163: *
164: * @param document The document being saved.
165: * @return True if the document being saved passed all the business rules, false otherwise.
166: *
167: * @see org.kuali.core.rule.DocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.core.document.Document)
168: */
169: @Override
170: public boolean processCustomSaveDocumentBusinessRules(
171: Document document) {
172: JournalVoucherDocument jvDoc = (JournalVoucherDocument) document;
173:
174: boolean valid = true;
175:
176: // check the selected balance type
177: jvDoc.refreshReferenceObject(BALANCE_TYPE);
178: BalanceTyp balanceType = jvDoc.getBalanceType();
179: valid &= AccountingDocumentRuleUtil.isValidBalanceType(
180: balanceType, JournalVoucherDocument.class,
181: BALANCE_TYPE_CODE, DOCUMENT_ERROR_PREFIX
182: + BALANCE_TYPE_CODE);
183:
184: // check the selected accounting period
185: jvDoc.refreshReferenceObject(ACCOUNTING_PERIOD);
186: AccountingPeriod accountingPeriod = jvDoc.getAccountingPeriod();
187: // KFSPropertyConstants.SELECTED_ACCOUNTING_PERIOD is on JournalVoucherForm, not JournalVoucherDocument
188: valid &= AccountingDocumentRuleUtil
189: .isValidOpenAccountingPeriod(accountingPeriod,
190: JournalVoucherDocument.class,
191: ACCOUNTING_PERIOD, DOCUMENT_ERROR_PREFIX
192: + SELECTED_ACCOUNTING_PERIOD);
193:
194: // check the chosen reversal date, only if they entered a value
195: if (null != jvDoc.getReversalDate()) {
196: java.sql.Date reversalDate = jvDoc.getReversalDate();
197: valid &= AccountingDocumentRuleUtil
198: .isValidReversalDate(reversalDate,
199: DOCUMENT_ERROR_PREFIX + REVERSAL_DATE);
200: }
201:
202: return valid;
203: }
204:
205: /**
206: *
207: * @see org.kuali.kfs.rules.AccountingDocumentRuleBase#getGeneralLedgerPendingEntryAmountForAccountingLine(org.kuali.kfs.bo.AccountingLine)
208: */
209: @Override
210: protected KualiDecimal getGeneralLedgerPendingEntryAmountForAccountingLine(
211: AccountingLine accountingLine) {
212: LOG
213: .debug("getGeneralLedgerPendingEntryAmountForAccountingLine(AccountingLine) - start");
214: KualiDecimal returnKualiDecimal;
215:
216: String budgetCodes = SpringContext
217: .getBean(OptionsService.class).getOptions(
218: accountingLine.getPostingYear())
219: .getBudgetCheckingBalanceTypeCd();
220: if (budgetCodes.contains(accountingLine.getBalanceTypeCode())) {
221: returnKualiDecimal = accountingLine.getAmount();
222: } else {
223: returnKualiDecimal = accountingLine.getAmount().abs();
224: }
225: LOG
226: .debug("getGeneralLedgerPendingEntryAmountForAccountingLine(AccountingLine) - end");
227: return returnKualiDecimal;
228: }
229:
230: /**
231: * This method sets attributes on the explicitly general ledger pending entry specific to JournalVoucher documents.
232: * This includes setting the accounting period code and year (as selected by the user, the object type code,
233: * the balance type code, the debit/credit code, the encumbrance update code and the reversal date.
234: *
235: * @param financialDocument The document which contains the general ledger pending entry being modified.
236: * @param accountingLine The accounting line the explicit entry was generated from.
237: * @param explicitEntry The explicit entry being updated.
238: *
239: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.core.document.FinancialDocument,
240: * org.kuali.core.bo.AccountingLine, org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
241: */
242: protected void customizeExplicitGeneralLedgerPendingEntry(
243: AccountingDocument financialDocument,
244: AccountingLine accountingLine,
245: GeneralLedgerPendingEntry explicitEntry) {
246: JournalVoucherDocument jvDoc = (JournalVoucherDocument) financialDocument;
247:
248: // set the appropriate accounting period values according to the values chosen by the user
249: explicitEntry.setUniversityFiscalPeriodCode(jvDoc
250: .getPostingPeriodCode());
251: explicitEntry.setUniversityFiscalYear(jvDoc.getPostingYear());
252:
253: // set the object type code directly from what was entered in the interface
254: explicitEntry.setFinancialObjectTypeCode(accountingLine
255: .getObjectTypeCode());
256:
257: // set the balance type code directly from what was entered in the interface
258: explicitEntry.setFinancialBalanceTypeCode(accountingLine
259: .getBalanceTypeCode());
260:
261: // set the debit/credit code appropriately
262: jvDoc.refreshReferenceObject(BALANCE_TYPE);
263: if (jvDoc.getBalanceType()
264: .isFinancialOffsetGenerationIndicator()) {
265: explicitEntry.setTransactionDebitCreditCode(getEntryValue(
266: accountingLine.getDebitCreditCode(), BLANK_SPACE));
267: } else {
268: explicitEntry.setTransactionDebitCreditCode(BLANK_SPACE);
269: }
270:
271: // set the encumbrance update code
272: explicitEntry
273: .setTransactionEncumbranceUpdateCode(getEntryValue(
274: accountingLine.getEncumbranceUpdateCode(),
275: BLANK_SPACE));
276:
277: // set the reversal date to what what specified at the document level
278: if (jvDoc.getReversalDate() != null) {
279: explicitEntry.setFinancialDocumentReversalDate(jvDoc
280: .getReversalDate());
281: }
282: }
283:
284: /**
285: * A Journal Voucher document doesn't generate an offset entry at all, so this method overrides to do nothing more than return
286: * true. This will be called by the parent's processGeneralLedgerPendingEntries method.
287: *
288: * @param financialDocument The document the offset will be stored within.
289: * @param sequenceHelper The sequence object to be modified.
290: * @param accountingLineToCopy The accounting line the offset is generated for.
291: * @param explicitEntry The explicit entry the offset will be generated for.
292: * @param offsetEntry The offset entry to be processed.
293: * @return This method always returns true.
294: *
295: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#processOffsetGeneralLedgerPendingEntry(org.kuali.core.document.FinancialDocument,
296: * org.kuali.core.util.GeneralLedgerPendingEntrySequenceHelper, org.kuali.core.bo.AccountingLine,
297: * org.kuali.module.gl.bo.GeneralLedgerPendingEntry, org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
298: */
299: @Override
300: protected boolean processOffsetGeneralLedgerPendingEntry(
301: AccountingDocument financialDocument,
302: GeneralLedgerPendingEntrySequenceHelper sequenceHelper,
303: AccountingLine accountingLineCopy,
304: GeneralLedgerPendingEntry explicitEntry,
305: GeneralLedgerPendingEntry offsetEntry) {
306: sequenceHelper.decrement(); // the parent already increments; assuming that all documents have offset entries
307: return true;
308: }
309:
310: // Overridden Helper Methods
311: /**
312: * Overrides the parent to return true, because Journal Voucher documents do not have to balance in order to be submitted for
313: * routing.
314: *
315: * @param financialDocument The document being validated.
316: * @return True if the balance of the document is valid, false otherwise.
317: */
318: @Override
319: protected boolean isDocumentBalanceValid(
320: AccountingDocument financialDocument) {
321: return true;
322: }
323:
324: /**
325: * Accounting lines for Journal Vouchers can be positive or negative, just not "$0.00".
326: *
327: * Additionally, accounting lines cannot have negative dollar amounts if the balance type of the
328: * journal voucher allows for general ledger pending entry offset generation or the balance type
329: * is not a budget type code.
330: *
331: * @param document The document when contains the accounting line being validated.
332: * @param acocuntingLine The accounting line to be validated.
333: * @return True if the accounting line amount is valid, false otherwise.
334: *
335: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isAmountValid(org.kuali.core.document.FinancialDocument,
336: * org.kuali.core.bo.AccountingLine)
337: */
338: @Override
339: public boolean isAmountValid(AccountingDocument document,
340: AccountingLine accountingLine) {
341: KualiDecimal amount = accountingLine.getAmount();
342:
343: JournalVoucherDocument jvDoc = (JournalVoucherDocument) document;
344: jvDoc.refreshReferenceObject(BALANCE_TYPE);
345:
346: if (jvDoc.getBalanceType()
347: .isFinancialOffsetGenerationIndicator()) {
348: // check for negative or zero amounts
349: if (amount.isZero()) { // if 0
350: GlobalVariables
351: .getErrorMap()
352: .putErrorWithoutFullErrorPath(
353: buildErrorMapKeyPathForDebitCreditAmount(true),
354: ERROR_ZERO_OR_NEGATIVE_AMOUNT,
355: "an accounting line");
356: GlobalVariables
357: .getErrorMap()
358: .putErrorWithoutFullErrorPath(
359: buildErrorMapKeyPathForDebitCreditAmount(false),
360: ERROR_ZERO_OR_NEGATIVE_AMOUNT,
361: "an accounting line");
362:
363: return false;
364: } else if (amount.isNegative()) { // entered a negative number
365: String debitCreditCode = accountingLine
366: .getDebitCreditCode();
367: if (StringUtils.isNotBlank(debitCreditCode)
368: && GL_DEBIT_CODE.equals(debitCreditCode)) {
369: GlobalVariables
370: .getErrorMap()
371: .putErrorWithoutFullErrorPath(
372: buildErrorMapKeyPathForDebitCreditAmount(true),
373: ERROR_ZERO_OR_NEGATIVE_AMOUNT,
374: "an accounting line");
375: } else {
376: GlobalVariables
377: .getErrorMap()
378: .putErrorWithoutFullErrorPath(
379: buildErrorMapKeyPathForDebitCreditAmount(false),
380: ERROR_ZERO_OR_NEGATIVE_AMOUNT,
381: "an accounting line");
382: }
383:
384: return false;
385: }
386: } else {
387: // Check for zero amounts
388: if (amount.isZero()) { // amount == 0
389: GlobalVariables.getErrorMap().putError(
390: AMOUNT_PROPERTY_NAME, ERROR_ZERO_AMOUNT,
391: "an accounting line");
392: return false;
393: } else if (amount.isNegative()) {
394: if (!accountingLine.getBalanceTypeCode().equals(
395: BALANCE_TYPE_BASE_BUDGET)
396: && !accountingLine.getBalanceTypeCode().equals(
397: BALANCE_TYPE_CURRENT_BUDGET)
398: && !accountingLine.getBalanceTypeCode().equals(
399: BALANCE_TYPE_MONTHLY_BUDGET)
400: && !accountingLine.getBalanceTypeCode().equals(
401: BALANCE_TYPE_BUDGET_STATISTICS)) {
402: GlobalVariables.getErrorMap().putError(
403: AMOUNT_PROPERTY_NAME,
404: ERROR_NEGATIVE_NON_BUDGET_AMOUNTS);
405: }
406: }
407: }
408:
409: return true;
410: }
411:
412: /**
413: * This method looks at the current full key path that exists in the ErrorMap structure to determine how to build
414: * the error map for the special journal voucher credit and debit fields since they don't conform to the standard
415: * pattern of accounting lines.
416: *
417: * The error map key path is also dependent on whether or not the accounting line containing an error is a new
418: * accounting line or an existing line that is being updated. This determination is made by searching for
419: * NEW_SOURCE_ACCT_LINE_PROPERTY_NAME in the error path of the global error map.
420: *
421: * @param isDebit Identifies whether or not the line we are returning an error path for is a debit accounting line or not.
422: * @return The full error map key path for the appropriate amount type.
423: */
424: private String buildErrorMapKeyPathForDebitCreditAmount(
425: boolean isDebit) {
426: // determine if we are looking at a new line add or an update
427: boolean isNewLineAdd = GlobalVariables.getErrorMap()
428: .getErrorPath().contains(
429: NEW_SOURCE_ACCT_LINE_PROPERTY_NAME);
430: isNewLineAdd |= GlobalVariables.getErrorMap().getErrorPath()
431: .contains(NEW_SOURCE_ACCT_LINE_PROPERTY_NAME);
432:
433: if (isNewLineAdd) {
434: if (isDebit) {
435: return DEBIT_AMOUNT_PROPERTY_NAME;
436: } else {
437: return CREDIT_AMOUNT_PROPERTY_NAME;
438: }
439: } else {
440: String index = StringUtils.substringBetween(GlobalVariables
441: .getErrorMap().getKeyPath("", true),
442: SQUARE_BRACKET_LEFT, SQUARE_BRACKET_RIGHT);
443: String indexWithParams = SQUARE_BRACKET_LEFT + index
444: + SQUARE_BRACKET_RIGHT;
445: if (isDebit) {
446: return JOURNAL_LINE_HELPER_PROPERTY_NAME
447: + indexWithParams
448: + VOUCHER_LINE_HELPER_DEBIT_PROPERTY_NAME;
449: } else {
450: return JOURNAL_LINE_HELPER_PROPERTY_NAME
451: + indexWithParams
452: + VOUCHER_LINE_HELPER_CREDIT_PROPERTY_NAME;
453: }
454:
455: }
456:
457: }
458:
459: /**
460: * Overrides the parent to return true, because Journal Voucher documents only use the SourceAccountingLines data structures.
461: * The list that holds TargetAccountingLines should be empty. This will be checked when the document is "routed" or submitted to
462: * post - it's called automatically by the parent's processRouteDocument method.
463: *
464: * @param financialDocument The document containing the target accounting lines being validated.
465: * @return This method always returns true because Journal Vouchers do not contain target accounting lines.
466: *
467: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isTargetAccountingLinesRequiredNumberForRoutingMet(org.kuali.core.document.FinancialDocument)
468: */
469: @Override
470: protected boolean isTargetAccountingLinesRequiredNumberForRoutingMet(
471: AccountingDocument financialDocument) {
472: return true;
473: }
474:
475: /**
476: * This method will check to make sure that the required number of source accounting lines for routing, exist in the document.
477: * The Journal Voucher only has one set of accounting lines; therefore, we need to use a different message for this.
478: *
479: * @param financialDocument The document containing the source accounting lines being validated.
480: * @return True if there is one or more source accounting lines in the given document.
481: *
482: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isSourceAccountingLinesRequiredNumberForRoutingMet(org.kuali.core.document.FinancialDocument)
483: */
484: @Override
485: protected boolean isSourceAccountingLinesRequiredNumberForRoutingMet(
486: AccountingDocument financialDocument) {
487: if (0 == financialDocument.getSourceAccountingLines().size()) {
488: GlobalVariables.getErrorMap().putError(
489: "document.sourceAccountingLines",
490: ERROR_DOCUMENT_SINGLE_SECTION_NO_ACCOUNTING_LINES);
491: return false;
492: } else {
493: return true;
494: }
495: }
496:
497: /**
498: * Overrides the parent to return true, because Journal Voucher documents aren't restricted from using any object code. This is
499: * part of the "save" check that gets done. This method is called automatically by the parent's processSaveDocument method.
500: *
501: * @param documentClass The document type class used to retrieve the rules defining if the object code is allowed.
502: * @param accountingLine The accounting line containing the object code being validated.
503: * @return This method always returns true.
504: *
505: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isObjectCodeAllowed(org.kuali.core.bo.AccountingLine)
506: */
507: @Override
508: public boolean isObjectCodeAllowed(Class documentClass,
509: AccountingLine accountingLine) {
510: return true;
511: }
512:
513: // Other Helper Methods Local To This Class
514: /**
515: * This method checks that values exist in the three reference fields (referenceOriginCode, referenceTypeCode, referenceNumber)
516: * that are required if the balance type is set to EXTERNAL ENCUMBRANCE.
517: *
518: * @param accountingLine The accounting line being validated.
519: * @return True if the fields are filled in, true if the balance type is not EXTERNAL ENCUMBRANCE, false otherwise.
520: */
521: protected boolean isExternalEncumbranceSpecificBusinessRulesValid(
522: AccountingLine accountingLine) {
523: // make sure that the line contains a proper balance type like it should
524: BalanceTyp balanceType = accountingLine.getBalanceTyp();
525: if (!AccountingDocumentRuleUtil.isValidBalanceType(balanceType,
526: GENERIC_CODE_PROPERTY_NAME)) {
527: return false;
528: } else if (BALANCE_TYPE_EXTERNAL_ENCUMBRANCE.equals(balanceType
529: .getCode())) {
530: // now check to make sure that the three extra fields (referenceOriginCode, referenceTypeCode, referenceNumber) have
531: // values in them
532: return isRequiredReferenceFieldsValid(accountingLine);
533: } else {
534: return true;
535: }
536: }
537:
538: /**
539: * This method checks that values exist in the three reference fields that are required if the balance type is set to EXTERNAL
540: * ENCUMBRANCE.
541: *
542: * @param accountingLine The accounting line being validated.
543: * @return True if all of the required external encumbrance reference fields are valid, false otherwise.
544: */
545: protected boolean isRequiredReferenceFieldsValid(
546: AccountingLine accountingLine) {
547: boolean valid = true;
548:
549: BusinessObjectEntry boe = SpringContext.getBean(
550: DataDictionaryService.class).getDataDictionary()
551: .getBusinessObjectEntry(
552: VoucherSourceAccountingLine.class.getName());
553: if (StringUtils
554: .isEmpty(accountingLine.getReferenceOriginCode())) {
555: putRequiredPropertyError(boe, REFERENCE_ORIGIN_CODE);
556: valid = false;
557: }
558: if (StringUtils.isEmpty(accountingLine.getReferenceNumber())) {
559: putRequiredPropertyError(boe, REFERENCE_NUMBER);
560: valid = false;
561: }
562: if (StringUtils.isEmpty(accountingLine.getReferenceTypeCode())) {
563: putRequiredPropertyError(boe, REFERENCE_TYPE_CODE);
564: valid = false;
565: }
566: return valid;
567: }
568:
569: /**
570: * The JV allows any object type b/c it is up to the user to enter it into the interface, but it is required. The existence
571: * check is done for us automatically by the data dictionary validation if a value exists; beforehand so we can assume that any
572: * value in that field is valid.
573: *
574: * @param documentClass The type of document the accounting line is contained within.
575: * @param accountingLine The accounting line the object type code will be retrieved from.
576: * @return True if the object type code exists, false otherwise.
577: *
578: * @see org.kuali.core.rule.AddAccountingLineRule#isObjectTypeAllowed(org.kuali.core.bo.AccountingLine)
579: */
580: @Override
581: public boolean isObjectTypeAllowed(Class documentClass,
582: AccountingLine accountingLine) {
583: String objectTypeCode = accountingLine.getObjectTypeCode();
584: if (StringUtils.isNotBlank(objectTypeCode)) {
585: return true;
586: } else {
587: String label = SpringContext.getBean(
588: DataDictionaryService.class).getDataDictionary()
589: .getBusinessObjectEntry(ObjectType.class.getName())
590: .getAttributeDefinition(GENERIC_CODE_PROPERTY_NAME)
591: .getLabel();
592: GlobalVariables.getErrorMap().putError(
593: OBJECT_TYPE_CODE_PROPERTY_NAME, ERROR_REQUIRED,
594: label);
595: return false;
596: }
597:
598: }
599:
600: /**
601: * The following are credits (return false)
602: * <ol>
603: * <li> (debitCreditCode isNotBlank) && debitCreditCode != 'D'
604: * </ol>
605: *
606: * The following are debits (return true)
607: * <ol>
608: * <li> debitCreditCode == 'D'
609: * <li> debitCreditCode isBlank
610: * </ol>
611: *
612: * @param financialDocument The document which contains the accounting line being analyzed.
613: * @param accountingLine The accounting line which will be analyzed to determine if it is a debit line.
614: * @return True if the accounting line provided is a debit accounting line, false otherwise.
615: * @throws IllegalStateException Thrown by method IsDebitUtiles.isDebitCode()
616: *
617: * @see org.kuali.core.rule.AccountingLineRule#isDebit(org.kuali.core.document.FinancialDocument,
618: * org.kuali.core.bo.AccountingLine)
619: * @see org.kuali.kfs.rules.AccountingDocumentRuleBase.IsDebitUtils#isDebitCode(String)
620: */
621: public boolean isDebit(AccountingDocument financialDocument,
622: AccountingLine accountingLine) throws IllegalStateException {
623: String debitCreditCode = accountingLine.getDebitCreditCode();
624:
625: boolean isDebit = StringUtils.isBlank(debitCreditCode)
626: || IsDebitUtils.isDebitCode(debitCreditCode);
627:
628: return isDebit;
629: }
630:
631: // /**
632: // * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#processSourceAccountingLineSufficientFundsCheckingPreparation(FinancialDocument,
633: // * org.kuali.core.bo.SourceAccountingLine)
634: // */
635: // @Override
636: // protected SufficientFundsItem processSourceAccountingLineSufficientFundsCheckingPreparation(FinancialDocument
637: // financialDocument, SourceAccountingLine sourceAccountingLine) {
638: // SufficientFundsItem item = null;
639: // String balanceTypeCode = ((JournalVoucherDocument) financialDocument).getBalanceTypeCode();
640: // // fp_dvj:lp_create_ple.10-1...11-1
641: // if (StringUtils.equals(BALANCE_TYPE_ACTUAL, balanceTypeCode) || StringUtils.equals(BALANCE_TYPE_CURRENT_BUDGET,
642: // balanceTypeCode)) {
643: //
644: // String financialObjectCode = sourceAccountingLine.getFinancialObjectCode();
645: // String accountSufficientFundsCode = sourceAccountingLine.getAccount().getAccountSufficientFundsCode();
646: //
647: //
648: // // fi_djv:lp_proc_jrnl_ln.37-1
649: // String debitCreditCode = null;
650: //
651: // // fi_djv:lp_proc_jrnl_ln.39-2...51-2
652: // if (StringUtils.equals(accountSufficientFundsCode, SF_TYPE_CASH_AT_ACCOUNT) && StringUtils.equals(financialObjectCode,
653: // sourceAccountingLine.getChart().getFinancialCashObjectCode())) {
654: // // use debit credit code
655: // debitCreditCode = sourceAccountingLine.getDebitCreditCode();
656: // }
657: // else if (!StringUtils.equals(accountSufficientFundsCode, SF_TYPE_CASH_AT_ACCOUNT)) {
658: // // fi_djv:lp+proc_jrnl_ln.39-2...43-2
659: // if (StringUtils.equals(sourceAccountingLine.getDebitCreditCode(), GL_DEBIT_CODE)) {
660: // debitCreditCode = GL_CREDIT_CODE;
661: // }
662: // else {
663: // debitCreditCode = GL_DEBIT_CODE;
664: // }
665: // }
666: // if (StringUtils.isNotBlank(debitCreditCode)) {
667: //
668: // String chartOfAccountsCode = sourceAccountingLine.getChartOfAccountsCode();
669: // String accountNumber = sourceAccountingLine.getAccountNumber();
670: // String financialObjectLevelCode = sourceAccountingLine.getObjectCode().getFinancialObjectLevelCode();
671: // Integer fiscalYear = sourceAccountingLine.getPostingYear();
672: // KualiDecimal lineAmount = sourceAccountingLine.getAmount();
673: // String financialObjectTypeCode = sourceAccountingLine.getObjectTypeCode();
674: // String sufficientFundsObjectCode =
675: // SpringContext.getBean(SufficientFundsService.class).getSufficientFundsObjectCode(sourceAccountingLine.getObjectCode(),accountSufficientFundsCode);
676: //
677: // item = buildSufficentFundsItem(accountNumber, accountSufficientFundsCode, lineAmount, chartOfAccountsCode,
678: // sufficientFundsObjectCode, debitCreditCode, financialObjectCode, financialObjectLevelCode, fiscalYear,
679: // financialObjectTypeCode);
680: // }
681: // }
682: //
683: // return item;
684: // }
685: //
686: // /**
687: // *
688: // * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#processTargetAccountingLineSufficientFundsCheckingPreparation(FinancialDocument,
689: // * org.kuali.core.bo.TargetAccountingLine)
690: // */
691: // @Override
692: // protected SufficientFundsItem processTargetAccountingLineSufficientFundsCheckingPreparation(FinancialDocument
693: // financialDocument, TargetAccountingLine targetAccountingLine) {
694: // if (targetAccountingLine != null) {
695: //
696: // throw new IllegalArgumentException("JV document doesn't have target accounting lines. This method should have never been
697: // entered");
698: // }
699: // return null;
700: // }
701: }
|