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.EMPTY_STRING;
019
020 import org.apache.commons.lang.StringUtils;
021 import org.kuali.kfs.fp.businessobject.NonCheckDisbursementDocumentAccountingLineParser;
022 import org.kuali.kfs.sys.KFSConstants;
023 import org.kuali.kfs.sys.KFSKeyConstants;
024 import org.kuali.kfs.sys.KFSPropertyConstants;
025 import org.kuali.kfs.sys.businessobject.AccountingLine;
026 import org.kuali.kfs.sys.businessobject.AccountingLineParser;
027 import org.kuali.kfs.sys.businessobject.Bank;
028 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
029 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
030 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
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.AccountingDocumentRuleHelperService;
036 import org.kuali.kfs.sys.document.service.DebitDeterminerService;
037 import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE;
038 import org.kuali.kfs.sys.service.BankService;
039 import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService;
040 import org.kuali.rice.kns.document.Copyable;
041 import org.kuali.rice.kns.util.KNSConstants;
042 import org.kuali.rice.kns.util.KualiDecimal;
043
044 /**
045 * This is the business object that represents the NonCheckDisbursementDocument in Kuali. The "Non-Check Disbursement" document is
046 * used to record charges or credits directly assessed to university bank accounts. It is used primarily by the Tax and Treasury
047 * Accounting office to record wire transfers, foreign drafts, etc.
048 */
049 public class NonCheckDisbursementDocument extends AccountingDocumentBase implements Copyable, Correctable, AmountTotaling {
050 protected String financialDocumentBankCode;
051
052 protected Bank bank;
053
054 /**
055 * Constructs a NonCheckDisbursementDocument instance.
056 */
057 public NonCheckDisbursementDocument() {
058 bank = new Bank();
059 }
060
061 /**
062 * Sets the bank code for a new document to the setup default for the Non Check Disbursement document.
063 */
064 public void setDefautBankCode() {
065 Bank defaultBank = SpringContext.getBean(BankService.class).getDefaultBankByDocType(this.getClass());
066 if (defaultBank != null) {
067 this.financialDocumentBankCode = defaultBank.getBankCode();
068 this.bank = defaultBank;
069 }
070 }
071
072 /**
073 * Gets the financialDocumentBankCode attribute.
074 *
075 * @return Returns the financialDocumentBankCode.
076 */
077 public String getFinancialDocumentBankCode() {
078 return financialDocumentBankCode;
079 }
080
081 /**
082 * Sets the financialDocumentBankCode attribute value.
083 *
084 * @param financialDocumentBankCode The financialDocumentBankCode to set.
085 */
086 public void setFinancialDocumentBankCode(String financialDocumentBankCode) {
087 this.financialDocumentBankCode = financialDocumentBankCode;
088 }
089
090 /**
091 * Gets the bank attribute.
092 *
093 * @return Returns the bank.
094 */
095 public Bank getBank() {
096 return bank;
097 }
098
099 /**
100 * Sets the bank attribute value.
101 *
102 * @param bank The bank to set.
103 */
104 public void setBank(Bank bank) {
105 this.bank = bank;
106 }
107
108 /**
109 * Overrides the base implementation to return "From".
110 *
111 * @see org.kuali.kfs.sys.document.AccountingDocument#getSourceAccountingLinesSectionTitle()
112 */
113 @Override
114 public String getSourceAccountingLinesSectionTitle() {
115 return EMPTY_STRING;
116 }
117
118 /**
119 * This method determines if a given accounting line is a debit accounting line. This is done by calling
120 * IsDebitUtiles.isDebitConsideringNothingPositiveOnly(). An IllegalStateException will be thrown if the accounting line passed
121 * in is not an expense, is an error correction with a positive dollar amount or is not an error correction and has a negative
122 * amount.
123 *
124 * @param transactionalDocument The document the accounting line being checked is located in.
125 * @param accountingLine The accounting line being analyzed.
126 * @return True if the accounting line given is a debit accounting line, false otherwise.
127 * @throws IllegalStateException Thrown if accounting line attributes are invalid.
128 * @see IsDebitUtils#isDebitConsideringNothingPositiveOnly(FinancialDocumentRuleBase, FinancialDocument, AccountingLine)
129 * @see org.kuali.rice.kns.rule.AccountingLineRule#isDebit(org.kuali.rice.kns.document.FinancialDocument,
130 * org.kuali.rice.kns.bo.AccountingLine)
131 */
132 public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) throws IllegalStateException {
133 DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
134 return isDebitUtils.isDebitConsideringNothingPositiveOnly(this, (AccountingLine) postable);
135 }
136
137 /**
138 * This method sets attributes on the explicitly general ledger pending entry specific to NonCheckDisbursement documents. This
139 * includes setting the transaction ledger entry description and blanking out the reference financial document number, the
140 * reference financial system origin code and the reference financial document type code. These values must be nullified because
141 * they don't belong in general ledger pending entries and if they aren't null, the general error corrections won't post
142 * properly.
143 *
144 * @param financialDocument The document which contains the general ledger pending entry being modified.
145 * @param accountingLine The accounting line the explicit entry was generated from.
146 * @param explicitEntry The explicit entry being updated.
147 * @see FinancialDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(FinancialDocument, AccountingLine,
148 * GeneralLedgerPendingEntry)
149 */
150 @Override
151 public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
152 explicitEntry.setTransactionLedgerEntryDescription(buildTransactionLedgerEntryDescriptionUsingRefOriginAndRefDocNumber(postable));
153
154 // Clearing fields that are already handled by the parent algorithm - we don't actually want
155 // these to copy over from the accounting lines b/c they don't belong in the GLPEs
156 // if they aren't nulled, then GECs fail to post
157 explicitEntry.setReferenceFinancialDocumentNumber(null);
158 explicitEntry.setReferenceFinancialSystemOriginationCode(null);
159 explicitEntry.setReferenceFinancialDocumentTypeCode(null);
160 }
161
162 /**
163 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#generateDocumentGeneralLedgerPendingEntries(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
164 */
165 @Override
166 public boolean generateDocumentGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
167 boolean success = true;
168
169 if (!SpringContext.getBean(BankService.class).isBankSpecificationEnabled()) {
170 return success;
171 }
172
173 this.refreshReferenceObject(KFSPropertyConstants.BANK);
174
175 GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class);
176
177 final KualiDecimal bankOffsetAmount = glpeService.getOffsetToCashAmount(this).negated();
178 GeneralLedgerPendingEntry bankOffsetEntry = new GeneralLedgerPendingEntry();
179 success &= glpeService.populateBankOffsetGeneralLedgerPendingEntry(getBank(), bankOffsetAmount, this, getPostingYear(), sequenceHelper, bankOffsetEntry, KNSConstants.DOCUMENT_PROPERTY_NAME + "." + KFSPropertyConstants.FINANCIAL_DOCUMENT_BANK_CODE);
180
181 if (success) {
182 AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
183 bankOffsetEntry.setTransactionLedgerEntryDescription(accountingDocumentRuleUtil.formatProperty(KFSKeyConstants.Bank.DESCRIPTION_GLPE_BANK_OFFSET));
184 getGeneralLedgerPendingEntries().add(bankOffsetEntry);
185 sequenceHelper.increment();
186
187 GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(bankOffsetEntry);
188 success &= glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), bankOffsetEntry, sequenceHelper, offsetEntry);
189 getGeneralLedgerPendingEntries().add(offsetEntry);
190 sequenceHelper.increment();
191 }
192
193 return success;
194 }
195
196 /**
197 * Builds an appropriately formatted string to be used for the <code>transactionLedgerEntryDescription</code>. It is built
198 * using information from the <code>{@link AccountingLine}</code>. Format is "01-12345: blah blah blah".
199 *
200 * @param financialDocument The document the description will be pulled from, if the accounting line description is blank.
201 * @param line The accounting line that will be used for populating the transaction ledger entry description.
202 * @return The description to be applied to the transaction ledger entry.
203 */
204 protected String buildTransactionLedgerEntryDescriptionUsingRefOriginAndRefDocNumber(GeneralLedgerPendingEntrySourceDetail postable) {
205 String description = "";
206 if (StringUtils.isBlank(postable.getReferenceNumber())) {
207 throw new IllegalStateException("Reference Document Number is required and should be validated before this point.");
208 }
209
210 description = KFSConstants.ORIGIN_CODE_KUALI + "-" + postable.getReferenceNumber();
211
212 if (StringUtils.isNotBlank(postable.getFinancialDocumentLineDescription())) {
213 description += ": " + postable.getFinancialDocumentLineDescription();
214 }
215 else {
216 description += ": " + getDocumentHeader().getDocumentDescription();
217 }
218
219 if (description.length() > GENERAL_LEDGER_PENDING_ENTRY_CODE.GLPE_DESCRIPTION_MAX_LENGTH) {
220 description = description.substring(0, GENERAL_LEDGER_PENDING_ENTRY_CODE.GLPE_DESCRIPTION_MAX_LENGTH - 3) + "...";
221 }
222
223 return description;
224 }
225 }