001/*
002 * Copyright 2005-2006 The Kuali Foundation
003 * 
004 * Licensed under the Educational Community License, Version 2.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/ecl2.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 */
016package org.kuali.ole.fp.document;
017
018import static org.kuali.ole.sys.OLEConstants.BALANCE_TYPE_ACTUAL;
019
020import org.kuali.ole.sys.OLEConstants;
021import org.kuali.ole.sys.businessobject.AccountingLine;
022import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
023import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
024import org.kuali.ole.sys.businessobject.SystemOptions;
025import org.kuali.ole.sys.context.SpringContext;
026import org.kuali.ole.sys.document.AccountingDocumentBase;
027import org.kuali.ole.sys.document.AmountTotaling;
028import org.kuali.ole.sys.document.Correctable;
029import org.kuali.ole.sys.document.service.AccountingDocumentRuleHelperService;
030import org.kuali.ole.sys.document.service.DebitDeterminerService;
031import org.kuali.ole.sys.service.OptionsService;
032import org.kuali.rice.krad.document.Copyable;
033
034/**
035 * The Transfer of Funds (TF) document is used to transfer funds (cash) between accounts. There are two kinds of transfer
036 * transactions, mandatory and non-mandatory. Mandatory transfers are required to meet contractual agreements. Specific object codes
037 * are used to identify these transactions. Examples of these are: moving dedicated student fees to the retirement of indebtedness
038 * fund group for principal and interest payments on bonds. Non-mandatory transfers are allocations of unrestricted cash between
039 * fund groups which are not required either by the terms of a loan or by other external agreements. These transfers are the most
040 * commonly used throughout the university.
041 */
042public class TransferOfFundsDocument extends AccountingDocumentBase implements Copyable, Correctable, AmountTotaling {
043    protected static final long serialVersionUID = -3871133713027969492L;
044
045    /**
046     * Initializes the array lists and some basic info.
047     */
048    public TransferOfFundsDocument() {
049        super();
050    }
051
052    /**
053     * Overrides the base implementation to return "From".
054     * 
055     * @see org.kuali.ole.sys.document.AccountingDocument#getSourceAccountingLinesSectionTitle()
056     */
057    public String getSourceAccountingLinesSectionTitle() {
058        return OLEConstants.FROM;
059    }
060
061    /**
062     * Overrides the base implementation to return "To".
063     * 
064     * @see org.kuali.ole.sys.document.AccountingDocument#getTargetAccountingLinesSectionTitle()
065     */
066    public String getTargetAccountingLinesSectionTitle() {
067        return OLEConstants.TO;
068    }
069    
070    /**
071     * Set attributes of an offset pending entry according to rules specific to TransferOfFundsDocument.  The current rules
072     * require setting the balance type code to 'actual'.
073     * 
074     * @param financialDocument The accounting document containing the general ledger pending entries being customized.
075     * @param accountingLine The accounting line the explicit general ledger pending entry was generated from.
076     * @param explicitEntry The explicit general ledger pending entry the offset entry is generated for.
077     * @param offsetEntry The offset general ledger pending entry being customized.
078     * @return This method always returns true.
079     * 
080     * @see org.kuali.ole.sys.document.validation.impl.AccountingDocumentRuleBase#customizeOffsetGeneralLedgerPendingEntry(org.kuali.rice.krad.document.FinancialDocument,
081     *      org.kuali.rice.krad.bo.AccountingLine, org.kuali.module.gl.bo.GeneralLedgerPendingEntry,
082     *      org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
083     */
084    @Override
085    public boolean customizeOffsetGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail accountingLine, GeneralLedgerPendingEntry explicitEntry, GeneralLedgerPendingEntry offsetEntry) {
086        offsetEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_ACTUAL);
087        return true;
088    }
089
090    /**
091     * Set attributes of an explicit pending entry according to rules specific to TransferOfFundsDocument.
092     * 
093     * @param financialDocument The accounting document containing the general ledger pending entries being customized.
094     * @param accountingLine The accounting line the explicit general ledger pending entry was generated from.
095     * @param explicitEntry The explicit general ledger pending entry to be customized.
096     * 
097     * @see org.kuali.ole.sys.document.validation.impl.AccountingDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.rice.krad.document.FinancialDocument,
098     *      org.kuali.rice.krad.bo.AccountingLine, org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
099     */
100    @Override
101    public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail generalLedgerPendingEntrySourceDetail, GeneralLedgerPendingEntry explicitEntry) {
102        AccountingLine accountingLine = (AccountingLine)generalLedgerPendingEntrySourceDetail;
103        SystemOptions options = SpringContext.getBean(OptionsService.class).getCurrentYearOptions();
104
105        explicitEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_ACTUAL);
106        DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
107        if (isDebitUtils.isExpense(accountingLine)) {
108            explicitEntry.setFinancialObjectTypeCode(options.getFinancialObjectTypeTransferExpenseCd());
109        }
110        else {
111            if (isDebitUtils.isIncome(accountingLine)) {
112                explicitEntry.setFinancialObjectTypeCode(options.getFinancialObjectTypeTransferIncomeCd());
113            }
114            else {
115                AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
116                explicitEntry.setFinancialObjectTypeCode(accountingDocumentRuleUtil.getObjectCodeTypeCodeWithoutSideEffects(accountingLine));
117            }
118        }
119    }
120
121    /**
122     * Adds the following restrictions in addition to those provided by <code>IsDebitUtils.isDebitConsideringNothingPositiveOnly</code>
123     * <ol>
124     * <li> Only allow income or expense object type codes
125     * <li> Target lines have the opposite debit/credit codes as the source lines
126     * </ol>
127     * 
128     * @param financialDocument The document used to determine if the accounting line is a debit line.
129     * @param accountingLine The accounting line to be analyzed.
130     * @return True if the accounting line provided is a debit line, false otherwise.
131     * 
132     * @see IsDebitUtils#isDebitConsideringNothingPositiveOnly(FinancialDocumentRuleBase, FinancialDocument, AccountingLine)
133     * @see org.kuali.rice.krad.rule.AccountingLineRule#isDebit(org.kuali.rice.krad.document.FinancialDocument,
134     *      org.kuali.rice.krad.bo.AccountingLine)
135     */
136    public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
137        AccountingLine accountingLine = (AccountingLine)postable;
138        // only allow income or expense
139        DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
140        if (!isDebitUtils.isIncome(accountingLine) && !isDebitUtils.isExpense(accountingLine)) {
141            throw new IllegalStateException(isDebitUtils.getDebitCalculationIllegalStateExceptionMessage());
142        }
143        boolean isDebit = false;
144        if (accountingLine.isSourceAccountingLine()) {
145            isDebit = isDebitUtils.isDebitConsideringNothingPositiveOnly(this, accountingLine);
146        }
147        else if (accountingLine.isTargetAccountingLine()) {
148            isDebit = !isDebitUtils.isDebitConsideringNothingPositiveOnly(this, accountingLine);
149        }
150        else {
151            throw new IllegalStateException(isDebitUtils.getInvalidLineTypeIllegalArgumentExceptionMessage());
152        }
153
154        return isDebit;
155    }
156}