package name.abuchen.portfolio.datatransfer;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
import name.abuchen.portfolio.datatransfer.Extractor.BuySellEntryItem;
import name.abuchen.portfolio.datatransfer.Extractor.Item;
import name.abuchen.portfolio.datatransfer.Extractor.SecurityItem;
import name.abuchen.portfolio.model.AccountTransaction;
import name.abuchen.portfolio.model.BuySellEntry;
import name.abuchen.portfolio.model.Client;
import name.abuchen.portfolio.model.PortfolioTransaction;
import name.abuchen.portfolio.model.Security;
import name.abuchen.portfolio.model.Transaction.Unit;
import name.abuchen.portfolio.money.Money;
import name.abuchen.portfolio.money.Quote;
import name.abuchen.portfolio.money.Values;
@SuppressWarnings("nls")
public class IBFlexStatementExtractorTest
{
private InputStream activityStatement;
private InputStream otherFile;
public IBFlexStatementExtractorTest()
{
activityStatement = getClass().getResourceAsStream("IBActivityStatement.xml");
otherFile = getClass().getResourceAsStream("pdf/comdirect/comdirectGutschrift.txt");
}
@Test
public void testIBAcitvityStatement() throws IOException
{
Client client = new Client();
IBFlexStatementExtractor extractor = new IBFlexStatementExtractor(client);
List<Exception> errors = new ArrayList<Exception>();
extractor.importActivityStatement(activityStatement, errors);
List<Item> results = extractor.getResults();
results.stream().filter(i -> !(i instanceof SecurityItem))
.forEach(i -> assertThat(i.getAmount(), notNullValue()));
// 1 Error Messages for negative interest which is not yet supported
assertThat(errors.size(), is(1));
assertThat(results.size(), is(25));
assertFirstSecurity(results.stream().filter(i -> i instanceof SecurityItem).findFirst());
assertFirstTransaction(results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst());
assertSecondSecurity(results.stream().filter(i -> i instanceof SecurityItem)
.reduce((previous, current) -> current).get());
assertFourthTransaction(results.stream().filter(i -> i instanceof BuySellEntryItem).skip(3).findFirst());
// TODO Check CorporateActions
}
private void assertFirstSecurity(Optional<Item> item)
{
assertThat(item.isPresent(), is(true));
Security security = ((SecurityItem) item.get()).getSecurity();
assertThat(security.getIsin(), is("CA38501D2041"));
assertThat(security.getWkn(), is("80845553"));
assertThat(security.getName(), is("GRAN COLOMBIA GOLD CORP"));
assertThat(security.getTickerSymbol(), is("GCM.TO"));
assertThat(security.getCurrencyCode(), is("CAD"));
}
private void assertSecondSecurity(Item item)
{
// Why is the second Security the GCM after Split ??? expected to be UUU
Security security = ((SecurityItem) item).getSecurity();
assertThat(security.getIsin(), is("CA38501D5010"));
assertThat(security.getWkn(), is("129258970"));
assertThat(security.getName(),
is("GCM(CA38501D2041) SPLIT 1 FOR 25 (GCM, GRAN COLOMBIA GOLD CORP, CA38501D5010)"));
assertThat(security.getCurrencyCode(), is("CAD"));
// setting GCM.TO as ticker symbol
// currently fails because the exchange is empty in corporate actions.
}
private void assertFirstTransaction(Optional<Item> item)
{
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(BuySellEntry.class));
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY));
assertThat(entry.getPortfolioTransaction().getSecurity().getName(), is("GRAN COLOMBIA GOLD CORP"));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), is(Money.of("CAD", 1356_75L)));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2013-04-01")));
assertThat(entry.getPortfolioTransaction().getShares(), is(5000_000000L));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), is(Money.of("CAD", 6_75L)));
assertThat(entry.getPortfolioTransaction().getGrossPricePerShare(),
is(Quote.of("CAD", Values.Quote.factorize(0.27))));
}
private void assertFourthTransaction(Optional<Item> item)
{
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(BuySellEntry.class));
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY));
assertThat(entry.getPortfolioTransaction().getSecurity().getName(), is("URANIUM ONE INC."));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), is(Money.of("CAD", 232_00L)));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2013-01-02")));
assertThat(entry.getPortfolioTransaction().getShares(), is(100_000000L));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), is(Money.of("CAD", 1_00L)));
}
@Test
public void testThatExceptionIsAddedForNonFlexStatementDocuments() throws IOException
{
Client client = new Client();
IBFlexStatementExtractor extractor = new IBFlexStatementExtractor(client);
List<Exception> errors = new ArrayList<Exception>();
extractor.importActivityStatement(otherFile, errors);
List<Item> results = extractor.getResults();
assertThat(results.isEmpty(), is(true));
assertThat(errors.size(), is(1));
}
}