/*
* Copyright (c) 2012 Denis Solonenko.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
package ru.orangesoftware.financisto2.test.db;
import java.util.Map;
import ru.orangesoftware.financisto2.db.TransactionsTotalCalculator;
import ru.orangesoftware.financisto2.filter.WhereFilter;
import ru.orangesoftware.financisto2.model.Account;
import ru.orangesoftware.financisto2.model.Category;
import ru.orangesoftware.financisto2.model.Currency;
import ru.orangesoftware.financisto2.model.Total;
import ru.orangesoftware.financisto2.model.Transaction;
import ru.orangesoftware.financisto2.test.builders.AccountBuilder;
import ru.orangesoftware.financisto2.test.builders.CategoryBuilder;
import ru.orangesoftware.financisto2.test.builders.CurrencyBuilder;
import ru.orangesoftware.financisto2.test.builders.DateTime;
import ru.orangesoftware.financisto2.test.builders.RateBuilder;
import ru.orangesoftware.financisto2.test.builders.TransactionBuilder;
import ru.orangesoftware.financisto2.test.builders.TransferBuilder;
/**
* Created by IntelliJ IDEA.
* User: denis.solonenko
* Date: 1/31/12 8:19 PM
*/
public class TransactionsTotalCalculatorTest extends AbstractDbTest {
Currency c1, c2, c3, c4;
Account a1, a2, a3;
Transaction a1t1_09th, a3t1_10th, a1t2_17th, a2t1_17th, a2t2_18th, a1t3_20th, a1t4_22nd, a1t5_23rd, a1t5_23rd_s1, a1t5_23rd_s2;
float r_c1c2_17th = 0.78592f;
float r_c1c2_18th = 0.78635f;
float r_c1c3_5th = 0.62510f;
float r_c2c3_5th = 0.12453f;
float r_c2c1_17th = 1f / r_c1c2_17th;
float r_c2c1_18th = 1f / r_c1c2_18th;
TransactionsTotalCalculator c;
@Override
public void setUp() throws Exception {
super.setUp();
Map<String, Category> categories = CategoryBuilder.createDefaultHierarchy(categoryRepository);
c1 = CurrencyBuilder.withDb(db).name("USD").title("Dollar").symbol("$").makeDefault().create();
c2 = CurrencyBuilder.withDb(db).name("EUR").title("Euro").symbol("€").create();
c3 = CurrencyBuilder.withDb(db).name("SGD").title("Singapore Dollar").symbol("S$").create();
c4 = CurrencyBuilder.withDb(db).name("RUB").title("Russian Ruble").symbol("p.").create();
c = new TransactionsTotalCalculator(db, WhereFilter.empty());
RateBuilder.withDb(db).from(c1).to(c2).at(DateTime.date(2012, 1, 17)).rate(r_c1c2_17th).create();
RateBuilder.withDb(db).from(c1).to(c2).at(DateTime.date(2012, 1, 18)).rate(r_c1c2_18th).create();
RateBuilder.withDb(db).from(c1).to(c3).at(DateTime.date(2012, 1, 5)).rate(r_c1c3_5th).create();
RateBuilder.withDb(db).from(c2).to(c3).at(DateTime.date(2012, 1, 5)).rate(r_c2c3_5th).create();
a1 = AccountBuilder.withDb(db).title("Cash").currency(c1).create();
a2 = AccountBuilder.withDb(db).title("Bank").currency(c2).create();
a3 = AccountBuilder.withDb(db).title("Cash2").currency(c1).doNotIncludeIntoTotals().create();
/*
a1t1 09 A1 USD -100 (orig: EUR -20)
a3t1_10th 10 A3 SGD +555
a1t2_17th 17 A1 USD +100
a2t1_17th 17 A2 EUR -100
a2t2_18th 18 A2 EUR -250
a1t3_20th 20 A1 USD -50 FT
a2t3 20 A2 EUR +20 TT
a1t4_22nd 22 A1 USD -450
a1t5_23rd 23 A1 USD -50 S
23 A1 USD -150 FT S
23 A2 EUR +100 TT S
*/
a1t1_09th = TransactionBuilder.withDb(db).account(a1).dateTime(DateTime.date(2012, 1, 9)).amount(-100).originalAmount(c2, -20).create();
a3t1_10th = TransactionBuilder.withDb(db).account(a3).dateTime(DateTime.date(2012, 1, 10)).amount(555).create();
a1t2_17th = TransactionBuilder.withDb(db).account(a1).dateTime(DateTime.date(2012, 1, 17).at(13, 30, 0, 0)).amount(100).create();
a2t1_17th = TransactionBuilder.withDb(db).account(a2).dateTime(DateTime.date(2012, 1, 17).at(13, 30, 0, 0)).amount(-100).create();
a2t2_18th = TransactionBuilder.withDb(db).account(a2).dateTime(DateTime.date(2012, 1, 18).at(18, 40, 0, 0)).amount(-250).create();
a1t3_20th = TransferBuilder.withDb(db).fromAccount(a1).toAccount(a2).dateTime(DateTime.date(2012, 1, 20).atNoon()).fromAmount(-50).toAmount(20).create();
a1t4_22nd = TransactionBuilder.withDb(db).account(a1).dateTime(DateTime.date(2012, 1, 22).atMidnight()).amount(-450).create();
a1t5_23rd = TransactionBuilder.withDb(db).account(a1).dateTime(DateTime.date(2012, 1, 23)).amount(-200)
.withSplit(categories.get("A1"), -50)
.withTransferSplit(a2, -150, 100)
.create();
a1t5_23rd_s1 = a1t5_23rd.splits.get(0);
a1t5_23rd_s2 = a1t5_23rd.splits.get(1);
}
public void test_should_return_error_if_exchange_rate_not_available() {
TransactionBuilder.withDb(db).account(a1).dateTime(DateTime.date(2012, 1, 10)).amount(1).create();
assertFalse(c.getAccountBalance(c1, a1.id).isError()); // no conversion
assertFalse(c.getAccountBalance(c3, a1.id).isError()); // all rates are available
Total total = c.getAccountBalance(c2, a1.id);
assertTrue(total.isError()); // no rate available on 10th
total = c.getAccountBalance(c4, a1.id);
assertTrue(total.isError()); // no rates at all
}
public void test_should_calculate_blotter_total_in_multiple_currencies() {
Total[] totals = c.getTransactionsBalance();
assertEquals(2, totals.length);
assertEquals(-700, totals[0].balance);
assertEquals(-230, totals[1].balance);
}
public void test_should_calculate_blotter_total_in_home_currency() {
assertEquals((long)(-100f +100f -(1f/ r_c1c2_17th)*100f -(1f/ r_c1c2_18th)*250f -50f +50f -450f -50f -150f +150f), c.getBlotterBalance(c1).balance);
assertEquals((long)(-20f +r_c1c2_17th *100f -100f -250f -20f +20f - r_c1c2_18th *450f - r_c1c2_18th *50f -100f +100f), c.getBlotterBalance(c2).balance);
assertEquals(c.getBlotterBalance(c1).balance, c.getBlotterBalanceInHomeCurrency().balance);
}
public void test_should_calculate_account_total_in_home_currency() {
//no conversion
assertEquals(a1t1_09th.fromAmount + a1t2_17th.fromAmount + a1t3_20th.fromAmount + a1t4_22nd.fromAmount + a1t5_23rd.fromAmount, c.getAccountBalance(c1, a1.id).balance);
//note that a1t3_20th is taken from the transfer without conversion
assertEquals((long) (a1t1_09th.originalFromAmount + r_c1c2_17th*a1t2_17th.fromAmount - a1t3_20th.toAmount + r_c1c2_18th *a1t4_22nd.fromAmount + r_c1c2_18th *a1t5_23rd.fromAmount), c.getAccountBalance(c2, a1.id).balance);
//no conversion
assertEquals(a2t1_17th.fromAmount + a2t2_18th.fromAmount + a1t3_20th.toAmount + a1t5_23rd_s2.toAmount, c.getAccountBalance(c2, a2.id).balance);
//conversion+transfers
assertEquals((long) (r_c2c1_17th *a2t1_17th.fromAmount + r_c2c1_18th *a2t2_18th.fromAmount - a1t3_20th.fromAmount - a1t5_23rd_s2.fromAmount), c.getAccountBalance(c1, a2.id).balance);
//conversions
assertEquals((long) (r_c1c3_5th * (a1t1_09th.fromAmount + a1t2_17th.fromAmount + a1t3_20th.fromAmount + a1t4_22nd.fromAmount + a1t5_23rd.fromAmount)), c.getAccountBalance(c3, a1.id).balance);
assertEquals((long) (r_c2c3_5th * (a2t1_17th.fromAmount + a2t2_18th.fromAmount + a1t3_20th.toAmount + a1t5_23rd_s2.toAmount)), c.getAccountBalance(c3, a2.id).balance);
}
public void test_should_calculate_account_total_in_home_currency_with_big_amounts() {
TransactionBuilder.withDb(db).account(a1).dateTime(DateTime.date(2012, 1, 10)).amount(45000000000L).create();
//no conversion
assertEquals(45000000000L+(long) (-100f +100f -50f -450f -50f -150f), c.getAccountBalance(c1, a1.id).balance);
}
}