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 }