/*
* 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.sys.service.impl;
import java.util.Calendar;
import java.util.HashMap;
import org.kuali.kfs.coa.businessobject.Account;
import org.kuali.kfs.coa.businessobject.ObjectCode;
import org.kuali.kfs.coa.businessobject.OffsetDefinition;
import org.kuali.kfs.coa.service.AccountService;
import org.kuali.kfs.coa.service.ObjectCodeService;
import org.kuali.kfs.fp.businessobject.OffsetAccount;
import org.kuali.kfs.gl.businessobject.FlexibleAccountUpdateable;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.exception.InvalidFlexibleOffsetException;
import org.kuali.kfs.sys.service.FlexibleOffsetAccountService;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.coreservice.framework.parameter.ParameterService;
import org.kuali.rice.krad.service.BusinessObjectService;
/**
* This is the default implementation of the FlexibleOffsetAccountService interface.
*/
public class FlexibleOffsetAccountServiceImpl implements FlexibleOffsetAccountService {
private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(FlexibleOffsetAccountServiceImpl.class);
private BusinessObjectService businessObjectService;
private AccountService accountService;
private ObjectCodeService objectCodeService;
private DateTimeService dateTimeService;
private ParameterService parameterService;
/**
* This method uses the parameters provided to retrieve an OffsetAccount instance if the flexible offset account flag is
* enabled.
*
* @param chartOfAccountsCode The chart code used to retrieve the flexible offset account.
* @param accountNumber The account number of the flexible offset account being retrieved.
* @param financialOffsetObjectCode The offset object code used to retrieve the offset account.
* @return A flexible offset account based on the parameters provided, or null if offsets are not enabled.
*
* @see FlexibleOffsetAccountService#getByPrimaryIdIfEnabled
*/
public OffsetAccount getByPrimaryIdIfEnabled(String chartOfAccountsCode, String accountNumber, String financialOffsetObjectCode) {
LOG.debug("getByPrimaryIdIfEnabled() started");
if (!getEnabled()) {
return null;
}
HashMap<String,Object> keys = new HashMap();
keys.put("chartOfAccountsCode", chartOfAccountsCode);
keys.put("accountNumber", accountNumber);
keys.put("financialOffsetObjectCode", financialOffsetObjectCode);
return (OffsetAccount) businessObjectService.findByPrimaryKey(OffsetAccount.class, keys);
}
/**
* This method queries the parameter table to retrieve the value of the flexible offset flag and returns the resulting value.
*
* @return True if flexible offsets are enabled, false otherwise.
*
* @see FlexibleOffsetAccountService#getEnabled
*/
public boolean getEnabled() {
LOG.debug("getEnabled() started");
return parameterService.getParameterValueAsBoolean(OffsetDefinition.class, KFSConstants.SystemGroupParameterNames.FLEXIBLE_OFFSET_ENABLED_FLAG);
}
/**
* This method modifies the origin entry provided with values from the associated flexible offset account, which is
* retrieved from the database using values provided by the origin entry.
*
* @param originEntry The origin entry to be updated with offset account details.
* @return False if the flexible offset flag is false, if there is no corresponding flexbile offset account, true otherwise.
*
* @see org.kuali.kfs.sys.service.FlexibleOffsetAccountService#updateOffset(org.kuali.kfs.gl.businessobject.OriginEntryFull)
*/
public boolean updateOffset(FlexibleAccountUpdateable transaction) {
LOG.debug("setBusinessObjectService() started");
if (!getEnabled()) {
return false;
}
String keyOfErrorMessage = "";
Integer fiscalYear = transaction.getUniversityFiscalYear();
String chartOfAccountsCode = transaction.getChartOfAccountsCode();
String accountNumber = transaction.getAccountNumber();
String balanceTypeCode = transaction.getFinancialBalanceTypeCode();
String documentTypeCode = transaction.getFinancialDocumentTypeCode();
// do nothing if there is no the offset account with the given chart of accounts code,
// account number and offset object code in the offset table.
OffsetAccount flexibleOffsetAccount = getByPrimaryIdIfEnabled(chartOfAccountsCode, accountNumber, transaction.getFinancialObjectCode());
if (flexibleOffsetAccount == null) {
return false;
}
String offsetAccountNumber = flexibleOffsetAccount.getFinancialOffsetAccountNumber();
String offsetChartOfAccountsCode = flexibleOffsetAccount.getFinancialOffsetChartOfAccountCode();
Account offsetAccount = accountService.getByPrimaryId(offsetChartOfAccountsCode, offsetAccountNumber);
if (offsetAccount == null) {
throw new InvalidFlexibleOffsetException("Invalid Flexible Offset Account " + offsetChartOfAccountsCode + "-" + offsetAccountNumber);
}
// Can't be closed and can't be expired
if (!offsetAccount.isActive()) {
throw new InvalidFlexibleOffsetException("Closed Flexible Offset Account " + offsetChartOfAccountsCode + "-" + offsetAccountNumber);
}
if ((offsetAccount.getAccountExpirationDate() != null) && isExpired(offsetAccount, dateTimeService.getCurrentCalendar())) {
throw new InvalidFlexibleOffsetException("Expired Flexible Offset Account " + offsetChartOfAccountsCode + "-" + offsetAccountNumber);
}
// If the chart changes, make sure the object code is still valid
if (!chartOfAccountsCode.equals(offsetChartOfAccountsCode)) {
ObjectCode objectCode = objectCodeService.getByPrimaryId(fiscalYear, offsetChartOfAccountsCode, transaction.getFinancialObjectCode());
if (objectCode == null) {
throw new InvalidFlexibleOffsetException("Invalid Object Code for flexible offset " + fiscalYear + "-" + offsetChartOfAccountsCode + "-" + transaction.getFinancialObjectCode());
}
}
// replace the chart and account of the given transaction with those of the offset account obtained above
transaction.setAccount(offsetAccount);
transaction.setAccountNumber(offsetAccountNumber);
transaction.setChartOfAccountsCode(offsetChartOfAccountsCode);
// blank out the sub account and sub object since the account has been replaced
transaction.setSubAccountNumber(KFSConstants.getDashSubAccountNumber());
transaction.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
return true;
}
/**
* This method determines if an account has expired. An account has expired if the expiration year of the account is
* less than the run date year or if the date of expiration occurred before the run date provided.
*
* @param account The account to be examined.
* @param runCalendar The date the expiration date is tested against.
* @return True if the account has expired, false otherwise.
*/
protected boolean isExpired(Account account, Calendar runCalendar) {
Calendar expirationDate = Calendar.getInstance();
expirationDate.setTimeInMillis(account.getAccountExpirationDate().getTime());
int expirationYear = expirationDate.get(Calendar.YEAR);
int runYear = runCalendar.get(Calendar.YEAR);
int expirationDay = expirationDate.get(Calendar.DAY_OF_YEAR);
int runDay = runCalendar.get(Calendar.DAY_OF_YEAR);
return (expirationYear < runYear) || (expirationYear == runYear && expirationDay < runDay);
}
/**
* Sets the local dateTimeService attribute.
* @param dateTimeService The DateTimeService instance to be set.
*/
public void setDateTimeService(DateTimeService dateTimeService) {
this.dateTimeService = dateTimeService;
}
/**
* Sets the local accountService attribute.
* @param accountService The AccountService instance to be set.
*/
public void setAccountService(AccountService accountService) {
this.accountService = accountService;
}
/**
* Sets the local objectCodeService attribute.
* @param objectCodeService The ObjectCodeService instance to be set.
*/
public void setObjectCodeService(ObjectCodeService objectCodeService) {
this.objectCodeService = objectCodeService;
}
/**
* Sets the local businessObjectService attribute.
* @param businessObjectService The BusinessObjectService instance to be set.
*/
public void setBusinessObjectService(BusinessObjectService businessObjectService) {
this.businessObjectService = businessObjectService;
}
/**
* Sets the local parameterService attribute.
* @param parameterService The ParameterService instance to be set.
*/
public void setParameterService(ParameterService parameterService) {
this.parameterService = parameterService;
}
}