/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.fp.document;
import java.sql.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.fp.businessobject.CapitalAccountingLines;
import org.kuali.kfs.fp.businessobject.CapitalAssetInformation;
import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.businessobject.AccountingLineBase;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.document.service.DebitDeterminerService;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.krad.util.ObjectUtils;
/**
* Abstract class which defines behavior common to CashReceipt-like documents.
*/
abstract public class CashReceiptFamilyBase extends CapitalAccountingLinesDocumentBase implements CapitalAssetEditable {
protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CashReceiptFamilyBase.class);
protected String campusLocationCode; // TODO Needs to be an actual object - also need to clarify this
protected Date depositDate;
/**
* Constructs a CashReceiptFamilyBase
*/
public CashReceiptFamilyBase() {
setCampusLocationCode(KFSConstants.CashReceiptConstants.DEFAULT_CASH_RECEIPT_CAMPUS_LOCATION_CODE);
}
/**
* Documents in the CashReceiptFamily do not perform Sufficient Funds checking
*
* @see org.kuali.kfs.sys.document.AccountingDocumentBase#documentPerformsSufficientFundsCheck()
*/
@Override
public boolean documentPerformsSufficientFundsCheck() {
return false;
}
/**
* Gets the campusLocationCode attribute.
*
* @return Returns the campusLocationCode.
*/
public String getCampusLocationCode() {
return campusLocationCode;
}
/**
* Sets the campusLocationCode attribute value.
*
* @param campusLocationCode The campusLocationCode to set.
*/
public void setCampusLocationCode(String campusLocationCode) {
this.campusLocationCode = campusLocationCode;
}
/**
* Gets the depositDate attribute.
*
* @return Returns the depositDate.
*/
public Date getDepositDate() {
return depositDate;
}
/**
* Sets the depositDate attribute value.
*
* @param depositDate The depositDate to set.
*/
public void setDepositDate(Date depositDate) {
this.depositDate = depositDate;
}
/**
* Total for a Cash Receipt according to the spec should be the sum of the amounts on accounting lines belonging to object codes
* having the 'income' object type, less the sum of the amounts on accounting lines belonging to object codes having the
* 'expense' object type.
*
* @see org.kuali.kfs.sys.document.AccountingDocument#getSourceTotal()
*/
@Override
public KualiDecimal getSourceTotal() {
KualiDecimal total = KualiDecimal.ZERO;
AccountingLineBase al = null;
if (ObjectUtils.isNull(getSourceAccountingLines()) || getSourceAccountingLines().isEmpty()) {
refreshReferenceObject(KFSPropertyConstants.SOURCE_ACCOUNTING_LINES);
}
Iterator iter = getSourceAccountingLines().iterator();
while (iter.hasNext()) {
al = (AccountingLineBase) iter.next();
try {
KualiDecimal amount = al.getAmount().abs();
if (amount != null && amount.isNonZero()) {
if (isDebit(al)) {
total = total.subtract(amount);
}
else { // in this context, if it's not a debit, it's a credit
total = total.add(amount);
}
}
}
catch (Exception e) {
// Possibly caused by accounting lines w/ bad data
LOG.error("Error occured trying to compute Cash receipt total, returning 0", e);
return KualiDecimal.ZERO;
}
}
return total;
}
/**
* Cash Receipts only have source lines, so this should always return 0.
*
* @see org.kuali.kfs.sys.document.AccountingDocument#getTargetTotal()
*/
@Override
public KualiDecimal getTargetTotal() {
return KualiDecimal.ZERO;
}
/**
* Overrides the base implementation to return an empty string.
*
* @see org.kuali.kfs.sys.document.AccountingDocument#getSourceAccountingLinesSectionTitle()
*/
@Override
public String getSourceAccountingLinesSectionTitle() {
return KFSConstants.EMPTY_STRING;
}
/**
* Overrides the base implementation to return an empty string.
*
* @see org.kuali.kfs.sys.document.AccountingDocument#getTargetAccountingLinesSectionTitle()
*/
@Override
public String getTargetAccountingLinesSectionTitle() {
return KFSConstants.EMPTY_STRING;
}
/**
* Returns true if accounting line is debit
*
* @param financialDocument
* @param accountingLine
* @param true if accountline line
* @see IsDebitUtils#isDebitConsideringType(FinancialDocumentRuleBase, FinancialDocument, AccountingLine)
* @see org.kuali.rice.krad.rule.AccountingLineRule#isDebit(org.kuali.rice.krad.document.FinancialDocument,
* org.kuali.rice.krad.bo.AccountingLine)
*/
@Override
public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
// error corrections are not allowed
DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
//TODO ??? we now allow error correction on AD and CCR, so can't do this checking here; do it in subclasses if needed.
//isDebitUtils.disallowErrorCorrectionDocumentCheck(this);
return isDebitUtils.isDebitConsideringType(this, postable);
}
/**
* Overrides to set the entry's description to the description from the accounting line, if a value exists.
*
* @param financialDocument submitted accounting document
* @param accountingLine accounting line in accounting document
* @param explicitEntry general ledger pending entry
* @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.rice.krad.document.FinancialDocument,
* org.kuali.rice.krad.bo.AccountingLine, org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
*/
@Override
public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
String accountingLineDescription = postable.getFinancialDocumentLineDescription();
if (StringUtils.isNotBlank(accountingLineDescription)) {
explicitEntry.setTransactionLedgerEntryDescription(accountingLineDescription);
}
}
/**
* @see org.kuali.kfs.fp.document.CapitalAssetEditable#getCapitalAssetInformation()
*/
@Override
public List<CapitalAssetInformation> getCapitalAssetInformation() {
return ObjectUtils.isNull(capitalAssetInformation) ? null : capitalAssetInformation;
}
/**
* @see org.kuali.kfs.fp.document.CapitalAssetEditable#setCapitalAssetInformation(org.kuali.kfs.fp.businessobject.CapitalAssetInformation)
*/
@Override
public void setCapitalAssetInformation(List<CapitalAssetInformation> capitalAssetInformation) {
this.capitalAssetInformation = capitalAssetInformation;
}
protected CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() {
return SpringContext.getBean(CapitalAssetManagementModuleService.class);
}
/**
* Note: This method is only shared by subclasses which implement Correctable.
* Upon error correction, negates amount in each capital asset accounting line,
* and updates the documentNumber to point to the new document.
*/
protected void correctCapitalAccountingLines() {
for (CapitalAccountingLines capacctline: capitalAccountingLines) {
capacctline.setDocumentNumber(documentNumber);
capacctline.setAmount(capacctline.getAmount().negated());
}
}
/**
* Returns true if the document is error corrected.
*/
public boolean isErrorCorrected() {
return StringUtils.isNotEmpty(getFinancialSystemDocumentHeader().getFinancialDocumentInErrorNumber());
}
}