Skip to content
Permalink
Browse files

Added Trade Republic PDF extractor

Issue: #1163
  • Loading branch information
buchen committed Jun 17, 2019
1 parent 5a5ba92 commit 58e4ff574261a0b457e75a70443b914245cf01f7
@@ -0,0 +1,34 @@
PDF Author: ''
PDFBox Version: 1.8.16
-----------------------------------------
TRADE REPUBLIC BANK GMBH KASTANIENALLEE 32 10435 BERLIN
Max Mustermann SEITE 1 von 1
Beispielstraße 1 DATUM 13.05.2019
D 12345 Stadt ORDER dead-beef
AUSFÜHRUNG ab12-c3de
DEPOT 123456789
WERTPAPIERABRECHNUNG
ÜBERSICHT
Market-Order Kauf am 13.05.2019, um 12:14 Uhr an der Lang & Schwarz Exchange.
Der Kontrahent der Transaktion ist Lang & Schwarz TradeCenter AG & Co. KG.
POSITION ANZAHL KURS BETRAG
iShs Core MSCI EM IMI U.ETF 1 Stk. 24,045 EUR 24,05 EUR
Registered Shares o.N.
IE00BKM4GZ66
GESAMT 24,05 EUR
ABRECHNUNG
POSITION BETRAG
Fremdkostenzuschlag -1,00 EUR
GESAMT -25,05 EUR
BUCHUNG
VERRECHNUNGSKONTO VALUTA BETRAG
DE12345678901234567890 15.05.2019 -25,05 EUR
iShs Core MSCI EM IMI U.ETF Registered Shares o.N. in Wertpapierrechnung.
Lagerland: Grossbritannien
Diese Abrechnung wird maschinell erstellt und daher nicht unterschrieben.
Sofern keine Umsatzsteuer ausgewiesen ist, handelt es sich gem. § 4 Nr. 8 UStG um eine umsatzsteuerfreie
Leistung.
Trade Republic Bank GmbH www.traderepublic.com Sitz der Gesellschaft: Düsseldorf Geschäftsführer
Kastanienallee 32 service@traderepublic.com AG Düsseldorf HRB 85864 Ingo Hillen
10435 Berlin USt-ID DE307510626 Karsten Müller
ABRE / 13.05.2019 / 23456789 / 1a23-b45c
@@ -0,0 +1,34 @@
PDF Author: ''
PDFBox Version: 1.8.16
-----------------------------------------
TRADE REPUBLIC BANK GMBH KASTANIENALLEE 32 10435 BERLIN
Max Mustermann SEITE 1 von 1
Straße 1 DATUM 13.05.2019
D 12345 Stadt ORDER 1234-abcd
AUSFÜHRUNG a1b2-3456
DEPOT 123456789
WERTPAPIERABRECHNUNG
ÜBERSICHT
Limit-Order Kauf am 13.05.2019, um 13:59 Uhr an der Lang & Schwarz Exchange.
Der Kontrahent der Transaktion ist Lang & Schwarz TradeCenter AG & Co. KG.
POSITION ANZAHL KURS BETRAG
Beyond Meat Inc. 1 Stk. 58,19 EUR 58,19 EUR
Registered Shares o.N.
US08862E1091
GESAMT 58,19 EUR
ABRECHNUNG
POSITION BETRAG
Fremdkostenzuschlag -1,00 EUR
GESAMT -59,19 EUR
BUCHUNG
VERRECHNUNGSKONTO VALUTA BETRAG
DE12345678901234567890 15.05.2019 -59,19 EUR
Beyond Meat Inc. Registered Shares o.N. in Wertpapierrechnung.
Lagerland: USA
Diese Abrechnung wird maschinell erstellt und daher nicht unterschrieben.
Sofern keine Umsatzsteuer ausgewiesen ist, handelt es sich gem. § 4 Nr. 8 UStG um eine umsatzsteuerfreie
Leistung.
Trade Republic Bank GmbH www.traderepublic.com Sitz der Gesellschaft: Düsseldorf Geschäftsführer
Kastanienallee 32 service@traderepublic.com AG Düsseldorf HRB 85864 Ingo Hillen
10435 Berlin USt-ID DE307510626 Karsten Müller
ABRE / 13.05.2019 / 23456789/ 1234-a56c
@@ -0,0 +1,33 @@
PDF Author: ''
PDFBox Version: 1.8.16
-----------------------------------------
TRADE REPUBLIC BANK GMBH KASTANIENALLEE 32 10435 BERLIN
<vorname> <name> SEITE 1 von 1
<adresse> DATUM 17.06.2019
D <PLZ> Tespe ORDER fd98-0283
AUSFÜHRUNG 51cb-50a8
DEPOT <depotnummer>
WERTPAPIERABRECHNUNG
ÜBERSICHT
Market-Order Kauf am 17.06.2019, um 12:27 Uhr an der Lang & Schwarz Exchange.
Der Kontrahent der Transaktion ist Lang & Schwarz TradeCenter AG & Co. KG.
POSITION ANZAHL KURS BETRAG
Tesla Inc. 1 Stk. 192,08 EUR 192,08 EUR
Registered Shares DL-,001
US88160R1014
GESAMT 192,08 EUR
ABRECHNUNG
POSITION BETRAG
Fremdkostenzuschlag -1,00 EUR
GESAMT -193,08 EUR
BUCHUNG
VERRECHNUNGSKONTO VALUTA BETRAG
DE32110101008889504147 19.06.2019 -193,08 EUR
Tesla Inc. Registered Shares DL-,001 in Girosammelverwahrung.
Diese Abrechnung wird maschinell erstellt und daher nicht unterschrieben.
Sofern keine Umsatzsteuer ausgewiesen ist, handelt es sich gem. § 4 Nr. 8 UStG um eine umsatzsteuerfreie
Leistung.
Trade Republic Bank GmbH www.traderepublic.com Sitz der Gesellschaft: Düsseldorf Geschäftsführer
Kastanienallee 32 service@traderepublic.com AG Düsseldorf HRB 85864 Ingo Hillen
10435 Berlin USt-ID DE307510626 Karsten Müller
ABRE / 17.06.2019 / 23675468 / af69-b0d8
@@ -0,0 +1,134 @@
package name.abuchen.portfolio.datatransfer.pdf.traderepublic;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
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.datatransfer.actions.AssertImportActions;
import name.abuchen.portfolio.datatransfer.pdf.PDFInputFile;
import name.abuchen.portfolio.datatransfer.pdf.TradeRepublicPDFExtractor;
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.CurrencyUnit;
import name.abuchen.portfolio.money.Money;
import name.abuchen.portfolio.money.Values;

@SuppressWarnings("nls")
public class TradeRepublicPDFExtractorTest
{
@Test
public void testKauf01()
{
TradeRepublicPDFExtractor extractor = new TradeRepublicPDFExtractor(new Client());

List<Exception> errors = new ArrayList<>();

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf01.txt"), errors);

assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);

// check security
Optional<Item> item = results.stream().filter(i -> i instanceof SecurityItem).findFirst();
Security security = ((SecurityItem) item.orElseThrow(IllegalArgumentException::new)).getSecurity();
assertThat(security.getIsin(), is("IE00BKM4GZ66"));
assertThat(security.getName(), is("iShs Core MSCI EM IMI U.ETF"));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));

// check transaction
item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
BuySellEntry entry = (BuySellEntry) item.orElseThrow(IllegalArgumentException::new).getSubject();
PortfolioTransaction tx = entry.getPortfolioTransaction();

assertThat(tx.getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY));

assertThat(tx.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(25.05))));
assertThat(tx.getDateTime(), is(LocalDateTime.parse("2019-05-13T12:14")));
assertThat(tx.getShares(), is(Values.Share.factorize(1)));
assertThat(tx.getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1))));
}

@Test
public void testKauf02()
{
TradeRepublicPDFExtractor extractor = new TradeRepublicPDFExtractor(new Client());

List<Exception> errors = new ArrayList<>();

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf02.txt"), errors);

assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);

// check security
Optional<Item> item = results.stream().filter(i -> i instanceof SecurityItem).findFirst();
Security security = ((SecurityItem) item.orElseThrow(IllegalArgumentException::new)).getSecurity();
assertThat(security.getIsin(), is("US08862E1091"));
assertThat(security.getName(), is("Beyond Meat Inc."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));

// check transaction
item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
BuySellEntry entry = (BuySellEntry) item.orElseThrow(IllegalArgumentException::new).getSubject();
PortfolioTransaction tx = entry.getPortfolioTransaction();

assertThat(tx.getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY));

assertThat(tx.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(59.19))));
assertThat(tx.getDateTime(), is(LocalDateTime.parse("2019-05-13T13:59")));
assertThat(tx.getShares(), is(Values.Share.factorize(1)));
assertThat(tx.getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1))));
}

@Test
public void testKauf03()
{
TradeRepublicPDFExtractor extractor = new TradeRepublicPDFExtractor(new Client());

List<Exception> errors = new ArrayList<>();

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf03.txt"), errors);

assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);

// check security
Optional<Item> item = results.stream().filter(i -> i instanceof SecurityItem).findFirst();
Security security = ((SecurityItem) item.orElseThrow(IllegalArgumentException::new)).getSecurity();
assertThat(security.getIsin(), is("US88160R1014"));
assertThat(security.getName(), is("Tesla Inc."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));

// check transaction
item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
BuySellEntry entry = (BuySellEntry) item.orElseThrow(IllegalArgumentException::new).getSubject();
PortfolioTransaction tx = entry.getPortfolioTransaction();

assertThat(tx.getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY));

assertThat(tx.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(193.08))));
assertThat(tx.getDateTime(), is(LocalDateTime.parse("2019-06-17T12:27")));
assertThat(tx.getShares(), is(Values.Share.factorize(1)));
assertThat(tx.getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1))));
}
}
@@ -44,6 +44,7 @@ public PDFImportAssistant(Client client, List<File> files)
extractors.add(new UnicreditPDFExtractor(client));
extractors.add(new HelloBankPDFExtractor(client));
extractors.add(new ViacPDFExtractor(client));
extractors.add(new TradeRepublicPDFExtractor(client));
}

public Map<Extractor, List<Item>> run(IProgressMonitor monitor, Map<File, List<Exception>> errors)
@@ -0,0 +1,75 @@
package name.abuchen.portfolio.datatransfer.pdf;

import name.abuchen.portfolio.datatransfer.pdf.PDFParser.Block;
import name.abuchen.portfolio.datatransfer.pdf.PDFParser.DocumentType;
import name.abuchen.portfolio.datatransfer.pdf.PDFParser.Transaction;
import name.abuchen.portfolio.model.BuySellEntry;
import name.abuchen.portfolio.model.Client;
import name.abuchen.portfolio.model.PortfolioTransaction;
import name.abuchen.portfolio.model.Transaction.Unit;
import name.abuchen.portfolio.money.Money;

public class TradeRepublicPDFExtractor extends AbstractPDFExtractor
{
public TradeRepublicPDFExtractor(Client client)
{
super(client);

addBankIdentifier("TRADE REPUBLIC"); //$NON-NLS-1$

addBuyTransaction();
}

@SuppressWarnings("nls")
private void addBuyTransaction()
{
DocumentType type = new DocumentType("Order Kauf");
this.addDocumentTyp(type);

Block block = new Block(".*Order Kauf.*");
type.addBlock(block);
block.set(new Transaction<BuySellEntry>()

.subject(() -> {
BuySellEntry entry = new BuySellEntry();
entry.setType(PortfolioTransaction.Type.BUY);
return entry;
})

.section("name", "isin", "shares") //
.find("POSITION ANZAHL KURS BETRAG") //
.match("(?<name>.*) (?<shares>[\\d+,.]*) Stk. ([\\d+,.]*) (\\w{3}+) ([\\d+,.]*) (\\w{3}+)$") //
.match(".*") //
.match("(?<isin>.*)").assign((t, v) -> {
t.setSecurity(getOrCreateSecurity(v));
t.setShares(asShares(v.get("shares")));
})

.section("amount", "currency") //
.match("GESAMT -(?<amount>[\\d+,.]*) (?<currency>\\w{3}+)") //
.assign((t, v) -> {
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
})

.section("date", "time") //
.match(".*Order Kauf am (?<date>\\d+.\\d+.\\d{4}+), um (?<time>\\d+:\\d+) Uhr.*")
.assign((t, v) -> t.setDate(asDate(v.get("date"), v.get("time"))))

.section("fee", "currency") //
.optional() //
.match("Fremdkostenzuschlag -(?<fee>[\\d+,.]*) (?<currency>\\w{3}+)")
.assign((t, v) -> t.getPortfolioTransaction()
.addUnit(new Unit(Unit.Type.FEE,
Money.of(asCurrencyCode(v.get("currency")),
asAmount(v.get("fee"))))))

.wrap(BuySellEntryItem::new));
}

@Override
public String getLabel()
{
return "Trade Republic"; //$NON-NLS-1$
}
}

0 comments on commit 58e4ff5

Please sign in to comment.
You can’t perform that action at this time.