001    /*
002     * Copyright 2011 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     */
016    package org.kuali.kfs.fp.document;
017    
018    import static org.kuali.kfs.sys.KFSConstants.BALANCE_TYPE_ACTUAL;
019    
020    import org.kuali.kfs.sys.KFSConstants;
021    import org.kuali.kfs.sys.businessobject.AccountingLine;
022    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
023    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
024    import org.kuali.kfs.sys.businessobject.SystemOptions;
025    import org.kuali.kfs.sys.context.SpringContext;
026    import org.kuali.kfs.sys.document.AccountingDocumentBase;
027    import org.kuali.kfs.sys.document.AmountTotaling;
028    import org.kuali.kfs.sys.document.Correctable;
029    import org.kuali.kfs.sys.document.service.AccountingDocumentRuleHelperService;
030    import org.kuali.kfs.sys.document.service.DebitDeterminerService;
031    import org.kuali.kfs.sys.service.OptionsService;
032    import org.kuali.rice.kns.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     */
042    public 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.kfs.sys.document.AccountingDocument#getSourceAccountingLinesSectionTitle()
056         */
057        public String getSourceAccountingLinesSectionTitle() {
058            return KFSConstants.FROM;
059        }
060    
061        /**
062         * Overrides the base implementation to return "To".
063         * 
064         * @see org.kuali.kfs.sys.document.AccountingDocument#getTargetAccountingLinesSectionTitle()
065         */
066        public String getTargetAccountingLinesSectionTitle() {
067            return KFSConstants.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.kfs.sys.document.validation.impl.AccountingDocumentRuleBase#customizeOffsetGeneralLedgerPendingEntry(org.kuali.rice.kns.document.FinancialDocument,
081         *      org.kuali.rice.kns.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.kfs.sys.document.validation.impl.AccountingDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.rice.kns.document.FinancialDocument,
098         *      org.kuali.rice.kns.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.kns.rule.AccountingLineRule#isDebit(org.kuali.rice.kns.document.FinancialDocument,
134         *      org.kuali.rice.kns.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    }