From 3a230232b9f2d7cdb7e11ae2945a121a87ab7058 Mon Sep 17 00:00:00 2001 From: Alexander Ott <45203494+Nirus2000@users.noreply.github.com> Date: Sun, 17 Nov 2024 08:54:44 +0100 Subject: [PATCH] Modify Trade Republic PDF-Importer to support new transaction (#4349) https://forum.portfolio-performance.info/t/pdf-import-von-trade-republic/5107/697 https://forum.portfolio-performance.info/t/trade-republic-import/30322/2 --- .../pdf/traderepublic/Kontoauszug21.txt | 54 ++++ .../pdf/traderepublic/Kontoauszug22.txt | 34 ++ .../TradeRepublicPDFExtractorTest.java | 138 +++++++- .../pdf/TradeRepublicPDFExtractor.java | 300 ++++++++++-------- 4 files changed, 383 insertions(+), 143 deletions(-) create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/Kontoauszug21.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/Kontoauszug22.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/Kontoauszug21.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/Kontoauszug21.txt new file mode 100644 index 0000000000..8bacf3ac15 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/Kontoauszug21.txt @@ -0,0 +1,54 @@ +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.71.2 +----------------------------------------- +qiPFhWG pNGFRJj dT. HplAUHLx DATUM 01 Apr. 2024 - 30 Sept. 2024 +drYNNjxTbKv 27, 28452 IBAN DE63100100000000090201 +KOTzsPHXW XHCFRjk, DE BIC TRBKDEBBXXX +KONTOÜBERSICHT +PRODUKT ANFANGSSALDO ZAHLUNGSEINGANG ZAHLUNGSAUSGANG ENDSALDO +Depotkonto 46.352,66 € 81.061,48 € 80.504,15 € 46.909,99 € +UMSATZÜBERSICHT +DATUM TYP BESCHREIBUNG ZAHLUNGSEINGANG ZAHLUNGSAUSGANG SALDO +01 Apr. 2024 Zinszahlung Your interest payment 114,96 € 46.467,62 € +16 Apr. 2024 Gebühren Trade Republic Card 5,00 € 46.462,62 € +23 Apr. 2024 Kartentransaktion ALDI SAGT DANKE 37,82 € 46.424,80 € +01 Mai 2024 Zinszahlung Your interest payment 111,50 € 46.536,30 € +01 Juni 2024 Zinszahlung Your interest payment 115,41 € 46.651,71 € +14 Juni 2024 Überweisung Incoming transfer from ELGcUHm aGUVVCu Ts. zVweVvRT 250,00 € 46.901,71 € +15 Juni 2024 Kartentransaktion Sebert's Hausschlachtewar 32,52 € 46.869,19 € +15 Juni 2024 Kartentransaktion APOTHEKE DR ANSCHUETZ 10,00 € 46.859,19 € +29 Juni 2024 Kartentransaktion REWE Riethmueller oHG 108,05 € 46.751,14 € +01 Juli 2024 Zinszahlung Your interest payment 107,80 € 46.858,94 € +05 Juli 2024 Kartentransaktion SB-TANK 9868 89,43 € 46.769,51 € +14 Juli 2024 Überweisung Outgoing transfer for BvNENli XcObMce Jv. lIzWULKt 12,34 € 46.757,17 € +15 Juli 2024 Kartentransaktion APOTHEKE DR ANSCHUETZ 12,50 € 46.744,67 € +22 Juli 2024 Überweisung Incoming transfer from KySavdk xMfQpFe zn. iSrubVAU 80.000,00 € 126.744,67 € +24 Juli 2024 Kartentransaktion Neckarbruecke 10,70 € 126.733,97 € +01 Aug. 2024 Zinszahlung Your interest payment 168,75 € 126.902,72 € +09 Aug. 2024 Kartentransaktion APOTHEKE DR ANSCHUETZ 5,63 € 126.897,09 € +13 Aug. 2024 Überweisung Outgoing transfer for rCyGuWY fhxOEBW gA. HBFOfBLD 12,34 € 126.884,75 € +14 Aug. 2024 Überweisung Outgoing transfer for AmaJIZH jLWGtPe Kb. WGfgHavT 80.000,00 € 46.884,75 € +01 Sept. 2024 Zinszahlung Your interest payment 193,06 € 47.077,81 € +02 Sept. 2024 Kartentransaktion APOTHEKE DR ANSCHUETZ 7,50 € 47.070,31 € +Seite 1 von 3 +Erstellt am 21 Okt. 2024 +Trade Republic Bank GmbH +DATUM TYP BESCHREIBUNG ZAHLUNGSEINGANG ZAHLUNGSAUSGANG SALDO +21 Sept. 2024 Kartentransaktion Frankfurt (Main) Hbf 7,10 € 47.063,21 € +25 Sept. 2024 Kartentransaktion REWE Riethmueller oHG 148,22 € 46.914,99 € +26 Sept. 2024 Kartentransaktion APOTHEKE DR ANSCHUETZ 5,00 € 46.909,99 € +Seite 2 von 3 +Erstellt am 21 Okt. 2024 +Trade Republic Bank GmbH +HAFTUNGSAUSSCHLUSS +Sehr geehrte Kundin, sehr geehrter Kunde +Bitte überprüfe unbedingt deine Buchungen, Berechnungen und den Schlusssaldo auf dem Kontoauszug, der gleichzeitig deinen Rechnungsabschluss +darstellt. Der Rechnungsabschluss gilt als anerkannt, wenn du innerhalb von sechs Wochen nach Zugang keine Einwendungen erhebst. Einwendungen +gegen Kontoauszüge sind schriftlich an uns zu richten. Guthaben sind einlagefähig im Sinne des Einlagensicherungsgesetzes (EinSiG). Weitere +Informationen entnehme bitte dem Merkblatt für den Einleger, das zusammen mit unseren Allgemeinen Geschäftsbedingungen eingesehen werden kann. +Trade Republic Bank GmbH Kontakt Sitz der Gesellschaft: Berlin +Brunnenstraße 19-21 www.traderepublic.com AG Charlottenburg HRB 244347 B +10119 Berlin service@traderepublic.com Umsatzsteuer-ID DE307510626 +Seite 3 von 3 +Erstellt am 21 Okt. 2024 +Trade Republic Bank GmbH \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/Kontoauszug22.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/Kontoauszug22.txt new file mode 100644 index 0000000000..4fe3cfc702 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/Kontoauszug22.txt @@ -0,0 +1,34 @@ +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.71.2 +----------------------------------------- +Me DATUM 01 März 2020 - 07 Nov. 2024 +, 60385 IBAN DE92 +Frankfurt am Main +KONTOÜBERSICHT +PRODUKT ANFANGSSALDO ZAHLUNGSEINGANG ZAHLUNGSAUSGANG ENDSALDO +Depotkonto 0,00 € 1.321.022,68 € 1.320.999,43 € 23,25 € +UMSATZÜBERSICHT +DATUM TYP BESCHREIBUNG ZAHLUNGSEINGANG ZAHLUNGSAUSGANG SALDO +30 März +2020 Überweisung Accepted PayIn:DE74500400480142038900 to DE30110101008889827581 4.000,00 € 4.000,00 € +31 März Handel Ausführung Handel Direktkauf Kauf DE000TT08LQ1 HSBC T+B X-TUP DAX 2020 2124467520200331 181,90 € 3.818,10 € +31 März Handel Ausführung Handel Direktkauf Kauf DE000TT1RHZ9 HSBC T+B TURBOP DJIA 2020 1785274420200331 194,20 € 3.623,90 € +31 März Handel Ausführung Handel Direktverkauf Verkauf DE000TT08LQ1 HSBC T+B X-TUP 2020 DAX 9510529720200331 198,54 € 3.822,44 € +31 März Handel Ausführung Handel Direktverkauf Verkauf DE000TT1RHZ9 HSBC T+B TURBOP 2020 DJIA 3185813520200331 213,16 € 4.035,60 € +01 Apr. Handel Ausführung Handel Direktkauf Kauf DE000TT1QLA6 HSBC T+B TURBOP DAX 2020 2358417820200401 402,20 € 3.633,40 € +01 Apr. Handel Ausführung Handel Direktkauf Kauf DE000TT1QLA6 HSBC T+B TURBOP DAX 2020 2061560820200401 346,60 € 3.286,80 € +01 Apr. Handel Ausführung Handel Direktkauf Kauf DE000TT1QLA6 HSBC T+B TURBOP DAX 2020 7898253320200401 274,50 € 3.012,30 € +01 Apr. Handel Ausführung Handel Direktverkauf Verkauf DE000TT1QLA6 HSBC T+B TURBOP 2020 DAX 6002040420200401 1.085,62 € 4.097,92 € +01 Apr. Handel Ausführung Handel Direktkauf Kauf DE000TT1QG73 HSBC T+B TURBOP DAX 2020 9906151020200401 550,00 € 3.547,92 € +Erstellt am 21 Nov. 2024 +Trade Republic Bank GmbH +HAFTUNGSAUSSCHLUSS +Sehr geehrte Kundin, sehr geehrter Kunde +Bitte überprüfe unbedingt deine Buchungen, Berechnungen und den Schlusssaldo auf dem Kontoauszug, der gleichzeitig deinen Rechnungsabschluss +darstellt. Der Rechnungsabschluss gilt als anerkannt, wenn du innerhalb von sechs Wochen nach Zugang keine Einwendungen erhebst. Einwendungen +gegen Kontoauszüge sind schriftlich an uns zu richten. Guthaben sind einlagefähig im Sinne des Einlagensicherungsgesetzes (EinSiG). Weitere +Informationen entnehme bitte dem Merkblatt für den Einleger, das zusammen mit unseren Allgemeinen Geschäftsbedingungen eingesehen werden kann. +Trade Republic Bank GmbH Kontakt Sitz der Gesellschaft: Berlin +Brunnenstraße 19-21 www.traderepublic.com AG Charlottenburg HRB 244347 B +10119 Berlin service@traderepublic.com Umsatzsteuer-ID DE307510626 +Trade Republic Bank GmbH \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/TradeRepublicPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/TradeRepublicPDFExtractorTest.java index 275db6e486..630213da51 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/TradeRepublicPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/traderepublic/TradeRepublicPDFExtractorTest.java @@ -1427,7 +1427,7 @@ public void testKontoauszug06() // assert transaction assertThat(results, hasItem(fee(hasDate("2024-04-03"), hasAmount("EUR", 5.00), // - hasSource("Kontoauszug06.txt"), hasNote(null)))); + hasSource("Kontoauszug06.txt"), hasNote("Trade Republic Card")))); // assert transaction assertThat(results, hasItem(deposit(hasDate("2024-04-04"), hasAmount("EUR", 1200.00), // @@ -2264,6 +2264,140 @@ public void testKontoauszug20() hasSource("Kontoauszug20.txt"), hasNote("Hornbach Baumarkt AG FIL.")))); } + @Test + public void testKontoauszug21() + { + TradeRepublicPDFExtractor extractor = new TradeRepublicPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoauszug21.txt"), errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(0L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(24L)); + assertThat(results.size(), is(24)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // assert transaction + assertThat(results, hasItem(interest(hasDate("2024-04-01"), hasAmount("EUR", 114.96), // + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(fee(hasDate("2024-04-16"), hasAmount("EUR", 5.00), + hasSource("Kontoauszug21.txt"), hasNote("Trade Republic Card")))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-04-23"), hasAmount("EUR", 37.82), + hasSource("Kontoauszug21.txt"), hasNote("ALDI SAGT DANKE")))); + + // assert transaction + assertThat(results, hasItem(interest(hasDate("2024-05-01"), hasAmount("EUR", 111.50), // + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(interest(hasDate("2024-06-01"), hasAmount("EUR", 115.41), // + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(deposit(hasDate("2024-06-14"), hasAmount("EUR", 250.00), + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-06-15"), hasAmount("EUR", 32.52), + hasSource("Kontoauszug21.txt"), hasNote("Sebert's Hausschlachtewar")))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-06-15"), hasAmount("EUR", 10.00), + hasSource("Kontoauszug21.txt"), hasNote("APOTHEKE DR ANSCHUETZ")))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-06-29"), hasAmount("EUR", 108.05), + hasSource("Kontoauszug21.txt"), hasNote("REWE Riethmueller oHG")))); + + // assert transaction + assertThat(results, hasItem(interest(hasDate("2024-07-01"), hasAmount("EUR", 107.80), // + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-07-05"), hasAmount("EUR", 89.43), + hasSource("Kontoauszug21.txt"), hasNote("SB-TANK 9868")))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-07-14"), hasAmount("EUR", 12.34), + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-07-15"), hasAmount("EUR", 12.50), + hasSource("Kontoauszug21.txt"), hasNote("APOTHEKE DR ANSCHUETZ")))); + + // assert transaction + assertThat(results, hasItem(deposit(hasDate("2024-07-22"), hasAmount("EUR", 80000.00), + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-07-24"), hasAmount("EUR", 10.70), + hasSource("Kontoauszug21.txt"), hasNote("Neckarbruecke")))); + + // assert transaction + assertThat(results, hasItem(interest(hasDate("2024-08-01"), hasAmount("EUR", 168.75), + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-08-09"), hasAmount("EUR", 5.63), + hasSource("Kontoauszug21.txt"), hasNote("APOTHEKE DR ANSCHUETZ")))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-08-13"), hasAmount("EUR", 12.34), + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-08-14"), hasAmount("EUR", 80000.00), + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(interest(hasDate("2024-09-01"), hasAmount("EUR", 193.06), + hasSource("Kontoauszug21.txt"), hasNote(null)))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-09-02"), hasAmount("EUR", 7.50), + hasSource("Kontoauszug21.txt"), hasNote("APOTHEKE DR ANSCHUETZ")))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-09-21"), hasAmount("EUR", 7.10), + hasSource("Kontoauszug21.txt"), hasNote("Frankfurt (Main) Hbf")))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-09-25"), hasAmount("EUR", 148.22), + hasSource("Kontoauszug21.txt"), hasNote("REWE Riethmueller oHG")))); + + // assert transaction + assertThat(results, hasItem(removal(hasDate("2024-09-26"), hasAmount("EUR", 5.00), + hasSource("Kontoauszug21.txt"), hasNote("APOTHEKE DR ANSCHUETZ")))); + } + + @Test + public void testKontoauszug22() + { + TradeRepublicPDFExtractor extractor = new TradeRepublicPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoauszug22.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); + + // assert transaction + assertThat(results, hasItem(deposit(hasDate("2020-03-30"), hasAmount("EUR", 4000.00), + hasSource("Kontoauszug22.txt"), hasNote(null)))); + } + @Test public void testReleveDeCompte01() { @@ -2901,7 +3035,7 @@ public void testTransaccionesDeCuenta02() // assert transaction assertThat(results, hasItem(fee(hasDate("2024-04-03"), hasAmount("EUR", 5.00), // - hasSource("TransaccionesDeCuenta02.txt"), hasNote(null)))); + hasSource("TransaccionesDeCuenta02.txt"), hasNote("Trade Republic Card")))); // assert transaction assertThat(results, hasItem(removal(hasDate("2024-04-08"), hasAmount("EUR", 75.00), // diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/TradeRepublicPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/TradeRepublicPDFExtractor.java index 7cdcb9d7c5..89def740ed 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/TradeRepublicPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/TradeRepublicPDFExtractor.java @@ -1761,10 +1761,11 @@ private void addAccountStatementTransaction_Format02() }); this.addDocumentTyp(type); - Block depositRemovalBlock_Format01 = new Block("^[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?( [\\d]{4})? " + Block depositRemovalBlock_Format01 = new Block("^[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?( [\\d]{4})? " // + "(.berweisung" // + "|Transfer" // - + "|Referral Refund) .*$"); + + "|Referral Refund" // + + "|Kartentransaktion) .*$"); type.addBlock(depositRemovalBlock_Format01); depositRemovalBlock_Format01.setMaxSize(1); depositRemovalBlock_Format01.set(new Transaction() @@ -1775,7 +1776,7 @@ private void addAccountStatementTransaction_Format02() return accountTransaction; }) - .oneOf( // + .optionalOneOf( // // @formatter:off // 02 Apr. Überweisung Einzahlung akzeptiert: DE7243872432 auf 2024 DE7243872432 1.200,00 € 51.352,41 € // @formatter:on @@ -1789,10 +1790,11 @@ private void addAccountStatementTransaction_Format02() }), // @formatter:off // 16 Apr. 2024 Überweisung Einzahlung akzeptiert: DE5987654321 auf DE12334567658 3.500,00 € 16.347,54 € + // 23 Juli 2024 Überweisung Incoming transfer from KLEslAT zxcWeqg 1.100,00 € 56.457,39 € // @formatter:on section -> section // .attributes("date", "amount", "currency") // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) .berweisung Einzahlung .* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) .berweisung (Einzahlung|Incoming) .* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // .assign((t, v) -> { t.setDateTime(asDate(v.get("date"))); t.setAmount(asAmount(v.get("amount"))); @@ -1810,24 +1812,12 @@ private void addAccountStatementTransaction_Format02() t.setCurrencyCode(asCurrencyCode(v.get("currency"))); }), // @formatter:off - // 01 Apr. 2024 Überweisung PayOut to transit 172,23 € 50.000,00 € - // @formatter:on - section -> section // - .attributes("date", "amount", "currency") // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) .berweisung PayOut .* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // - .assign((t, v) -> { - t.setType(AccountTransaction.Type.REMOVAL); - - t.setDateTime(asDate(v.get("date"))); - t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - }), - // @formatter:off // 26 Sep 2024 Transfer PayOut to transit €15.99 €0.00 + // 24 Sep 2024 Referral Refund for your gift €10.01 €113.01 // @formatter:on section -> section // .attributes("date", "amount", "currency") // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) Transfer PayOut .* (?\\p{Sc})(?[\\.,\\d]+) \\p{Sc}[\\.,\\d]+$") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) (Transfer PayOut|Referral Refund) .* (?\\p{Sc})(?[\\.,\\d]+) \\p{Sc}[\\.,\\d]+$") // .assign((t, v) -> { t.setType(AccountTransaction.Type.REMOVAL); @@ -1836,35 +1826,27 @@ private void addAccountStatementTransaction_Format02() t.setCurrencyCode(asCurrencyCode(v.get("currency"))); }), // @formatter:off - // 23 Juli 2024 Überweisung Incoming transfer from KLEslAT zxcWeqg 1.100,00 € 56.457,39 € + // 23 Apr. 2024 Kartentransaktion ALDI SAGT DANKE 37,82 € 46.424,80 € // @formatter:on section -> section // - .attributes("date", "amount", "currency") // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) .berweisung Incoming transfer from .* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // - .assign((t, v) -> { - t.setDateTime(asDate(v.get("date"))); - t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - }), - // @formatter:off - // 22 Juli 2024 Überweisung Outgoing transfer for EMYRMzk QpSHhzd 200,00 € 55.357,39 € - // @formatter:on - section -> section // - .attributes("date", "amount", "currency") // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) .berweisung Outgoing transfer for .* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // + .attributes("date", "note", "amount", "currency") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) Kartentransaktion (?.*) (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // .assign((t, v) -> { t.setType(AccountTransaction.Type.REMOVAL); t.setDateTime(asDate(v.get("date"))); t.setAmount(asAmount(v.get("amount"))); t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + t.setNote(trim(v.get("note"))); }), // @formatter:off - // 24 Sep 2024 Referral Refund for your gift €10.01 €113.01 + // 01 Apr. 2024 Überweisung PayOut to transit 172,23 € 50.000,00 € + // 26 Sep 2024 Transfer PayOut to transit €15.99 €0.00 + // 22 Juli 2024 Überweisung Outgoing transfer for EMYRMzk QpSHhzd 200,00 € 55.357,39 € // @formatter:on section -> section // .attributes("date", "amount", "currency") // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) Referral Refund .* (?\\p{Sc})(?[\\.,\\d]+) \\p{Sc}[\\.,\\d]+$") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) .berweisung (PayOut|Outgoing).* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // .assign((t, v) -> { t.setType(AccountTransaction.Type.REMOVAL); @@ -1901,7 +1883,7 @@ private void addAccountStatementTransaction_Format02() .wrap(TransactionItem::new)); - Block depositRemovalBlock_Format02 = new Block("^[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?[\\s](Transacci.n.*)?$"); + Block depositRemovalBlock_Format02 = new Block("^[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?[\\s].*$"); type.addBlock(depositRemovalBlock_Format02); depositRemovalBlock_Format02.setMaxSize(4); depositRemovalBlock_Format02.set(new Transaction() @@ -1959,7 +1941,7 @@ private void addAccountStatementTransaction_Format02() // @formatter:on section -> section // .attributes("date", "year", "note", "amount", "currency", "amountAfter", "currencyAfter") // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?)[\\s](Transacci.n.*)?$") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?)[\\s].*$") // .match("^(?[\\d]{4}) " // + "(Kartentransaktion|con tarjeta|Virement|Parrainage) " // + "(?(?!(Einzahlung|Ingreso|Paiement)).*) " // @@ -2026,6 +2008,9 @@ private void addAccountStatementTransaction_Format02() // // 08 abr // 2024 Recomendación Reembolso por tu regalo 9,96 € 6.337,75 € + // + // 30 März + // 2020 Überweisung Accepted PayIn:DE74500400480142038900 to DE30110101008889827581 4.000,00 € 4.000,00 € // @formatter:on section -> section // .attributes("date", "year", "amount", "currency") // @@ -2034,15 +2019,16 @@ private void addAccountStatementTransaction_Format02() + "(.berweisung" // + "|Pr.mie" // + "|Transferencia" // - + "|Recompensa" + + "|Recompensa" // + "|Recomendaci.n" // + "|Virement) " // + "(Einzahlung akzeptiert:" // + + "|Accepted PayIn:" // + "|Ingreso aceptado:" // + "|Paiement accept.:" // + "|Your Saveback" // + "|Your Saveback payment" // - + "|Incoming transfer from" + + "|Incoming transfer from" // + "|Reembolso)" // + ".* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // .assign((t, v) -> { @@ -2111,7 +2097,7 @@ private void addAccountStatementTransaction_Format02() Block depositRemovalBlock_Format03 = new Block("^[\\d]{2}[\\s]$"); type.addBlock(depositRemovalBlock_Format03); - depositRemovalBlock_Format03.setMaxSize(3); + depositRemovalBlock_Format03.setMaxSize(4); depositRemovalBlock_Format03.set(new Transaction() .subject(() -> { @@ -2196,6 +2182,37 @@ private void addAccountStatementTransaction_Format02() t.setCurrencyCode(asCurrencyCode(v.get("currency"))); }), // @formatter:off + // 20 + // Sept. Überweisung Einzahlung akzeptiert: DE00000000000000000000 auf + // 2024 DE00000000000000000000 + // 889,77 € 964,18 € + // @formatter:on + section -> section // + .attributes("day", "month", "year", "amount", "currency", "amountAfter", "currencyAfter") // + .match("^(?[\\d]{2})[\\s]$") // + .match("^(?[\\p{L}]{3,4}([\\.]{1})?) .berweisung Einzahlung akzeptiert: .*") // + .match("^(?[\\d]{4}) .*$") // + .match("(?[\\.,\\d]+) (?\\p{Sc}) (?[\\.,\\d]+) (?\\p{Sc})$") // + .assign((t, v) -> { + DocumentContext context = type.getCurrentContext(); + Money amountAfter = Money.of(asCurrencyCode(v.get("currencyAfter")), asAmount(v.get("amountAfter"))); + + AccountAmountTransactionHelper accountAmountTransactionHelper = context.getType(AccountAmountTransactionHelper.class).orElseGet(AccountAmountTransactionHelper::new); + Optional item = accountAmountTransactionHelper.findItem(v.getStartLineNumber(), amountAfter); + + if (item.isPresent()) + { + Money amountBefore = Money.of(item.get().currency, item.get().amount); + + if (amountBefore.isGreaterThan(amountAfter)) + t.setType(AccountTransaction.Type.REMOVAL); + } + + t.setDateTime(asDate(v.get("day") + " " + v.get("month") + " " + v.get("year"))); + t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + }), + // @formatter:off // 14 // Juni Überweisung PayOut to transit 6.500,00 € 50.860,76 € // 2024 @@ -2225,48 +2242,35 @@ private void addAccountStatementTransaction_Format02() return null; })); - Block depositRemovalBlock_Format04 = new Block("^[\\d]{2}[\\s]$"); - type.addBlock(depositRemovalBlock_Format04); - depositRemovalBlock_Format04.setMaxSize(4); - depositRemovalBlock_Format04.set(new Transaction() + // @formatter:off + // 03 Apr. + // 2024 Gebühren Trade Republic Card 5,00 € 49.997,41 € + // + // 03 abr + // 2024 Comisión Trade Republic Card 5,00 € 6.402,79 € + // @formatter:on + Block feesBlock_Format01 = new Block("^[\\d]{2} [\\w]{3,4}([\\.]{1})?[\\s]$"); + type.addBlock(feesBlock_Format01); + feesBlock_Format01.setMaxSize(2); + feesBlock_Format01.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.DEPOSIT); + accountTransaction.setType(AccountTransaction.Type.FEES); return accountTransaction; }) .optionalOneOf( // - // @formatter:off - // 20 - // Sept. Überweisung Einzahlung akzeptiert: DE00000000000000000000 auf - // 2024 DE00000000000000000000 - // 889,77 € 964,18 € - // @formatter:on section -> section // - .attributes("day", "month", "year", "amount", "currency", "amountAfter", "currencyAfter") // - .match("^(?[\\d]{2})[\\s]$") // - .match("^(?[\\p{L}]{3,4}([\\.]{1})?) .berweisung Einzahlung akzeptiert: .*") // - .match("^(?[\\d]{4}) .*$") // - .match("(?[\\.,\\d]+) (?\\p{Sc}) (?[\\.,\\d]+) (?\\p{Sc})$") // + .attributes("date", "year", "note", "amount", "currency") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?)[\\s]$") // + .match("^(?[\\d]{4}) .* (?Trade Republic Card) " // + + "(?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // .assign((t, v) -> { - DocumentContext context = type.getCurrentContext(); - Money amountAfter = Money.of(asCurrencyCode(v.get("currencyAfter")), asAmount(v.get("amountAfter"))); - - AccountAmountTransactionHelper accountAmountTransactionHelper = context.getType(AccountAmountTransactionHelper.class).orElseGet(AccountAmountTransactionHelper::new); - Optional item = accountAmountTransactionHelper.findItem(v.getStartLineNumber(), amountAfter); - - if (item.isPresent()) - { - Money amountBefore = Money.of(item.get().currency, item.get().amount); - - if (amountBefore.isGreaterThan(amountAfter)) - t.setType(AccountTransaction.Type.REMOVAL); - } - - t.setDateTime(asDate(v.get("day") + " " + v.get("month") + " " + v.get("year"))); + t.setDateTime(asDate(v.get("date") + " " + v.get("year"))); t.setAmount(asAmount(v.get("amount"))); t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + t.setNote(v.get("note")); })) .wrap(t -> { @@ -2276,16 +2280,12 @@ private void addAccountStatementTransaction_Format02() })); // @formatter:off - // 03 Apr. - // 2024 Gebühren Trade Republic Card 5,00 € 49.997,41 € - // - // 03 abr - // 2024 Comisión Trade Republic Card 5,00 € 6.402,79 € + // 16 Apr. 2024 Gebühren Trade Republic Card 5,00 € 46.462,62 € // @formatter:on - Block feesBlock = new Block("^[\\d]{2} [\\w]{3,4}([\\.]{1})?[\\s]$"); - type.addBlock(feesBlock); - feesBlock.setMaxSize(2); - feesBlock.set(new Transaction() + Block feesBlock_Format02 = new Block("^[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?( [\\d]{4})? .* Trade Republic Card [\\.,\\d]+ \\p{Sc} [\\.,\\d]+ \\p{Sc}$"); + type.addBlock(feesBlock_Format02); + feesBlock_Format02.setMaxSize(1); + feesBlock_Format02.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); @@ -2293,14 +2293,17 @@ private void addAccountStatementTransaction_Format02() return accountTransaction; }) - .section("date", "year", "amount", "currency").optional() // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?)[\\s]$") - .match("^(?[\\d]{4}) .* Trade Republic Card (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // - .assign((t, v) -> { - t.setDateTime(asDate(v.get("date") + " " + v.get("year"))); - t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - }) + .optionalOneOf( // + section -> section // + .attributes("date", "note", "amount", "currency") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})? [\\d]{4}) .* (?Trade Republic Card) " // + + "(?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date"))); + t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + t.setNote(v.get("note")); + })) .wrap(t -> { if (t.getCurrencyCode() != null && t.getAmount() != 0) @@ -2308,6 +2311,7 @@ private void addAccountStatementTransaction_Format02() return null; })); + // @formatter:off // 01 Apr. 2024 Zinszahlung Your interest payment 172,23 € 50.172,23 € // @formatter:on @@ -2322,14 +2326,16 @@ private void addAccountStatementTransaction_Format02() return accountTransaction; }) - .section("date", "amount", "currency") // - .match("^(?[\\d]{2} ([\\p{L}]{3,4}([\\.]{1})?) [\\d]{4}) (Zinszahlung|intereses|d.int.r.ts) .* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // - .assign((t, v) -> { - t.setDateTime(asDate(v.get("date"))); - t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - v.getTransactionContext().put(FAILURE, Messages.MsgErrorTransactionAlternativeDocumentRequired); - }) + .optionalOneOf( // + section -> section // + .attributes("date", "amount", "currency") // + .match("^(?[\\d]{2} ([\\p{L}]{3,4}([\\.]{1})?) [\\d]{4}) (Zinszahlung|intereses|d.int.r.ts) .* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date"))); + t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + v.getTransactionContext().put(FAILURE, Messages.MsgErrorTransactionAlternativeDocumentRequired); + })) .wrap((t, ctx) -> { TransactionItem item = new TransactionItem(t); @@ -2366,15 +2372,17 @@ private void addAccountStatementTransaction_Format02() return accountTransaction; }) - .section("date", "year", "amount", "currency").optional() // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?)[\\s]((Pago|Paiement).*)?$") - .match("^(?[\\d]{4}) (Zinszahlung|intereses|d.int.r.ts) Your interest payment (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // - .assign((t, v) -> { - t.setDateTime(asDate(v.get("date") + " " + v.get("year"))); - t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - v.getTransactionContext().put(FAILURE, Messages.MsgErrorTransactionAlternativeDocumentRequired); - }) + .optionalOneOf( // + section -> section // + .attributes("date", "year", "amount", "currency") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?)[\\s]((Pago|Paiement).*)?$") + .match("^(?[\\d]{4}) (Zinszahlung|intereses|d.int.r.ts) Your interest payment (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date") + " " + v.get("year"))); + t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + v.getTransactionContext().put(FAILURE, Messages.MsgErrorTransactionAlternativeDocumentRequired); + })) .wrap((t, ctx) -> { TransactionItem item = new TransactionItem(t); @@ -2403,16 +2411,19 @@ private void addAccountStatementTransaction_Format02() return accountTransaction; }) - .section("day", "month", "year", "amount", "currency").optional() // - .match("^(?[\\d]{2})[\\s]$") - .match("^(?[\\p{L}]{3,4}([\\.]{1})?) (Zinszahlung|intereses|d.int.r.ts) Your interest payment (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // - .match("^(?[\\d]{4})$") // - .assign((t, v) -> { - t.setDateTime(asDate(v.get("day") + " " + v.get("month") + " " + v.get("year"))); - t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - v.getTransactionContext().put(FAILURE, Messages.MsgErrorTransactionAlternativeDocumentRequired); - }) + .optionalOneOf( // + section -> section // + .attributes("day", "month", "year", "amount", "currency") // + .match("^(?[\\d]{2})[\\s]$") + .match("^(?[\\p{L}]{3,4}([\\.]{1})?) (Zinszahlung|intereses|d.int.r.ts) Your interest payment (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // + .match("^(?[\\d]{4})$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("day") + " " + v.get("month") + + " " + v.get("year"))); + t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + v.getTransactionContext().put(FAILURE, Messages.MsgErrorTransactionAlternativeDocumentRequired); + })) .wrap((t, ctx) -> { TransactionItem item = new TransactionItem(t); @@ -2440,14 +2451,16 @@ private void addAccountStatementTransaction_Format02() return accountTransaction; }) - .section("date", "year", "amount", "currency").optional() // - .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?)[\\s]$") - .match("^(?[\\d]{4}) Steuern (Steueroptimierung |Tax Optimisation|Kapitalertragssteueroptimierung ).* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // - .assign((t, v) -> { - t.setDateTime(asDate(v.get("date") + " " + v.get("year"))); - t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - }) + .optionalOneOf( // + section -> section // + .attributes("date", "year", "amount", "currency") // + .match("^(?[\\d]{2} [\\p{L}]{3,4}([\\.]{1})?)[\\s]$") + .match("^(?[\\d]{4}) Steuern (Steueroptimierung |Tax Optimisation|Kapitalertragssteueroptimierung ).* (?[\\.,\\d]+) (?\\p{Sc}) [\\.,\\d]+ \\p{Sc}$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date") + " " + v.get("year"))); + t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + })) .wrap(t -> { if (t.getCurrencyCode() != null && t.getAmount() != 0) @@ -2479,29 +2492,34 @@ private void addAccountStatementTransaction_Format02() return accountTransaction; }) - .section("day", "month", "year", "amount", "currency", "amountAfter", "currencyAfter").optional() // - .match("^(?[\\d]{2})[\\s]$") - .match("^(?[\\p{L}]{3,4}([\\.]{1})?) Steuern (Steueroptimierung |Tax Optimisation|Kapitalertragssteueroptimierung ).* (?[\\.,\\d]+) (?\\p{Sc}) (?[\\.,\\d]+) (?\\p{Sc})$") // - .match("^(?[\\d]{4}).*$") // - .assign((t, v) -> { - DocumentContext context = type.getCurrentContext(); - Money amountAfter = Money.of(asCurrencyCode(v.get("currencyAfter")), asAmount(v.get("amountAfter"))); + .optionalOneOf( // + section -> section // + .attributes("day", "month", "year", "amount", "currency", "amountAfter", "currencyAfter") // + .match("^(?[\\d]{2})[\\s]$") + .match("^(?[\\p{L}]{3,4}([\\.]{1})?) Steuern (Steueroptimierung |Tax Optimisation|Kapitalertragssteueroptimierung ).* (?[\\.,\\d]+) (?\\p{Sc}) (?[\\.,\\d]+) (?\\p{Sc})$") // + .match("^(?[\\d]{4}).*$") // + .assign((t, v) -> { + DocumentContext context = type.getCurrentContext(); + Money amountAfter = Money.of( + asCurrencyCode(v.get("currencyAfter")), + asAmount(v.get("amountAfter"))); - AccountAmountTransactionHelper accountAmountTransactionHelper = context.getType(AccountAmountTransactionHelper.class).orElseGet(AccountAmountTransactionHelper::new); - Optional item = accountAmountTransactionHelper.findItem(v.getStartLineNumber(), amountAfter); + AccountAmountTransactionHelper accountAmountTransactionHelper = context.getType(AccountAmountTransactionHelper.class) + .orElseGet(AccountAmountTransactionHelper::new); + Optional item = accountAmountTransactionHelper.findItem(v.getStartLineNumber(), amountAfter); - if (item.isPresent()) - { - Money amountBefore = Money.of(item.get().currency, item.get().amount); + if (item.isPresent()) + { + Money amountBefore = Money.of(item.get().currency, item.get().amount); - if (amountBefore.isGreaterThan(amountAfter)) - t.setType(AccountTransaction.Type.TAXES); - } + if (amountBefore.isGreaterThan(amountAfter)) + t.setType(AccountTransaction.Type.TAXES); + } - t.setDateTime(asDate(v.get("day") + " " + v.get("month") + " " + v.get("year"))); - t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - }) + t.setDateTime(asDate(v.get("day") + " " + v.get("month") + " " + v.get("year"))); + t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + })) .wrap(t -> { if (t.getCurrencyCode() != null && t.getAmount() != 0)