From 2c396ca95a96eea3490666b896c172be5f17c722 Mon Sep 17 00:00:00 2001 From: Andreas Buchen Date: Wed, 13 Sep 2023 20:19:01 +0200 Subject: [PATCH 1/2] [PDF] [Deutsche Bank] Fix detection of currency for account statement The latest account statements cannot be imported because the currency was not detected. Apparently the latest document (can) introduce a line break between account number and final balance. With this change, the currency is retrieved from the header of the document. However, to enable this we need to check for two lines. --- .../DeutscheBankPDFExtractorTest.java | 34 +++++++++++++ .../pdf/deutschebank/GiroKontoauszug06.txt | 50 +++++++++++++++++++ .../pdf/DeutscheBankPDFExtractor.java | 19 ++++--- 3 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/GiroKontoauszug06.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/DeutscheBankPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/DeutscheBankPDFExtractorTest.java index 42f91a8915..824597199e 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/DeutscheBankPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/DeutscheBankPDFExtractorTest.java @@ -2299,4 +2299,38 @@ public void testGiroKontoauszug05() "Deutsche Bank Privat- und Geschäftskunden AG", "GiroKontoauszug05.txt"); assertEquals(expectedErrorMessage, firstError.getMessage()); } + + @Test + public void testGiroKontoauszug06() + { + DeutscheBankPDFExtractor extractor = new DeutscheBankPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "GiroKontoauszug06.txt"), errors); + + assertThat(errors, empty()); + assertThat(results.size(), is(3)); + + // check dividends transaction + assertThat(results, hasItem(removal( // + hasDate("2023-08-14"), hasShares(0), // + hasSource("GiroKontoauszug06.txt"), hasNote("Überweisung an 2023 2023 Max Mustermann"), // + hasAmount("EUR", 1000), hasGrossValue("EUR", 1000), // + hasTaxes("EUR", 0), hasFees("EUR", 0.00)))); + + assertThat(results, hasItem(deposit( // + hasDate("2023-08-16"), hasShares(0), // + hasSource("GiroKontoauszug06.txt"), hasNote(""), // + hasAmount("EUR", 33.23), hasGrossValue("EUR", 33.23), // + hasTaxes("EUR", 0), hasFees("EUR", 0.00)))); + + assertThat(results, hasItem(deposit( // + hasDate("2023-08-31"), hasShares(0), // + hasSource("GiroKontoauszug06.txt"), hasNote(""), // + hasAmount("EUR", 74.49), hasGrossValue("EUR", 74.49), // + hasTaxes("EUR", 0), hasFees("EUR", 0.00)))); + + } + } diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/GiroKontoauszug06.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/GiroKontoauszug06.txt new file mode 100644 index 0000000000..8770685f91 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/GiroKontoauszug06.txt @@ -0,0 +1,50 @@ +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.65.4.qualifier +----------------------------------------- +Deutsche Bank AG +Filiale +Mannheim-Neckarau +Friedrichstraße 3-5 +Herrn 68199 Mannheim +PkOgVXl uGpqfT Frau Nicole Schrempp +FDBFxtwbEH. 12 Telefon (0621) 84228-14 +12929 FGSuxgpw +24h-Kundenservice (069) 910-10000 +31. August 2023 +Kontoauszug vom 01.08.2023 bis 31.08.2023 +Kontoinhaber: BGAGHwc yrPqwr +Auszug Seite von IBAN Alter Saldo per 31.07.2023 +8 1 2 DE03 0304 6283 7910 2573 16 EUR + 1.428,92 +Buchung Valuta Vorgang Soll Haben +14.08. 14.08. SEPA Überweisung an - 1.000,00 +2023 2023 Max Mustermann +IBAN DE70700100800927167806 +BIC PBNKDEFFXXX +Verwendungszweck/ Kundenreferenz +urlaub +16.08. 16.08. Verwendungszweck/ Kundenreferenz + 33,23 +2023 2023 ZINSEN/DIVIDENDEN/ERTRAEGE FIL/DEPOT-NR: +218/338781300IS.E.R.G.G.1.5-2.5Y U.ETF DE +INH.ANT.E UR(D.) +31.08. 31.08. Verwendungszweck/ Kundenreferenz + 74,49 +2023 2023 ZINSEN/DIVIDENDEN/ERTRAEGE FIL/DEPOT-NR: +218/338781300ISHSII-CORE MSCI EUROPE U.ETF +REG.SH.O .N. +Filialnummer Kontonummer Neuer Saldo +218 3387813 03 +EUR + 536,63 +BIC (SWIFT) +DEUTDEDBXXX +Wichtige Hinweise +Bitte erheben Sie Einwendungen gegen einzelne Buchungen unverzüglich. Schecks, Wechsel und sonstige Lastschriften schreiben wir unter dem Vorbehalt +des Eingangs gut. Der angegebene Kontostand berücksichtigt nicht die Wertstellung der Buchungen (siehe oben unter "Valuta"). +Somit können bei Verfügungen1) möglicherweise Zinsen für die Inanspruchnahme einer eingeräumten oder geduldeten Kontoüberziehung anfallen. +Die abgerechneten Leistungen sind als Bank- oder Finanzdienstleistungen von der Umsatzsteuer befreit, sofern Umsatzsteuer nicht gesondert +ausgewiesen ist. Umsatzsteuer ID Nr.: Deutsche Bank AG, 60262 Frankfurt DE114103379 +1) Der Begriff umfasst unter anderem die relevanten Zahlungskontendienste "Bargeldauszahlung" und "Überweisung". +0000000003 / 06500900 / 20230902 +Auszug Seite von IBAN +8 2 2 DE03 3807 0724 0248 4780 40 +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. +0000000003 / 06500900 / 20230902 diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DeutscheBankPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DeutscheBankPDFExtractor.java index ef6a902f43..88e3e276b5 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DeutscheBankPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DeutscheBankPDFExtractor.java @@ -335,14 +335,21 @@ private void addDividendeTransaction() private void addAccountStatementTransaction() { final DocumentType type = new DocumentType("Kontoauszug vom", (context, lines) -> { - Pattern pCurrency = Pattern.compile("[\\d]{3} [\\d]+ [\\d]{2} (?[\\w]{3}) [\\-|\\+] [\\.,\\d]+"); - Pattern pYear = Pattern.compile("Kontoauszug vom [\\d]{2}\\.[\\d]{2}\\.(?[\\d]{4}) bis [\\d]{2}\\.[\\d]{2}\\.[\\d]{4}"); + Pattern pCurrency = Pattern.compile(".* (?[\\w]{3}) [\\-|\\+] [\\.,\\d]+$"); + Pattern pYear = Pattern.compile( + "Kontoauszug vom [\\d]{2}\\.[\\d]{2}\\.(?[\\d]{4}) bis [\\d]{2}\\.[\\d]{2}\\.[\\d]{4}"); - for (String line : lines) + for (int lineNo = 0; lineNo < lines.length; lineNo++) { - Matcher mCurrency = pCurrency.matcher(line); - if (mCurrency.matches()) - context.put("currency", mCurrency.group("currency")); + String line = lines[lineNo]; + + // check for currency + if (line.startsWith("Auszug Seite") && lineNo + 1 < lines.length) + { + Matcher mCurrency = pCurrency.matcher(lines[lineNo + 1]); + if (mCurrency.matches()) + context.put("currency", mCurrency.group("currency")); + } Matcher mYear = pYear.matcher(line); if (mYear.matches()) From 9e544a72455da1f23d82a9323ed4d4530d52bf53 Mon Sep 17 00:00:00 2001 From: Nirus2000 Date: Thu, 14 Sep 2023 07:05:08 +0200 Subject: [PATCH 2/2] Improve skip dividend transaction from account statement Modify Deutsche Bank PDF-Importer #3548 --- .../DeutscheBankPDFExtractorTest.java | 18 ++---- .../pdf/DeutscheBankPDFExtractor.java | 63 +++++++++---------- 2 files changed, 34 insertions(+), 47 deletions(-) diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/DeutscheBankPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/DeutscheBankPDFExtractorTest.java index 824597199e..b3a59858d0 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/DeutscheBankPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/deutschebank/DeutscheBankPDFExtractorTest.java @@ -2310,7 +2310,11 @@ public void testGiroKontoauszug06() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "GiroKontoauszug06.txt"), errors); assertThat(errors, empty()); - assertThat(results.size(), is(3)); + 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(removal( // @@ -2319,18 +2323,6 @@ public void testGiroKontoauszug06() hasAmount("EUR", 1000), hasGrossValue("EUR", 1000), // hasTaxes("EUR", 0), hasFees("EUR", 0.00)))); - assertThat(results, hasItem(deposit( // - hasDate("2023-08-16"), hasShares(0), // - hasSource("GiroKontoauszug06.txt"), hasNote(""), // - hasAmount("EUR", 33.23), hasGrossValue("EUR", 33.23), // - hasTaxes("EUR", 0), hasFees("EUR", 0.00)))); - - assertThat(results, hasItem(deposit( // - hasDate("2023-08-31"), hasShares(0), // - hasSource("GiroKontoauszug06.txt"), hasNote(""), // - hasAmount("EUR", 74.49), hasGrossValue("EUR", 74.49), // - hasTaxes("EUR", 0), hasFees("EUR", 0.00)))); - } } diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DeutscheBankPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DeutscheBankPDFExtractor.java index 88e3e276b5..f063c531ec 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DeutscheBankPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DeutscheBankPDFExtractor.java @@ -335,21 +335,14 @@ private void addDividendeTransaction() private void addAccountStatementTransaction() { final DocumentType type = new DocumentType("Kontoauszug vom", (context, lines) -> { - Pattern pCurrency = Pattern.compile(".* (?[\\w]{3}) [\\-|\\+] [\\.,\\d]+$"); - Pattern pYear = Pattern.compile( - "Kontoauszug vom [\\d]{2}\\.[\\d]{2}\\.(?[\\d]{4}) bis [\\d]{2}\\.[\\d]{2}\\.[\\d]{4}"); + Pattern pCurrency = Pattern.compile("^.* [\\d]{4} [\\d]{4} [\\d]{4} [\\d]{4} [\\d]{2} .*(?[\\w]{3}) [\\-|\\+] [\\.,\\d]+$"); + Pattern pYear = Pattern.compile("^Kontoauszug vom [\\d]{2}\\.[\\d]{2}\\.(?[\\d]{4}) bis [\\d]{2}\\.[\\d]{2}\\.[\\d]{4}$"); - for (int lineNo = 0; lineNo < lines.length; lineNo++) + for (String line : lines) { - String line = lines[lineNo]; - - // check for currency - if (line.startsWith("Auszug Seite") && lineNo + 1 < lines.length) - { - Matcher mCurrency = pCurrency.matcher(lines[lineNo + 1]); - if (mCurrency.matches()) - context.put("currency", mCurrency.group("currency")); - } + Matcher mCurrency = pCurrency.matcher(line); + if (mCurrency.matches()) + context.put("currency", mCurrency.group("currency")); Matcher mYear = pYear.matcher(line); if (mYear.matches()) @@ -424,22 +417,25 @@ private void addAccountStatementTransaction() t.setAmount(asAmount(v.get("amount"))); t.setNote(v.get("note")); - // @formatter:off - // If we have fees, then we skip the transaction - // - // 31.12. 31.12. Verwendungszweck/ Kundenreferenz - 13,47 - // Saldo der Abschlussposten - // @formatter:on - if ("Saldo der Abschlussposten".equals(v.get("note1"))) - type.getCurrentContext().putBoolean("skipTransaction", true); - - // @formatter:off - // If we have security transaction, then we skip the transaction - // - // 01.06. 02.06. Verwendungszweck/ Kundenreferenz - 1.073,65 - // 2023 2023 WERTPAPIER-KAUF STK/NOM: 35 - // @formatter:on - if (v.get("note1").contains("WERTPAPIER")) + // @formatter:off + // If we have fees, then we skip the transaction + // + // 31.12. 31.12. Verwendungszweck/ Kundenreferenz - 13,47 + // Saldo der Abschlussposten + // @formatter:on + if ("Saldo der Abschlussposten".equals(v.get("note1"))) + type.getCurrentContext().putBoolean("skipTransaction", true); + + // @formatter:off + // If we have security transaction, then we skip the transaction + // + // 01.06. 02.06. Verwendungszweck/ Kundenreferenz - 1.073,65 + // 2023 2023 WERTPAPIER-KAUF STK/NOM: 35 + // + // 16.08. 16.08. Verwendungszweck/ Kundenreferenz + 33,23 + // 2023 2023 ZINSEN/DIVIDENDEN/ERTRAEGE FIL/DEPOT-NR: + // @formatter:on + if (v.get("note1").contains("WERTPAPIER") || v.get("note1").contains("DEPOT-NR:")) type.getCurrentContext().putBoolean("skipTransaction", true); }) @@ -449,15 +445,14 @@ private void addAccountStatementTransaction() if (t.getCurrencyCode() != null && t.getAmount() == 0) item.setFailureMessage(Messages.MsgErrorTransactionTypeNotSupported); + if (Boolean.valueOf(type.getCurrentContext().getBoolean("skipTransaction"))) + return null; + // If we have multiple entries in the document, // then the "skipTransaction" flag must be removed. - boolean skipTransaction = type.getCurrentContext().getBoolean("skipTransaction"); type.getCurrentContext().remove("skipTransaction"); - if (!skipTransaction) - return item; - - return null; + return item; })); // @formatter:off