From 42d8c680fa8421b706054b739b9e338e622d3706 Mon Sep 17 00:00:00 2001 From: kriegerse Date: Sat, 4 Jul 2026 21:16:43 +0200 Subject: [PATCH 1/4] Fix slighly changed format for Sunris buy statement --- .../datatransfer/pdf/sunrise/Kauf06.txt | 40 +++++++++++++++++++ .../pdf/sunrise/SunrisePDFExtractorTest.java | 34 ++++++++++++++++ .../datatransfer/pdf/SunrisePDFExtractor.java | 2 + 3 files changed, 76 insertions(+) create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/Kauf06.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/Kauf06.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/Kauf06.txt new file mode 100644 index 0000000000..565a0d65af --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/Kauf06.txt @@ -0,0 +1,40 @@ +PDFBox Version: 3.0.6 +Portfolio Performance Version: 0.84.2 +System: linux | x86_64 | 25.0.3+9-2-24.04.2-Ubuntu | Ubuntu +----------------------------------------- +Ein Service von: +Für Rückfragen wenden Sie sich +bitte an: info@sunrise.app +Herr +XXXXXXX YYYYYY Fondsabrechnung +ZZZZ Straße. XX +54321 XXXXXXXX Datum: 03.07.2026 +Deutschland Depotnummer: 1234567890 +Hiermit bestätigen wir Ihnen folgende Transaktion für Sie ausgeführt zu haben: +Transaktion Fondsname Betrag Preis Anteile +ISIN Preisdatum +Verwahrart/Lagerland +Verwahrort +Kauf Standortfonds Deutschland 100.24 € 192.77 € 0.520 +AT0000A1Z882 02.07.2026 +Girosammelverwahrung/AT +Raiffeisen Bank International AG + 100.24 € + 0,00% + 20260701123456789000001944747 + DE33 **** **** **** **** ** +Anlagen in Investmentfonds können erst nach Kenntnisnahme der gesetzlichen Verkaufsunterlagen +(Basisinformationsblatt) erfolgen. Diese Unterlagen haben Sie direkt über die Sunrise Kanäle erhalten bzw. vor +Auftragserteilung dort eingesehen. +Die erworbenen Vermögenswerte fallen unter die Regelungen der Richtlinie 2014/65/EU („MiFID II“), insbesondere die +in dieser Richtlinie enthaltenen Bestimmungen zum Schutz Ihrer Vermögenswerte. Informationen und Risiken im +Zusammenhang mit der Sammelverwahrung entnehmen Sie bitte den "Allgemeinen Geschäftsbedingungen" unter +www.sunrise.app. +Wichtiger Hinweis: Einwendungen gegen diese Fondsabrechnung wegen Unrichtigkeit oder Unvollständigkeit richten +Sie bitte schriftlich spätestens einen Monat nach Zugang an: info@sunrise.app. +Mit besten Grüßen +Ihr Sunrise Team +Sunrise Securities GmbH, Gußhausstraße 3/2, A-1040 Wien; UID-Nummer: ATU 68616777, Firmenbuchnummer: FN 410750w +Sunrise Securities GmbH nach österreichischem Recht Zweigniederlassung Deutschland, Rahel-Hirsch-Straße 10, D-10557 Berlin; Handelsregister: HRB 258310 B +Version 2026_01 +Version_2025_01_K \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java index f7b99316e8..271f53b0e1 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java @@ -211,6 +211,40 @@ public void testWertpapierKauf05() hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } + @Test + public void testWertpapierKauf06() + { + var extractor = new SunrisePDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + var results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf06.txt"), errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(1L)); + assertThat(countAccountTransactions(results), is(0L)); + assertThat(countAccountTransfers(results), is(0L)); + assertThat(countItemsWithFailureMessage(results), is(0L)); + assertThat(countSkippedItems(results), is(0L)); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, "EUR"); + + // check security + assertThat(results, hasItem(security( // + hasIsin("AT0000A1Z882"), hasWkn(null), hasTicker(null), // + hasName("Standortfonds Deutschland"), // + hasCurrencyCode("EUR")))); + + // check buy sell transaction + assertThat(results, hasItem(purchase( // + hasDate("2026-07-02T00:00"), hasShares(0.520), // + hasSource("Kauf06.txt"), // + hasNote("Auftrags-Nummer: 20260701123456789000001944747"), // + hasAmount("EUR", 100.24), hasGrossValue("EUR", 100.24), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + } + @Test public void testDividende22() { diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java index c57e300180..1b17cf5f0d 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java @@ -81,9 +81,11 @@ private void addBuySellTransaction() // @formatter:off // AT0000A1QA38 10.01.2022 5.123 + // AT0000A1Z882 02.07.2026 // @formatter:on .section("date") // .match("^[A-Z]{2}[A-Z0-9]{9}[0-9] (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) [\\.'\\d]+$") // + .match("^[A-Z]{2}[A-Z0-9]{9}[0-9] (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4})") // .assign((t, v) -> t.setDate(asDate(v.get("date")))) // @formatter:off From f5af7d95904d7573716dc9e29a0645dbf30dc1df Mon Sep 17 00:00:00 2001 From: kriegerse Date: Sat, 4 Jul 2026 21:36:51 +0200 Subject: [PATCH 2/4] use unified regex to match ne ISIN and data format --- .../portfolio/datatransfer/pdf/SunrisePDFExtractor.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java index 1b17cf5f0d..e64cf9fd61 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java @@ -66,10 +66,12 @@ private void addBuySellTransaction() // @formatter:off // Kauf Standortfonds Österreich 10.00 € 140.59 € 0.071 // AT0000A1QA38 10.01.2022 5.123 + // Kauf Standortfonds Deutschland 100.24 € 192.77 € 0.520 + // AT0000A1Z882 02.07.2026 // @formatter:on .section("name", "currency", "isin") // .match("^Kauf (?.*) [\\.'\\d]+ \\p{Sc} [\\.'\\d]+ (?\\p{Sc}) [\\.'\\d]+$") // - .match("^(?[A-Z]{2}[A-Z0-9]{9}[0-9]) [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} ['\\.\\d]+$") // + .match("^(?[A-Z]{2}[A-Z0-9]{9}[0-9]) [\\d]{2}\\.[\\d]{2}\\.[\\d]{4}( ['\\.\\d]+)?$") // .assign((t, v) -> t.setSecurity(getOrCreateSecurity(v))) // @formatter:off @@ -84,8 +86,7 @@ private void addBuySellTransaction() // AT0000A1Z882 02.07.2026 // @formatter:on .section("date") // - .match("^[A-Z]{2}[A-Z0-9]{9}[0-9] (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) [\\.'\\d]+$") // - .match("^[A-Z]{2}[A-Z0-9]{9}[0-9] (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4})") // + .match("^[A-Z]{2}[A-Z0-9]{9}[0-9] (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4})( [\\.'\\d]+)?$") // .assign((t, v) -> t.setDate(asDate(v.get("date")))) // @formatter:off From 1965ea0ffc941d78035c5ff4cf90f18959ad4b6d Mon Sep 17 00:00:00 2001 From: kriegerse Date: Sat, 4 Jul 2026 21:54:19 +0200 Subject: [PATCH 3/4] Abrechnungsbetrag: is now optional --- .../portfolio/datatransfer/pdf/SunrisePDFExtractor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java index e64cf9fd61..b7add80463 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java @@ -91,9 +91,10 @@ private void addBuySellTransaction() // @formatter:off // Abrechnungsbetrag: 10.00 € + // 100.24 € // @formatter:on .section("amount", "currency") // - .match("^Abrechnungsbetrag: (?['\\.\\d]+) (?\\p{Sc})$") // + .match("^(Abrechnungsbetrag:)?\s+(?['\\.\\d]+) (?\\p{Sc})$") // .assign((t, v) -> { t.setAmount(asAmount(v.get("amount"))); t.setCurrencyCode(asCurrencyCode(v.get("currency"))); From 5af7571396ca4f15c144fdc98c52a7357479f1a1 Mon Sep 17 00:00:00 2001 From: kriegerse Date: Sat, 4 Jul 2026 22:46:24 +0200 Subject: [PATCH 4/4] "Auftrags-Nummer:" prefix also vanished --- .../datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java | 2 +- .../portfolio/datatransfer/pdf/SunrisePDFExtractor.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java index 271f53b0e1..955d96aaac 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/sunrise/SunrisePDFExtractorTest.java @@ -240,7 +240,7 @@ public void testWertpapierKauf06() assertThat(results, hasItem(purchase( // hasDate("2026-07-02T00:00"), hasShares(0.520), // hasSource("Kauf06.txt"), // - hasNote("Auftrags-Nummer: 20260701123456789000001944747"), // + hasNote("20260701123456789000001944747"), // hasAmount("EUR", 100.24), hasGrossValue("EUR", 100.24), // hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java index b7add80463..69f517ed48 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/SunrisePDFExtractor.java @@ -102,9 +102,10 @@ private void addBuySellTransaction() // @formatter:off // Auftrags-Nummer: 20220106123456789000000612345 + // 20260701123456789000001944747 // @formatter:on .section("note").optional() // - .match("^(?Auftrags\\-Nummer: [\\d]+)$") // + .match("^(?(Auftrags\\-Nummer:)? [\\d]+)$") // .assign((t, v) -> t.setNote(trim(v.get("note")))) .wrap(BuySellEntryItem::new);