Skip to content

Commit

Permalink
Added new PDF Importer for J&T Direktbank (#3748)
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander Ott <45203494+Nirus2000@users.noreply.github.com>
  • Loading branch information
ZfT2 and Nirus2000 committed Jan 20, 2024
1 parent a51ff8f commit 1d68cbc
Show file tree
Hide file tree
Showing 7 changed files with 737 additions and 0 deletions.
@@ -0,0 +1,254 @@
package name.abuchen.portfolio.datatransfer.pdf.jtdirektbank;

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

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.Test;

import name.abuchen.portfolio.datatransfer.Extractor;
import name.abuchen.portfolio.datatransfer.Extractor.InputFile;
import name.abuchen.portfolio.datatransfer.Extractor.Item;
import name.abuchen.portfolio.datatransfer.Extractor.TransactionItem;
import name.abuchen.portfolio.datatransfer.pdf.JTDirektbankPDFExtractor;
import name.abuchen.portfolio.datatransfer.pdf.PDFInputFile;
import name.abuchen.portfolio.model.AccountTransaction;
import name.abuchen.portfolio.model.Client;
import name.abuchen.portfolio.money.CurrencyUnit;
import name.abuchen.portfolio.money.Values;

@SuppressWarnings("nls")
public class JTDirektbankPDFExtractorTest
{
@Test
public void testKontoauszug1()
{
JTDirektbankPDFExtractor extractor = new JTDirektbankPDFExtractor(new Client());
List<Exception> errors = new ArrayList<>();
List<Item> results = extractor.extract(loadFile("jtdirektbankKontoauszug1.txt"), errors);

assertThat(errors, empty());

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject()).getType() == AccountTransaction.Type.DEPOSIT)
.count(), is(1L));

Iterator<Extractor.Item> iter = results.stream().filter(i -> i instanceof TransactionItem).iterator();
Item item = iter.next();

AccountTransaction transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DEPOSIT));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-03-31T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(3000)));
}

@Test
public void testKontoauszug2()
{
JTDirektbankPDFExtractor extractor = new JTDirektbankPDFExtractor(new Client());
List<Exception> errors = new ArrayList<>();
List<Item> results = extractor.extract(loadFile("jtdirektbankKontoauszug2.txt"), errors);

assertThat(errors, empty());

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject()).getType() == AccountTransaction.Type.DEPOSIT)
.count(), is(2L));

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject())
.getType() == AccountTransaction.Type.INTEREST)
.count(), is(1L));

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject()).getType() == AccountTransaction.Type.REMOVAL)
.count(), is(5L));

Iterator<Extractor.Item> iter = results.stream().filter(i -> i instanceof TransactionItem).iterator();
Item item = iter.next();

AccountTransaction transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DEPOSIT));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-06-15T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(4500)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DEPOSIT));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-06-29T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(5400)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.REMOVAL));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-06-01T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(400)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.REMOVAL));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-06-06T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(250)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.REMOVAL));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-06-12T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(900)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.REMOVAL));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-06-15T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(100)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.REMOVAL));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-06-19T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(26150)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.INTEREST));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-06-30T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(37.50)));
}

@Test
public void testKontoauszug3()
{
JTDirektbankPDFExtractor extractor = new JTDirektbankPDFExtractor(new Client());
List<Exception> errors = new ArrayList<>();
List<Item> results = extractor.extract(loadFile("jtdirektbankKontoauszug3.txt"), errors);

assertThat(errors, empty());

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject()).getType() == AccountTransaction.Type.DEPOSIT)
.count(), is(1L));

Iterator<Extractor.Item> iter = results.stream().filter(i -> i instanceof TransactionItem).iterator();
Item item = iter.next();

AccountTransaction transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DEPOSIT));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-12-18T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(900)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.INTEREST));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-12-29T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(32.16)));
}

@Test
public void testKontoauszug4()
{
JTDirektbankPDFExtractor extractor = new JTDirektbankPDFExtractor(new Client());
List<Exception> errors = new ArrayList<>();
List<Item> results = extractor.extract(loadFile("jtdirektbankKontoauszug4.txt"), errors);

assertThat(errors, empty());

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject()).getType() == AccountTransaction.Type.DEPOSIT)
.count(), is(2L));

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject()).getType() == AccountTransaction.Type.REMOVAL)
.count(), is(2L));

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject())
.getType() == AccountTransaction.Type.INTEREST)
.count(), is(2L));

assertThat(results.stream().filter(i -> i instanceof TransactionItem)
.filter(i -> i.getSubject() instanceof AccountTransaction)
.filter(i -> ((AccountTransaction) i.getSubject())
.getType() == AccountTransaction.Type.INTEREST_CHARGE)
.count(), is(1L));

Iterator<Extractor.Item> iter = results.stream().filter(i -> i instanceof TransactionItem).iterator();
Item item = iter.next();

AccountTransaction transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DEPOSIT));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-05-04T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(15200)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DEPOSIT));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-05-16T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(5000)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.REMOVAL));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-05-19T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(250)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.REMOVAL));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-05-31T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(3000)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.INTEREST));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-05-04T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(11.69)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.INTEREST));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-05-31T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(54.32)));

item = iter.next();
transaction = (AccountTransaction) item.getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.INTEREST_CHARGE));
assertThat(transaction.getCurrencyCode(), is(CurrencyUnit.EUR));
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2023-05-03T00:00")));
assertThat(transaction.getAmount(), is(Values.Amount.factorize(13.44)));
}

private List<InputFile> loadFile(String filename)
{
return PDFInputFile.loadTestCase(getClass(), filename);
}
}
@@ -0,0 +1,55 @@
```
PDFBox Version: 1.8.17
Portfolio Performance Version: 0.67.0
-----------------------------------------
J&T Tagesgeld
EUR-Konto Kontonummer 6480010
J&T Direktbank - Postfach 232
45952 Gladbeck Kontoauszug Nr. 1/2023
erstellt am 31.03.2023 21:57 Blatt 1 von 1
IBAN: DE55 5001 5001 0006 4800 10 BIC: JTBPDEFFXXX
Herrn
Max Muster
Musterstr. 4
06448 Musterhausen
Bu-Tag Wert Vorgang
alter Kontostand 0,00 H
31.03. 31.03. Überweisungsgutschr. 3.000,00 H
Max Muster
Einzahlung 001 JT Direktbank
neuer Kontostand vom 31.03.2023 3.000,00 H
0189
000
K00002656
5M Bitte beachten Sie die Hinweise auf der Rückseite oder am Ende des Dokuments
Sehr geehrte Kundin, sehr geehrter Kunde,
Sie haben eine Bankmitteilung erhalten, z. B. einen Kontoauszug, einen Sparkontoauszug oder eine Dividendenabrechnung. Bitte
prüfen Sie diese genau: Ist alles korrekt? Falls nicht, sprechen Sie uns bitte an. Damit Sie immer gut informiert sind und wissen, wie
Sie Ihre Bankmitteilung "richtig lesen", haben wir diese nützlichen Hinweise für Sie zusammengestellt:
Falls in diesem Dokument Bankdienstleistungen aufgeführt sind, sind diese umsatzsteuerfrei - sofern nichts Abweichendes angegeben
ist. Der im Kontoauszug ausgewiesene Betrag muss nicht dem tatsächlichen Kontoguthaben entsprechen, weil z. B. die Wertstellung
einzelner Buchungen nicht berücksichtigt wurde oder noch Zinsen für eine Kontoüberziehung bei einer Verfügung anfallen können.
Rechnungsabschlüsse
Ihr Kontoauszug ist mit dem Hinweis "Rechnungsabschluss" versehen?
Dann haben wir für Ihr Konto einen Rechnungsabschluss durchgeführt, einschließlich Zinsen und Entgelte. Alle weiteren, nach dem
Erstellungsdatum dieser Mitteilung anfallenden Umsätze und Kontoauszüge werden erst in der folgenden Abrechnung
berücksichtigt - auch wenn sie sich auf den Abrechnungssaldo des abgelaufenen Abrechnungszeitraumes auswirken.
Korrekturen werden gekennzeichnet. Den Rechnungsabschluss können Sie beim Finanzamt vorlegen.
Einwendungen
Sie haben Einwendungen gegen den Rechnungsabschluss Ihres Kontokorrentkontos oder den Inhalt des Sparkontoauszugs? Dann
haben Sie nach Erhalt sechs Wochen Zeit, uns schriftlich zu informieren. Sonst gilt der Rechnungsabschluss als genehmigt.
Einzugsaufträge
Einzugspapiere wie z. B. Schecks und Lastschriften werden unter dem Vorbehalt des Eingangs gutgeschrieben, und zwar auch
dann, wenn diese Papiere bei uns selbst zahlbar sind.
Schecks und Lastschriften sind erst eingelöst, wenn die Belastungsbuchung nicht spätestens am zweiten Bankarbeitstag - bei
Lastschriften im SEPA-Firmen-Lastschriftverfahren nicht spätestens am dritten Bankarbeitstag - nach ihrer Vornahme rückgängig
gemacht wird. Barschecks sind bereits mit Zahlung an den Scheckvorleger eingelöst. Schecks sind auch schon dann eingelöst,
wenn wir im Einzelfall eine Bezahltmeldung absenden.
Guthaben
Guthaben sind als Einlagen nach Maßgabe des Einlagensicherungsgesetzes entschädigungsfähig.
Nähere Informationen können dem "Informationsbogen für den Einleger" entnommen werden.
Sie haben noch Fragen? Dann kontaktieren Sie uns bitte. Wir sind gern für Sie da.
Mit freundlichen Grüßen
Ihre Bank

```

0 comments on commit 1d68cbc

Please sign in to comment.