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.rice.kns.util.AssertionUtils.assertThat;
019    import static org.kuali.kfs.sys.KFSConstants.BALANCE_TYPE_PRE_ENCUMBRANCE;
020    
021    import java.util.ArrayList;
022    import java.util.List;
023    
024    import org.kuali.kfs.fp.businessobject.PreEncumbranceDocumentAccountingLineParser;
025    import org.kuali.kfs.sys.KFSConstants;
026    import org.kuali.kfs.sys.businessobject.AccountingLine;
027    import org.kuali.kfs.sys.businessobject.AccountingLineParser;
028    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
029    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
030    import org.kuali.kfs.sys.businessobject.SufficientFundsItem;
031    import org.kuali.kfs.sys.context.SpringContext;
032    import org.kuali.kfs.sys.document.AccountingDocumentBase;
033    import org.kuali.kfs.sys.document.AmountTotaling;
034    import org.kuali.kfs.sys.document.Correctable;
035    import org.kuali.kfs.sys.document.service.DebitDeterminerService;
036    import org.kuali.kfs.sys.service.HomeOriginationService;
037    import org.kuali.rice.kew.exception.WorkflowException;
038    import org.kuali.rice.kns.document.Copyable;
039    import org.kuali.rice.kns.service.DateTimeService;
040    
041    /**
042     * The Pre-Encumbrance document provides the capability to record encumbrances independently of purchase orders, travel, or Physical
043     * Plant work orders. These transactions are for the use of the account manager to earmark funds for which unofficial commitments
044     * have already been made.
045     */
046    public class PreEncumbranceDocument extends AccountingDocumentBase implements Copyable, Correctable, AmountTotaling {
047        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PreEncumbranceDocument.class);
048    
049        protected java.sql.Date reversalDate;
050    
051        /**
052         * Initializes the array lists and some basic info.
053         */
054        public PreEncumbranceDocument() {
055            super();
056        }
057    
058        /**
059         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#checkSufficientFunds()
060         */
061        @Override
062        public List<SufficientFundsItem> checkSufficientFunds() {
063            LOG.debug("checkSufficientFunds() started");
064    
065            // This document does not do sufficient funds checking
066            return new ArrayList<SufficientFundsItem>();
067        }
068    
069    
070        /**
071         * @return Timestamp
072         */
073        public java.sql.Date getReversalDate() {
074            return reversalDate;
075        }
076    
077        /**
078         * @param reversalDate
079         */
080        public void setReversalDate(java.sql.Date reversalDate) {
081            this.reversalDate = reversalDate;
082        }
083    
084        /**
085         * Overrides the base implementation to return "Encumbrance".
086         * 
087         * @see org.kuali.kfs.sys.document.AccountingDocument#getSourceAccountingLinesSectionTitle()
088         */
089        @Override
090        public String getSourceAccountingLinesSectionTitle() {
091            return KFSConstants.ENCUMBRANCE;
092        }
093    
094        /**
095         * Overrides the base implementation to return "Disencumbrance".
096         * 
097         * @see org.kuali.kfs.sys.document.AccountingDocument#getTargetAccountingLinesSectionTitle()
098         */
099        @Override
100        public String getTargetAccountingLinesSectionTitle() {
101            return KFSConstants.DISENCUMBRANCE;
102        }
103    
104        /**
105         * This method limits valid debits to only expense object type codes.  Additionally, an 
106         * IllegalStateException will be thrown if the accounting line passed in is not an expense, 
107         * is an error correction with a positive dollar amount or is not an error correction and 
108         * has a negative amount. 
109         * 
110         * @param transactionalDocument The document the accounting line being checked is located in.
111         * @param accountingLine The accounting line being analyzed.
112         * @return True if the accounting line given is a debit accounting line, false otherwise.
113         * 
114         * @see IsDebitUtils#isDebitConsideringSection(FinancialDocumentRuleBase, FinancialDocument, AccountingLine)
115         * @see org.kuali.rice.kns.rule.AccountingLineRule#isDebit(org.kuali.rice.kns.document.FinancialDocument,
116         *      org.kuali.rice.kns.bo.AccountingLine)
117         */
118        public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
119            AccountingLine accountingLine = (AccountingLine)postable;
120            // if not expense, or positive amount on an error-correction, or negative amount on a non-error-correction, throw exception
121            DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
122            if (!isDebitUtils.isExpense(accountingLine) || (isDebitUtils.isErrorCorrection(this) == accountingLine.getAmount().isPositive())) {
123                throw new IllegalStateException(isDebitUtils.getDebitCalculationIllegalStateExceptionMessage());
124            }
125    
126            return !isDebitUtils.isDebitConsideringSection(this, accountingLine);
127        }
128        
129        /**
130         * This method contains PreEncumbrance document specific general ledger pending entry explicit entry 
131         * attribute assignments.  These attributes include financial balance type code, reversal date and 
132         * transaction encumbrance update code.
133         * 
134         * @param financialDocument The document which contains the explicit entry.
135         * @param accountingLine The accounting line the explicit entry is generated from.
136         * @param explicitEntry The explicit entry being updated.
137         * 
138         * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.rice.kns.document.FinancialDocument,
139         *      org.kuali.rice.kns.bo.AccountingLine, org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
140         */
141        @Override
142        public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
143            explicitEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_PRE_ENCUMBRANCE);
144            AccountingLine accountingLine = (AccountingLine)postable;
145    
146            // set the reversal date to what was chosen by the user in the interface
147            if (getReversalDate() != null) {
148                explicitEntry.setFinancialDocumentReversalDate(getReversalDate());
149            }
150            explicitEntry.setTransactionEntryProcessedTs(null);
151            if (accountingLine.isSourceAccountingLine()) {
152                explicitEntry.setTransactionEncumbranceUpdateCode(KFSConstants.ENCUMB_UPDT_DOCUMENT_CD);
153            }
154            else {
155                assertThat(accountingLine.isTargetAccountingLine(), accountingLine);
156                explicitEntry.setTransactionEncumbranceUpdateCode(KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD);
157                explicitEntry.setReferenceFinancialSystemOriginationCode(SpringContext.getBean(HomeOriginationService.class).getHomeOrigination().getFinSystemHomeOriginationCode());
158                explicitEntry.setReferenceFinancialDocumentNumber(accountingLine.getReferenceNumber());
159                explicitEntry.setReferenceFinancialDocumentTypeCode(explicitEntry.getFinancialDocumentTypeCode()); // "PE"
160            }
161        }
162    
163        /**
164         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#toCopy()
165         */
166        @Override
167        public void toCopy() throws WorkflowException {
168            super.toCopy();
169            refreshReversalDate();
170        }
171        
172        /**
173         * If the reversal date on this document is in need of refreshing, refreshes the reveral date.  THIS METHOD MAY CHANGE DOCUMENT STATE!
174         * @return true if the reversal date ended up getting refreshed, false otherwise
175         */
176        protected boolean refreshReversalDate() {
177            boolean refreshed = false;
178            if (getReversalDate() != null) {
179                java.sql.Date today = SpringContext.getBean(DateTimeService.class).getCurrentSqlDateMidnight();
180                if (getReversalDate().before(today)) {
181                    // set the reversal date on the document
182                    setReversalDate(today);
183                    refreshed = true;
184                }
185            }
186            return refreshed;
187        }
188    }