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 }