package org.internna.ossmoney.mvc;
import java.util.Map;
import java.util.Set;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.HashMap;
import java.util.Calendar;
import java.util.Currency;
import java.util.ArrayList;
import java.math.BigDecimal;
import org.junit.Test;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.internna.ossmoney.model.Account;
import org.internna.ossmoney.model.Category;
import org.internna.ossmoney.util.DateUtils;
import org.internna.ossmoney.cache.CacheStore;
import org.internna.ossmoney.model.Subcategory;
import org.internna.ossmoney.util.SecurityUtils;
import org.internna.ossmoney.model.AccountTransaction;
import org.internna.ossmoney.model.security.UserDetails;
import org.internna.ossmoney.model.support.IncomeExpense;
import org.internna.ossmoney.model.support.NameValuePair;
import org.springframework.ui.ModelMap;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.test.context.transaction.TransactionConfiguration;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback = true)
@ContextConfiguration(locations = {"classpath:/META-INF/spring/applicationContext.xml", "classpath:/META-INF/spring/applicationContext-security.xml"})
public class WidgetControllerTest {
@Autowired private CacheStore cache;
@Autowired private AuthenticationManager authenticationManager;
private UserDetails user;
private WidgetController controller = new WidgetController();
@Before
public void setup() {
controller.setCache(cache);
SecurityUtils.authenticate(authenticationManager, "jose", "jose");
user = UserDetails.findCurrentUser();
}
@After
public void clean() {
cache.invalidate(user);
assertTrue("Cache is empty (no side effects", cache.isEmpty());
}
@Test
public void testIncomeAndExpenses() {
controller.incomeVsExpenses("last_quarter", new ModelMap());
assertNotNull("Cache updated", cache.getIncomeAndExpenses(user, "last_quarter"));
}
@Test
public void testCalculateIncomeAndExpenses() {
Account account = new Account();
account.setLocale(Locale.GERMANY);
Account usAccount = new Account();
usAccount.setLocale(Locale.US);
List<AccountTransaction> transactions = null;
Map<Currency, NameValuePair<BigDecimal, BigDecimal>> data = controller.calculateIncomeAndExpenses(transactions);
transactions = new ArrayList<AccountTransaction>();
AccountTransaction transaction = new AccountTransaction();
transaction.setAccount(account);
transaction.setOperationDate(new Date());
transaction.setAmount(BigDecimal.TEN);
transactions.add(transaction);
data = controller.calculateIncomeAndExpenses(transactions);
assertEquals("Some income", BigDecimal.TEN, data.get(Currency.getInstance(account.getLocale())).getKey());
AccountTransaction expense = new AccountTransaction();
expense.setOperationDate(new Date());
expense.setAmount(new BigDecimal(-4));
expense.setAccount(account);
transactions.add(expense);
data = controller.calculateIncomeAndExpenses(transactions);
assertEquals("An expense", new BigDecimal(4), data.get(Currency.getInstance(account.getLocale())).getValue());
AccountTransaction otherExpense = new AccountTransaction();
otherExpense.setAccount(account);
otherExpense.setOperationDate(new Date());
otherExpense.setAmount(new BigDecimal(-6));
transactions.add(otherExpense);
data = controller.calculateIncomeAndExpenses(transactions);
assertEquals("Several expenses", BigDecimal.TEN, data.get(Currency.getInstance(account.getLocale())).getValue());
AccountTransaction usTransaction = new AccountTransaction();
usTransaction.setAccount(usAccount);
usTransaction.setOperationDate(new Date());
usTransaction.setAmount(BigDecimal.ONE);
transactions.add(usTransaction);
data = controller.calculateIncomeAndExpenses(transactions);
assertEquals("Some $ income", BigDecimal.ONE, data.get(Currency.getInstance(usAccount.getLocale())).getKey());
}
@Test
public void testGetMaxValue() {
Map<Currency, NameValuePair<BigDecimal, BigDecimal>> data = new HashMap<Currency, NameValuePair<BigDecimal, BigDecimal>>();
NameValuePair<BigDecimal, BigDecimal> incomeExpense = new NameValuePair<BigDecimal, BigDecimal>(BigDecimal.ONE, BigDecimal.ZERO);
NameValuePair<BigDecimal, BigDecimal> incomeExpense2 = new NameValuePair<BigDecimal, BigDecimal>(BigDecimal.ZERO, BigDecimal.TEN);
data.put(Currency.getInstance("USD"), incomeExpense);
data.put(Currency.getInstance("EUR"), incomeExpense2);
assertTrue("Chart max value", 11L == controller.getMaxValue(data));
incomeExpense.setKey(new BigDecimal(36));
data.put(Currency.getInstance("USD"), incomeExpense);
assertTrue("Chart max value incremented", 40L == controller.getMaxValue(data));
}
@Test
public void testExpensesByCategory() {
controller.expensesByCategory("last_quarter", new ModelMap());
assertNotNull("Cache updated", cache.getExpensesByCategory(user, "last_quarter"));
}
@Test
public void testOrganizeByCategory() {
Category income = new Category();
income.setIncome(Boolean.TRUE);
Subcategory fooIncome = new Subcategory();
fooIncome.setParentCategory(income);
Category expense = new Category();
expense.setIncome(Boolean.FALSE);
Subcategory fooExpense = new Subcategory();
fooExpense.setId(1L);
fooExpense.setParentCategory(expense);
fooExpense.setCategory("fooExpense");
Account account = new Account();
account.setLocale(Locale.GERMANY);
Account usAccount = new Account();
usAccount.setLocale(Locale.US);
List<AccountTransaction> transactions = null;
Map<Currency, Map<Subcategory, BigDecimal>> data = controller.organizeByCategory(transactions);
assertEquals("No data organized", 0, data.size());
transactions = new ArrayList<AccountTransaction>();
AccountTransaction transaction = new AccountTransaction();
transaction.setAccount(account);
transaction.setOperationDate(new Date());
transaction.setAmount(BigDecimal.TEN);
transaction.setSubcategory(fooIncome);
transactions.add(transaction);
data = controller.organizeByCategory(transactions);
assertEquals("No expense data", 0, data.size());
AccountTransaction expensetransaction = new AccountTransaction();
expensetransaction.setAccount(account);
expensetransaction.setOperationDate(new Date());
expensetransaction.setAmount(new BigDecimal(-75));
expensetransaction.setSubcategory(fooExpense);
transactions.add(expensetransaction);
data = controller.organizeByCategory(transactions);
assertEquals("Some expense data", 1, data.size());
assertEquals("Some categories", 1, data.get(Currency.getInstance(account.getLocale())).size());
assertEquals("Some total amount", new BigDecimal(75), data.get(Currency.getInstance(account.getLocale())).get(fooExpense));
AccountTransaction otherExpenseInCategory = new AccountTransaction();
otherExpenseInCategory.setAccount(account);
otherExpenseInCategory.setOperationDate(new Date());
otherExpenseInCategory.setAmount(new BigDecimal(-75));
otherExpenseInCategory.setSubcategory(fooExpense);
transactions.add(otherExpenseInCategory);
data = controller.organizeByCategory(transactions);
assertEquals("Same categories", 1, data.get(Currency.getInstance(account.getLocale())).size());
assertEquals("Added total amount", new BigDecimal(150), data.get(Currency.getInstance(account.getLocale())).get(fooExpense));
AccountTransaction otherExpense = new AccountTransaction();
otherExpense.setAccount(usAccount);
otherExpense.setOperationDate(new Date());
otherExpense.setAmount(new BigDecimal(-75));
otherExpense.setSubcategory(fooExpense);
transactions.add(otherExpense);
data = controller.organizeByCategory(transactions);
assertEquals("Two currencies", 2, data.size());
assertEquals("Added total amount", new BigDecimal(75), data.get(Currency.getInstance(usAccount.getLocale())).get(fooExpense));
Category expense2 = new Category();
expense2.setIncome(Boolean.FALSE);
Subcategory fooExpense2 = new Subcategory();
fooExpense2.setId(2L);
fooExpense2.setParentCategory(expense2);
fooExpense2.setCategory("fooExpense2");
AccountTransaction otherExpenseInNewCategory = new AccountTransaction();
otherExpenseInNewCategory.setAccount(account);
otherExpenseInNewCategory.setOperationDate(new Date());
otherExpenseInNewCategory.setAmount(new BigDecimal(-75));
otherExpenseInNewCategory.setSubcategory(fooExpense2);
transactions.add(otherExpenseInNewCategory);
data = controller.organizeByCategory(transactions);
assertEquals("Two categories", 2, data.get(Currency.getInstance(account.getLocale())).size());
assertEquals("Total amount not changed", new BigDecimal(150), data.get(Currency.getInstance(account.getLocale())).get(fooExpense));
assertEquals("More amounts", new BigDecimal(75), data.get(Currency.getInstance(account.getLocale())).get(fooExpense2));
}
@Test
public void testNetWorthOverTime() {
controller.netWorthOverTime(11, new ModelMap());
assertNotNull("Cache updated", cache.getNetWorthOverTime(user, 11));
}
@Test
public void testCalculateWealth() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, -3);
Account account = new Account();
account.setLocale(Locale.GERMANY);
account.setOpened(calendar.getTime());
account.setInitialBalance(BigDecimal.TEN);
Account usAccount = new Account();
usAccount.setLocale(Locale.US);
usAccount.setOpened(calendar.getTime());
usAccount.setInitialBalance(BigDecimal.ONE);
Set<Account> accounts = new java.util.HashSet<Account>(2);
accounts.add(account);
accounts.add(usAccount);
calendar.add(Calendar.MONTH, 1);
AccountTransaction transaction = new AccountTransaction();
transaction.setAccount(account);
calendar.setTime(new Date());
calendar.add(Calendar.DATE, -1);
transaction.setOperationDate(calendar.getTime());
transaction.setAmount(BigDecimal.TEN);
Date[] dates = DateUtils.dates(5);
Map<Currency, Map<Date, IncomeExpense>> data = controller.calculateWealth(dates, accounts);
assertEquals("Two currencies", 2, data.size());
assertEquals("Before creation", BigDecimal.ZERO, data.get(Currency.getInstance(account.getLocale())).get(dates[0]).getKey());
assertEquals("Added transactions", new BigDecimal(20), data.get(Currency.getInstance(Locale.GERMANY)).get(dates[5]).getKey());
}
@Test
public void testExpensesOverTime() {
controller.expensesOverTime(11, new ModelMap());
assertNotNull("Cache updated", cache.getIncomeVsExpensesOverTime(user, 11));
}
@Test
public void testIncomeVsExpensesOverTime() {
controller.incomeVsExpensesOverTime(11, new ModelMap());
assertNotNull("Cache updated", cache.getIncomeVsExpensesOverTime(user, 11));
}
@Test
public void testCalculateIncomeVsExpensesOverTime() {
Account account = Account.findAccount(1L);
Set<Account> accounts = new java.util.HashSet<Account>(2);
accounts.add(account);
Date[] dates = new Date[1];
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, 10);
calendar.set(Calendar.YEAR, 2010);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
dates[0] = calendar.getTime();
Map<Currency, Map<Date, IncomeExpense>> data = controller.calculateIncomeVsExpensesOverTime(dates, accounts);
assertEquals("One currency only", 1, data.size());
assertEquals("Income calculated", new Double(785D), new Double(data.get(Currency.getInstance(account.getLocale())).get(dates[0]).getKey().doubleValue()));
assertEquals("Expenses calculated", new Double(126D), new Double(data.get(Currency.getInstance(account.getLocale())).get(dates[0]).getValue().doubleValue()));
}
}