/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mifos.application.master.business.MifosCurrency;
import org.mifos.config.business.MifosConfigurationManager;
import org.mifos.config.persistence.ConfigurationPersistence;
import org.mifos.framework.TestUtils;
import org.mifos.framework.util.StandardTestingService;
import org.mifos.framework.util.helpers.Money;
import org.mifos.service.test.TestMode;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class AccountingRulesTest {
static {
// FIXME - keithw - this doesn't work - globalMulticurrencyFlagWorks fails when i change my custom applicationConfiguration.properties file.
// Ignore MIFOS_CONF/applicationConfiguration.custom.properties. See MIFOS-2865.
new StandardTestingService().setTestMode(TestMode.INTEGRATION);
}
@Mock
private static ConfigurationPersistence configurationPersistence;
@BeforeClass
public static void setupMifosLoggerDueToUseOfStaticClientRules() {
Money.setDefaultCurrency(TestUtils.RUPEE);
}
@Test
public void testGetCurrencyRoundingMode() {
RoundingMode configuredMode = AccountingRules.getCurrencyRoundingMode();
String roundingMode = "FLOOR";
RoundingMode configRoundingMode = RoundingMode.FLOOR;
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
configMgr.setProperty(AccountingRulesConstants.CURRENCY_ROUNDING_MODE, roundingMode);
// return value from accounting rules class has to be the value defined
// in the config file
assertEquals(configRoundingMode, AccountingRules.getCurrencyRoundingMode());
// clear the RoundingRule property from the config file so should get
// the default value
configMgr.clearProperty(AccountingRulesConstants.CURRENCY_ROUNDING_MODE);
RoundingMode defaultValue = AccountingRules.getCurrencyRoundingMode();
assertEquals(defaultValue, RoundingMode.HALF_UP);
// now set a wrong rounding mode in config
roundingMode = "UP";
configMgr.addProperty(AccountingRulesConstants.CURRENCY_ROUNDING_MODE, roundingMode);
try {
AccountingRules.getCurrencyRoundingMode();
fail();
} catch (RuntimeException e) {
assertEquals("CurrencyRoundingMode defined in the config file is not CEILING, FLOOR, HALF_UP. It is "
+ roundingMode, e.getMessage());
}
// save it back
configMgr.setProperty(AccountingRulesConstants.CURRENCY_ROUNDING_MODE, configuredMode.toString());
}
@Test
public void testGetInitialRoundingMode() {
RoundingMode configuredMode = AccountingRules.getInitialRoundingMode();
String roundingMode = "FLOOR";
RoundingMode configRoundingMode = RoundingMode.FLOOR;
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
configMgr.setProperty(AccountingRulesConstants.INITIAL_ROUNDING_MODE, roundingMode);
// return value from accounting rules class has to be the value defined
// in the config file
assertEquals(configRoundingMode, AccountingRules.getInitialRoundingMode());
// clear the RoundingRule property from the config file
configMgr.clearProperty(AccountingRulesConstants.INITIAL_ROUNDING_MODE);
RoundingMode defaultValue = AccountingRules.getInitialRoundingMode();
assertEquals(defaultValue, RoundingMode.HALF_UP);
// now set a wrong rounding mode in config
roundingMode = "UP";
configMgr.addProperty(AccountingRulesConstants.INITIAL_ROUNDING_MODE, roundingMode);
try {
AccountingRules.getInitialRoundingMode();
fail();
} catch (RuntimeException e) {
assertEquals("InitialRoundingMode defined in the config file is not CEILING, FLOOR, HALF_UP. It is "
+ roundingMode, e.getMessage());
}
// save it back
configMgr.setProperty(AccountingRulesConstants.INITIAL_ROUNDING_MODE, configuredMode.toString());
}
@Test
public void testGetFinalRoundingMode() {
RoundingMode configuredMode = AccountingRules.getFinalRoundingMode();
String roundingMode = "CEILING";
RoundingMode configRoundingMode = RoundingMode.CEILING;
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
configMgr.setProperty(AccountingRulesConstants.FINAL_ROUNDING_MODE, roundingMode);
// return value from accounting rules class has to be the value defined
// in the config file
assertEquals(configRoundingMode, AccountingRules.getFinalRoundingMode());
// clear the RoundingRule property from the config file
configMgr.clearProperty(AccountingRulesConstants.FINAL_ROUNDING_MODE);
RoundingMode defaultValue = AccountingRules.getFinalRoundingMode();
assertEquals(defaultValue, RoundingMode.CEILING);
// now set a wrong rounding mode in config
roundingMode = "DOWN";
configMgr.addProperty(AccountingRulesConstants.FINAL_ROUNDING_MODE, roundingMode);
try {
AccountingRules.getFinalRoundingMode();
fail();
} catch (RuntimeException e) {
assertEquals("FinalRoundingMode defined in the config file is not CEILING, FLOOR, HALF_UP. It is "
+ roundingMode, e.getMessage());
}
// save it back
configMgr.setProperty(AccountingRulesConstants.FINAL_ROUNDING_MODE, configuredMode.toString());
}
@Test
public void testGetFinalRoundOffMultiple() {
BigDecimal configuredRoundOffMultiple = AccountingRules.getFinalRoundOffMultiple();
String roundOffMultiple = "1";
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
configMgr.setProperty(AccountingRulesConstants.FINAL_ROUND_OFF_MULTIPLE, roundOffMultiple);
// return value from accounting rules class has to be the value defined
// in the config file
assertEquals(new BigDecimal(roundOffMultiple), AccountingRules.getFinalRoundOffMultiple());
// clear the RoundingRule property from the config file
configMgr.clearProperty(AccountingRulesConstants.FINAL_ROUND_OFF_MULTIPLE);
BigDecimal defaultValue = AccountingRules.getFinalRoundOffMultiple();
assertEquals(defaultValue, new BigDecimal("1"));
// save it back
configMgr.addProperty(AccountingRulesConstants.FINAL_ROUND_OFF_MULTIPLE, configuredRoundOffMultiple.toString());
}
@Test
public void testGetInitialRoundOffMultiple() {
BigDecimal configuredRoundOffMultiple = AccountingRules.getInitialRoundOffMultiple();
String roundOffMultiple = "1";
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
configMgr.setProperty(AccountingRulesConstants.INITIAL_ROUND_OFF_MULTIPLE, roundOffMultiple);
// return value from accounting rules class has to be the value defined
// in the config file
assertEquals(new BigDecimal(roundOffMultiple), AccountingRules.getInitialRoundOffMultiple());
// clear the RoundingRule property from the config file
configMgr.clearProperty(AccountingRulesConstants.INITIAL_ROUND_OFF_MULTIPLE);
BigDecimal defaultValue = AccountingRules.getInitialRoundOffMultiple();
assertEquals(defaultValue, new BigDecimal("1"));
// save it back
configMgr.addProperty(AccountingRulesConstants.INITIAL_ROUND_OFF_MULTIPLE, configuredRoundOffMultiple
.toString());
}
@Test
public void testgetMifosCurrency() {
when(configurationPersistence.getCurrency("INR")).thenReturn(TestUtils.RUPEE);
when(configurationPersistence.getCurrency("EUR")).thenReturn(TestUtils.EURO);
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
String currencyCode = configMgr.getString(AccountingRulesConstants.CURRENCY_CODE);
configMgr.setProperty(AccountingRulesConstants.CURRENCY_CODE, "INR");
MifosCurrency currency = AccountingRules.getMifosCurrency(configurationPersistence);
assertEquals(currency.getCurrencyCode(), "INR");
configMgr.setProperty(AccountingRulesConstants.CURRENCY_CODE, "EUR");
currency = AccountingRules.getMifosCurrency(configurationPersistence);
assertEquals(currency.getCurrencyCode(), "EUR");
configMgr.setProperty(AccountingRulesConstants.CURRENCY_CODE, "UUU");
try {
currency = AccountingRules.getMifosCurrency(configurationPersistence);
fail();
} catch (Exception e) {
}
configMgr.setProperty(AccountingRulesConstants.CURRENCY_CODE, currencyCode);
}
@Test
public void testGetNumberOfInterestDays() {
Short interestDaysInConfig = AccountingRules.getNumberOfInterestDays();
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
Short insertedDays = 365;
configMgr.setProperty(AccountingRulesConstants.NUMBER_OF_INTEREST_DAYS, insertedDays);
assertEquals(insertedDays, AccountingRules.getNumberOfInterestDays());
insertedDays = 360;
// set new value
configMgr.setProperty(AccountingRulesConstants.NUMBER_OF_INTEREST_DAYS, insertedDays);
// return value from accounting rules class has to be the value defined
// in the config file
assertEquals(insertedDays, AccountingRules.getNumberOfInterestDays());
insertedDays = 355;
configMgr.setProperty(AccountingRulesConstants.NUMBER_OF_INTEREST_DAYS, insertedDays);
// throw exception because the invalid value 355
try {
AccountingRules.getNumberOfInterestDays();
fail();
} catch (RuntimeException e) {
assertEquals("Invalid number of interest days defined in property file " + insertedDays.shortValue(), e
.getMessage());
} finally {
configMgr.setProperty(AccountingRulesConstants.NUMBER_OF_INTEREST_DAYS, interestDaysInConfig);
}
}
private void checkDigitsAfterDecimalMultiple(int digitsAfterDecimalInt, String multiple) {
Short digitsAfterDecimal = (short) digitsAfterDecimalInt;
MifosConfigurationManager.getInstance().setProperty(AccountingRulesConstants.DIGITS_AFTER_DECIMAL,
digitsAfterDecimal);
assertEquals(new BigDecimal(multiple), AccountingRules.getDigitsAfterDecimalMultiple(TestUtils.RUPEE));
}
@Test
public void testGetDigitsAfterDecimalMultiple() {
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
Short digitsAfterDecimalSaved = AccountingRules.getDigitsAfterDecimal();
try {
checkDigitsAfterDecimalMultiple(2, "0.01");
checkDigitsAfterDecimalMultiple(1, "0.1");
checkDigitsAfterDecimalMultiple(0, "1");
checkDigitsAfterDecimalMultiple(-1, "10");
checkDigitsAfterDecimalMultiple(-2, "100");
} finally {
configMgr.setProperty(AccountingRulesConstants.DIGITS_AFTER_DECIMAL, digitsAfterDecimalSaved);
}
}
@Ignore
@Test
public void globalMulticurrencyFlagWorks() {
assertFalse(AccountingRules.isMultiCurrencyEnabled());
List<String> codes = new ArrayList<String>();
codes.add("LBP");
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
try {
configMgr.setProperty(AccountingRulesConstants.ADDITIONAL_CURRENCY_CODES, codes);
assertTrue(AccountingRules.isMultiCurrencyEnabled());
} finally {
configMgr.clearProperty(AccountingRulesConstants.ADDITIONAL_CURRENCY_CODES);
}
}
@Test(expected = IllegalArgumentException.class)
public void alternateCurrenciesNotConfigured() {
AccountingRules.getDigitsAfterDecimal(TestUtils.EURO);
}
@Ignore
@Test
public void digitsAfterDecimalFallsBackToDefault() {
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
try {
configMgr.setProperty(AccountingRulesConstants.ADDITIONAL_CURRENCY_CODES, TestUtils.EURO.getCurrencyCode());
assertEquals(new Short("1"), AccountingRules.getDigitsAfterDecimal(TestUtils.EURO));
} finally {
configMgr.clearProperty(AccountingRulesConstants.ADDITIONAL_CURRENCY_CODES);
}
}
@Test
public void canConfigureAlternateCurrencyWithNonDefaultDigitsAfterDecimal() {
MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance();
try {
configMgr.setProperty(AccountingRulesConstants.ADDITIONAL_CURRENCY_CODES, TestUtils.EURO.getCurrencyCode());
configMgr.setProperty(AccountingRulesConstants.DIGITS_AFTER_DECIMAL + "."
+ TestUtils.EURO.getCurrencyCode(), (short) 2);
assertEquals(new Short("2"), AccountingRules.getDigitsAfterDecimal(TestUtils.EURO));
} finally {
configMgr.clearProperty(AccountingRulesConstants.ADDITIONAL_CURRENCY_CODES);
configMgr.clearProperty(AccountingRulesConstants.DIGITS_AFTER_DECIMAL + "."
+ TestUtils.EURO.getCurrencyCode());
}
}
/**
* Example usage: LBP should round to the 10s or 100s. Not sure if
* DigitsAfterDecimal is the correct configuration option (there may be
* several that need to go negative).
*
* See: <a href="http://mingle.mifos.org/projects/mifos/cards/2306">Card
* 2306</a> and <a href="http://mifosforge.jira.com/browse/MIFOS-2600">Issue
* 2600</a>.
*/
@Test
public void canConfigureNegativeDigitsAfterDecimal() {
// TODO: implement
}
}