From c649fd2ca53fca581562efe6f244ceaec7642e8a Mon Sep 17 00:00:00 2001 From: Nirus2000 Date: Wed, 17 Jan 2024 11:13:12 +0100 Subject: [PATCH] Modify DADAT PDF-Importer to support new transaction https://forum.portfolio-performance.info/t/pdf-import-von-dadat/15684/58 replaceMultipleBlanks in security name grab year in documentContext --- .../DADATBankenhausPDFExtractorTest.java | 122 +++++++- .../pdf/dadatbankenhaus/Kauf02.txt | 22 ++ .../pdf/dadatbankenhaus/Kontoauszug26.txt | 27 ++ .../pdf/DADATBankenhausPDFExtractor.java | 265 +++++++++++++----- 4 files changed, 353 insertions(+), 83 deletions(-) create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/Kauf02.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/Kontoauszug26.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/DADATBankenhausPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/DADATBankenhausPDFExtractorTest.java index 6019a04c21..9ec7b269cb 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/DADATBankenhausPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/DADATBankenhausPDFExtractorTest.java @@ -16,6 +16,7 @@ import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasTaxes; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasTicker; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasWkn; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.purchase; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.sale; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.security; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.taxRefund; @@ -104,6 +105,37 @@ public void testWertpapierKauf01() is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); } + @Test + public void testWertpapierKauf02() + { + DADATBankenhausPDFExtractor extractor = new DADATBankenhausPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf02.txt"), errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(1L)); + assertThat(countAccountTransactions(results), is(0L)); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check security + assertThat(results, hasItem(security( // + hasIsin("NL0011794037"), hasWkn(null), hasTicker(null), // + hasName("AHOLD DELHAIZE,KON.EO-,01"), // + hasCurrencyCode("EUR")))); + + // check buy sell transaction + assertThat(results, hasItem(purchase( // + hasDate("2023-12-27T00:00"), hasShares(40.00), // + hasSource("Kauf02.txt"), // + hasNote(null), // + hasAmount("EUR", 1053.18), hasGrossValue("EUR", 1046.40), // + hasTaxes("EUR", 0.00), hasFees("EUR", 6.78)))); + } + @Test public void testWertpapierStornoVerkauf01() { @@ -123,7 +155,7 @@ public void testWertpapierStornoVerkauf01() assertThat(security1.getIsin(), is("US00206R1023")); assertNull(security1.getWkn()); assertNull(security1.getTickerSymbol()); - assertThat(security1.getName(), is("AT + T INC. DL 1")); + assertThat(security1.getName(), is("AT + T INC. DL 1")); assertThat(security1.getCurrencyCode(), is(CurrencyUnit.USD)); Security security2 = results.stream().filter(SecurityItem.class::isInstance).skip(1).findFirst() @@ -139,7 +171,7 @@ public void testWertpapierStornoVerkauf01() assertThat(security3.getIsin(), is("US5949181045")); assertNull(security3.getWkn()); assertNull(security3.getTickerSymbol()); - assertThat(security3.getName(), is("MICROSOFT DL-,00000625")); + assertThat(security3.getName(), is("MICROSOFT DL-,00000625")); assertThat(security3.getCurrencyCode(), is(CurrencyUnit.USD)); Security security4 = results.stream().filter(SecurityItem.class::isInstance).skip(3).findFirst() @@ -147,7 +179,7 @@ public void testWertpapierStornoVerkauf01() assertThat(security4.getIsin(), is("US1912161007")); assertNull(security4.getWkn()); assertNull(security4.getTickerSymbol()); - assertThat(security4.getName(), is("COCA-COLA CO. DL-,25")); + assertThat(security4.getName(), is("COCA-COLA CO. DL-,25")); assertThat(security4.getCurrencyCode(), is(CurrencyUnit.USD)); Security security5 = results.stream().filter(SecurityItem.class::isInstance).skip(4).findFirst() @@ -171,7 +203,7 @@ public void testWertpapierStornoVerkauf01() assertThat(security7.getIsin(), is("US4781601046")); assertNull(security7.getWkn()); assertNull(security7.getTickerSymbol()); - assertThat(security7.getName(), is("JOHNSON + JOHNSON DL 1")); + assertThat(security7.getName(), is("JOHNSON + JOHNSON DL 1")); assertThat(security7.getCurrencyCode(), is(CurrencyUnit.USD)); // check 1st cancellation (Storno) transaction @@ -507,7 +539,7 @@ public void testKontoauszug03() assertThat(security.getIsin(), is("US2561631068")); assertNull(security.getWkn()); assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("DOCUSIGN INC DL-,0001")); + assertThat(security.getName(), is("DOCUSIGN INC DL-,0001")); assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); // check buy sell transaction @@ -602,7 +634,7 @@ public void testKontoauszug04() assertThat(security.getIsin(), is("US2561631068")); assertNull(security.getWkn()); assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("DOCUSIGN INC DL-,0001")); + assertThat(security.getName(), is("DOCUSIGN INC DL-,0001")); assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); // check buy sell transaction @@ -740,7 +772,7 @@ public void testKontoauszug06() assertThat(security1.getIsin(), is("US00206R1023")); assertNull(security1.getWkn()); assertNull(security1.getTickerSymbol()); - assertThat(security1.getName(), is("AT + T INC. DL 1")); + assertThat(security1.getName(), is("AT + T INC. DL 1")); assertThat(security1.getCurrencyCode(), is(CurrencyUnit.USD)); Security security2 = results.stream().filter(i -> i instanceof SecurityItem).skip(1).findFirst() @@ -1727,7 +1759,7 @@ public void testKontoauszug21() assertThat(security2.getIsin(), is("US1667641005")); assertNull(security2.getWkn()); assertNull(security2.getTickerSymbol()); - assertThat(security2.getName(), is("CHEVRON CORP. DL-,75")); + assertThat(security2.getName(), is("CHEVRON CORP. DL-,75")); assertThat(security2.getCurrencyCode(), is(CurrencyUnit.EUR)); // check 1st buy sell transaction @@ -1950,12 +1982,12 @@ public void testKontoauszug25() // check security assertThat(results, hasItem(security( // hasIsin("US00206R1023"), hasWkn(null), hasTicker(null), // - hasName("AT + T INC. DL 1"), // + hasName("AT + T INC. DL 1"), // hasCurrencyCode("EUR")))); assertThat(results, hasItem(security( // hasIsin("US7672921050"), hasWkn(null), hasTicker(null), // - hasName("RIOT PLATFORMS DL-,001"), // + hasName("RIOT PLATFORMS DL-,001"), // hasCurrencyCode("EUR")))); assertThat(results, hasItem(security( // @@ -2012,6 +2044,76 @@ public void testKontoauszug25() hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } + @Test + public void testKontoauszug26() + { + DADATBankenhausPDFExtractor extractor = new DADATBankenhausPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoauszug26.txt"), errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check security + assertThat(results, hasItem(security( // + hasIsin("US7134481081"), hasWkn(null), hasTicker(null), // + hasName("PEPSICO INC. DL-,0166"), // + hasCurrencyCode("USD")))); + + // check dividends transaction + assertThat(results, hasItem(dividend( // + hasDate("2024-01-09T00:00"), hasShares(55), // + hasSource("Kontoauszug26.txt"), // + hasNote(null), // + hasAmount("EUR", 45.97), hasGrossValue("EUR", 63.41), // + hasForexGrossValue("USD", 69.58), // + hasTaxes("EUR", (10.44 + 8.70) / 1.097300), hasFees("EUR", 0.00)))); + } + + @Test + public void testKontoauszug26WithSecurityInEUR() + { + Security security = new Security("PEPSICO INC. DL-,0166", CurrencyUnit.EUR); + security.setIsin("US7134481081"); + + Client client = new Client(); + client.addSecurity(security); + + DADATBankenhausPDFExtractor extractor = new DADATBankenhausPDFExtractor(client); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoauszug26.txt"), errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(0L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(1)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check dividends transaction + assertThat(results, hasItem(dividend( // + hasDate("2024-01-09T00:00"), hasShares(55), // + hasSource("Kontoauszug26.txt"), // + hasNote(null), // + hasAmount("EUR", 45.97), hasGrossValue("EUR", 63.41), // + hasTaxes("EUR", (10.44 + 8.70) / 1.097300), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); + } + @Test public void testWertpapierDividende01() { diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/Kauf02.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/Kauf02.txt new file mode 100644 index 0000000000..08ffd5f01c --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/Kauf02.txt @@ -0,0 +1,22 @@ +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.67.1 +----------------------------------------- +sBUeWc diuaF Datum: 11.01.2024 +ajWhS AsQWaFpAMrh 7/0 +0086 PlpZ +Buchungsbestätigung +HBOp: +Kontoinhaber: AaiYDZ VpUtQ +Auf oben genanntem Konto wurde folgende Buchung vorgenommen: +Buchungsdatum: 27.12.2023 +Betrag in EUR -1.053,18 Effekten +Verwendungszweck: +Kauf Depot 636036082/20231227-96207266 +ISIN NL0011794037 AHOLD DELHAIZE,KON.EO-,01 40,00000 STK +Kurs 26,160000 Kurswert -1.046,40 EUR +DADAT Handelsspesen -6,78 EUR +Mit freundlichen Grüßen +Schelhammer Capital Bank AG +Wien +BIC BSSWATWW 11.01.2024 Schelhammer Capital Bank AG +Seite 1 von 1 Wien \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/Kontoauszug26.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/Kontoauszug26.txt new file mode 100644 index 0000000000..c5ef412b77 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dadatbankenhaus/Kontoauszug26.txt @@ -0,0 +1,27 @@ +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.67.1 +----------------------------------------- +DADAT-Bank KONTOAUSZUG +Schelhammer Capital Bank AG vom 09.01.2024 +99999 +Kundennummer +Alter Saldo per 08.01.2024 45.452,58 +Summe der Gutschriften 45,97 +Summe der Lastschriften 0,00 +Schelhammer, PF 1000, A-5021 Salzburg +Neuer Saldo zu Ihren Gunsten +Bv uuDwCN vYyzPvY EUR 99.888,55 +NLGEHFRNxj 66/75 +0064 Wien +Konto-Nr.: 63365073411 Bankleitzahl: 19190 +Empfängerhinweis: +Datum Buchungstext Wert Betrag +09.01 Ertrag Depot 0450115847/10802351-84757305 05.01 45,97 +ISIN US7134481081 PEPSICO INC. DL-,0166 55,00000 STK +Kurs 1,265000 Zinsen/Dividenden 69,58 USD +Quellensteuer -10,44 USD Auslands-KESt -8,70 USD +DevKurs 1,097300/5.1.2024 +Neuer Saldo zu Ihren Gunsten 99.999,55 +AT21 0699 9485 4579 5511 BSSWATWW 01 0002 1/1 +IBAN BIC Filiale Auszug Blatt/Gesamt +R0042 27540 Doknr.: EK00-714-0919865102 \ No newline at end of file diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DADATBankenhausPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DADATBankenhausPDFExtractor.java index a0152a146b..260d5fc7e0 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DADATBankenhausPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DADATBankenhausPDFExtractor.java @@ -1,6 +1,7 @@ package name.abuchen.portfolio.datatransfer.pdf; import static name.abuchen.portfolio.datatransfer.ExtractorUtils.checkAndSetGrossUnit; +import static name.abuchen.portfolio.util.TextUtil.replaceMultipleBlanks; import static name.abuchen.portfolio.util.TextUtil.trim; import name.abuchen.portfolio.Messages; @@ -23,6 +24,7 @@ public DADATBankenhausPDFExtractor(Client client) addBankIdentifier("DADAT - Bankhaus"); addBankIdentifier("DADAT-Bank"); + addBankIdentifier("Schelhammer Capital Bank AG"); addBuySellTransaction(); addDividendeTransaction(); @@ -43,12 +45,12 @@ public String getLabel() private void addBuySellTransaction() { - DocumentType type = new DocumentType("Abrechnungsauskunft"); + DocumentType type = new DocumentType("(Abrechnungsauskunft|Kauf Depot)"); this.addDocumentTyp(type); Transaction pdfTransaction = new Transaction<>(); - Block firstRelevantLine = new Block("^Gesch.ftsart: Kauf$"); + Block firstRelevantLine = new Block("^(Gesch.ftsart: Kauf|Buchungsbestätigung)$"); type.addBlock(firstRelevantLine); firstRelevantLine.set(pdfTransaction); @@ -60,45 +62,86 @@ private void addBuySellTransaction() return portfolioTransaction; }) - // @formatter:off - // Titel: US09247X1019 B L A C K R O C K I NC. - // Reg. Shares Class A DL -,01 - // Kurswert: -1.800,-- EUR - // @formatter:on - .section("isin", "name", "name1", "currency") // - .match("^Titel: (?[A-Z]{2}[A-Z0-9]{9}[0-9])[\\s]{1,}(?.*)$") // - .match("^(?.*)$") // - .match("^Kurswert: [\\-\\.,\\d]+ (?[\\w]{3}).*$") // - .assign((t, v) -> { - if (!v.get("name1").startsWith("Kurs")) - v.put("name", trim(v.get("name")) + " " + trim(v.get("name1"))); + .oneOf( // + // @formatter:off + // Titel: US09247X1019 B L A C K R O C K I NC. + // Reg. Shares Class A DL -,01 + // Kurswert: -1.800,-- EUR + // @formatter:on + section -> section // + .attributes("isin", "name", "name1", "currency") // + .match("^Titel: (?[A-Z]{2}[A-Z0-9]{9}[0-9])[\\s]{1,}(?.*)$") // + .match("^(?.*)$") // + .match("^Kurswert: [\\-\\.,\\d]+ (?[\\w]{3}).*$") // + .assign((t, v) -> { + if (!v.get("name1").startsWith("Kurs")) + v.put("name", trim(v.get("name")) + " " + trim(v.get("name1"))); - t.setSecurity(getOrCreateSecurity(v)); - }) + t.setSecurity(getOrCreateSecurity(v)); + }), + // @formatter:off + // ISIN NL0011794037 AHOLD DELHAIZE,KON.EO-,01 40,00000 STK + // Kurs 26,160000 Kurswert -1.046,40 EUR + // @formatter:on + section -> section // + .attributes("isin", "name", "currency") // + .match("^ISIN (?[A-Z]{2}[A-Z0-9]{9}[0-9]) (?.*) [\\.,\\d]+ STK$") // + .match("^Kurs .* (\\-)?[\\.,\\d]+ (?[\\w]{3})$") // + .assign((t, v) -> t.setSecurity(getOrCreateSecurity(v)))) - // @formatter:off - // Zugang: 3 Stk - // @formatter:on - .section("shares") // - .match("^Zugang: (?[\\.,\\d]+) Stk$") // - .assign((t, v) -> t.setShares(asShares(v.get("shares")))) + .oneOf( // + // @formatter:off + // Zugang: 3 Stk + // @formatter:on + section -> section // + .attributes("shares") // + .match("^Zugang: (?[\\.,\\d]+) Stk$") // + .assign((t, v) -> t.setShares(asShares(v.get("shares")))), + // @formatter:off + // ISIN NL0011794037 AHOLD DELHAIZE,KON.EO-,01 40,00000 STK + // @formatter:on + section -> section // + .attributes("shares") // + .match("^ISIN [A-Z]{2}[A-Z0-9]{9}[0-9] .* (?[\\.,\\d]+) STK$") // + .assign((t, v) -> t.setShares(asShares(v.get("shares"))))) - // @formatter:off - // Handelszeit: 17.2.2021 um 20:49:54 Uhr - // @formatter:on - .section("date", "time") // - .match("^Handelszeit: (?[\\d]{1,2}\\.[\\d]{1,2}\\.[\\d]{4}) .* (?