/*
* 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.gl.batch.service.impl;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import org.kuali.kfs.gl.batch.service.AccountingCycleCachingService;
import org.kuali.kfs.gl.batch.service.BalanceCalculator;
import org.kuali.kfs.gl.batch.service.PostTransaction;
import org.kuali.kfs.gl.businessobject.Balance;
import org.kuali.kfs.gl.businessobject.Transaction;
import org.kuali.kfs.sys.businessobject.UniversityDate;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.service.ReportWriterService;
import org.kuali.kfs.sys.service.UniversityDateService;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.springframework.transaction.annotation.Transactional;
/**
* This implementation of PostTransaction updates the appropriate Balance
*/
@Transactional
public class PostBalance implements PostTransaction, BalanceCalculator {
private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PostBalance.class);
private AccountingCycleCachingService accountingCycleCachingService;
private static final KualiDecimal NEGATIVE_ONE = new KualiDecimal(-1);
/**
* Constructs a PostBalance instance
*/
public PostBalance() {
super();
}
/**
* This posts the effect of the transaction upon the appropriate balance record.
*
* @param t the transaction which is being posted
* @param mode the mode the poster is currently running in
* @param postDate the date this transaction should post to
* @param posterReportWriterService the writer service where the poster is writing its report
* @return the accomplished post type
* @see org.kuali.kfs.gl.batch.service.PostTransaction#post(org.kuali.kfs.gl.businessobject.Transaction, int, java.util.Date)
*/
public String post(Transaction t, int mode, Date postDate, ReportWriterService posterReportWriterService) {
LOG.debug("post() started");
String postType = "U";
KualiDecimal amount = t.getTransactionLedgerEntryAmount();
// Subtract the amount if offset generation indicator & the debit/credit code isn't the same
// as the one in the object type code table
if (t.getBalanceType().isFinancialOffsetGenerationIndicator()) {
if (!t.getTransactionDebitCreditCode().equals(t.getObjectType().getFinObjectTypeDebitcreditCd())) {
amount = amount.multiply(NEGATIVE_ONE);
}
}
Balance b = accountingCycleCachingService.getBalance(t);
if (b == null) {
postType = "I";
b = new Balance(t);
}
String period = t.getUniversityFiscalPeriodCode();
b.addAmount(period, amount);
if (postType.equals("I")) {
accountingCycleCachingService.insertBalance(b);
} else {
accountingCycleCachingService.updateBalance(b);
}
return postType;
}
/**
* Given a list of balances, determines which one the given trsnaction should post to
*
* @param balanceList a Collection of balances
* @param t the transaction that is being posted
* @return the balance, either found from the list, or, if not present in the list, newly created
* @see org.kuali.kfs.gl.batch.service.BalanceCalculator#findBalance(java.util.Collection, org.kuali.kfs.gl.businessobject.Transaction)
*/
public Balance findBalance(Collection balanceList, Transaction t) {
// Try to find one that already exists
for (Iterator iter = balanceList.iterator(); iter.hasNext();) {
Balance b = (Balance) iter.next();
if (b.getUniversityFiscalYear().equals(t.getUniversityFiscalYear()) && b.getChartOfAccountsCode().equals(t.getChartOfAccountsCode()) && b.getAccountNumber().equals(t.getAccountNumber()) && b.getSubAccountNumber().equals(t.getSubAccountNumber()) && b.getObjectCode().equals(t.getFinancialObjectCode()) && b.getSubObjectCode().equals(t.getFinancialSubObjectCode()) && b.getBalanceTypeCode().equals(t.getFinancialBalanceTypeCode()) && b.getObjectTypeCode().equals(t.getFinancialObjectTypeCode())) {
return b;
}
}
// If we couldn't find one that exists, create a new one
Balance b = new Balance(t);
balanceList.add(b);
return b;
}
/**
* @param t
* @param enc
*/
public void updateBalance(Transaction t, Balance b) {
// The pending entries haven't been scrubbed so there could be
// bad data. This won't update a balance if the data it needs
// is invalid
KualiDecimal amount = t.getTransactionLedgerEntryAmount();
if (amount == null) {
amount = KualiDecimal.ZERO;
}
if (t.getObjectType() == null) {
LOG.error("updateBalance() Invalid object type (" + t.getFinancialObjectTypeCode() + ") in pending table");
return;
}
if (t.getBalanceType() == null) {
LOG.error("updateBalance() Invalid balance type (" + t.getFinancialBalanceTypeCode() + ") in pending table");
return;
}
// Subtract the amount if offset generation indicator & the debit/credit code isn't the same
// as the one in the object type code table
if (t.getBalanceType().isFinancialOffsetGenerationIndicator()) {
if (!t.getTransactionDebitCreditCode().equals(t.getObjectType().getFinObjectTypeDebitcreditCd())) {
amount = amount.multiply(new KualiDecimal(-1));
}
}
// update the balance amount of the cooresponding period
String period = t.getUniversityFiscalPeriodCode();
if (period == null) {
UniversityDate currentUniversityDate = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate();
period = currentUniversityDate.getUniversityFiscalAccountingPeriod();
}
b.addAmount(period, amount);
}
/**
* @see org.kuali.kfs.gl.batch.service.PostTransaction#getDestinationName()
*/
public String getDestinationName() {
return "GL_BALANCE_T";
}
public void setAccountingCycleCachingService(AccountingCycleCachingService accountingCycleCachingService) {
this.accountingCycleCachingService = accountingCycleCachingService;
}
}