From 1d2e13e36a9f6f8d2964850ea627628aa6f7feb0 Mon Sep 17 00:00:00 2001 From: christen90 Date: Mon, 2 Dec 2024 18:56:21 +0100 Subject: [PATCH 1/3] adding Ginmon documents Account Statements, Buys, Sells, Fees --- .../pdf/dab/DABPDFExtractorTest.java | 210 ++++++++++++++++ .../datatransfer/pdf/dab/FeeInvoice01.txt | 41 ++++ .../portfolio/datatransfer/pdf/dab/Kauf14.txt | 50 ++++ .../datatransfer/pdf/dab/Kontoumsaetze08.txt | 31 +++ .../datatransfer/pdf/dab/Kontoumsaetze09.txt | 34 +++ .../datatransfer/pdf/dab/Kontoumsaetze10.txt | 34 +++ .../datatransfer/pdf/dab/Kontoumsaetze11.txt | 30 +++ .../datatransfer/pdf/dab/Kontoumsaetze12.txt | 30 +++ .../datatransfer/pdf/dab/Verkauf14.txt | 89 +++++++ .../datatransfer/pdf/DABPDFExtractor.java | 226 +++++++++++++++++- 10 files changed, 774 insertions(+), 1 deletion(-) create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/FeeInvoice01.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kauf14.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze08.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze09.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze10.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze11.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze12.txt create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Verkauf14.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java index bb017d5c95..b7d552f518 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java @@ -1,7 +1,9 @@ package name.abuchen.portfolio.datatransfer.pdf.dab; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.check; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.deposit; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.dividend; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.fee; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasAmount; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasCurrencyCode; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasDate; @@ -18,6 +20,8 @@ import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasWkn; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.inboundDelivery; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.outboundDelivery; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.purchase; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.removal; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.sale; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.security; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.taxRefund; @@ -799,6 +803,37 @@ public void testWertpapierKauf13() is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(10.00)))); } + @Test + public void testWertpapierKauf14() + { + DABPDFExtractor extractor = new DABPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf14.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("IE00BCBJG560"), hasWkn(null), hasTicker(null), // + hasName("SPDR MSCI Wrld Small Cap U.ETF Registered Shares o.N."), // + hasCurrencyCode("EUR")))); + + // check buy sell transaction + assertThat(results, hasItem(purchase( // + hasDate("2024-08-29T12:59:00"), hasShares(0.0425), // + hasSource("Kauf14.txt"), // + hasNote("Abrechnungs-Nr. 92328727"), // + hasAmount("EUR", 4.13), hasGrossValue("EUR", 4.13), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + } + @Test public void testWertpapierVerkauf01() { @@ -1702,6 +1737,37 @@ public void testWertpapierVerkauf13() hasTaxes("EUR", 100.00 + 10.00 + 10.00), hasFees("EUR", 0.00)))); } + @Test + public void testWertpapierVerkauf14() + { + DABPDFExtractor extractor = new DABPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Verkauf14.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("IE00BL25JM42"), hasWkn(null), hasTicker(null), // + hasName("Xtr.(IE) - MSCI World Value Registered Shares 1C USD o.N."), // + hasCurrencyCode("EUR")))); + + // check buy sell transaction + assertThat(results, hasItem(sale( // + hasDate("2024-11-07T16:00"), hasShares(0.2741), // + hasSource("Verkauf14.txt"), // + hasNote("Abrechnungs-Nr. 64518224"), // + hasAmount("EUR", 11.60), hasGrossValue("EUR", 11.67), // + hasTaxes("EUR", 0.07), hasFees("EUR", 0.00)))); + } + @Test public void testMultipleWertpapierKaufVerkauf01() { @@ -3648,4 +3714,148 @@ public void testKontoumsaetze07() assertThat(transaction.getSource(), is("Kontoumsaetze07.txt")); assertThat(transaction.getNote(), is("Porto")); } + + @Test + public void testKontoumsaetze08() + { + DABPDFExtractor extractor = new DABPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoumsaetze08.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("2024-08-28"), hasAmount("EUR", 26.59), // + hasSource("Kontoumsaetze08.txt"), hasNote("vermögenswirksame Leistung")))); + } + + @Test + public void testKontoumsaetze09() + { + DABPDFExtractor extractor = new DABPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoumsaetze09.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(fee(hasDate("2024-10-09"), hasAmount("EUR", 0.02), // + hasSource("Kontoumsaetze09.txt"), hasNote("Ginmon Gebuehrenrechnung September 2024")))); + } + + @Test + public void testKontoumsaetze10() + { + DABPDFExtractor extractor = new DABPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoumsaetze10.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(removal(hasDate("2024-11-11"), hasAmount("EUR", 50.00), // + hasSource("Kontoumsaetze10.txt"), hasNote("SEPA-Überweisung")))); + } + + @Test + public void testKontoumsaetze11() + { + DABPDFExtractor extractor = new DABPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoumsaetze11.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("IE00B52MJY50"), hasWkn(null), hasTicker(null), // + hasName(null), // + hasCurrencyCode("EUR")))); + + // assert transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionAlternativeDocumentRequired, + sale(hasDate("2024-11-11"), hasAmount("EUR", 0.49), hasShares(0.003), // + hasSource("Kontoumsaetze11.txt"), hasNote(null))))); + } + + @Test + public void testKontoumsaetze12() + { + DABPDFExtractor extractor = new DABPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kontoumsaetze12.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("IE00BL25JM42"), hasWkn(null), hasTicker(null), // + hasName(null), // + hasCurrencyCode("EUR")))); + + // assert transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionAlternativeDocumentRequired, + purchase(hasDate("2024-10-01"), hasAmount("EUR", 6.26), hasShares(0.15), // + hasSource("Kontoumsaetze12.txt"), hasNote(null))))); + } + + @Test + public void testFeeInvoice01() + { + DABPDFExtractor extractor = new DABPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "FeeInvoice01.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(withFailureMessage( // + Messages.MsgErrorTransactionAlternativeDocumentRequired, + fee(hasDate("2024-10-31"), hasAmount("EUR", 0.04), // + hasSource("FeeInvoice01.txt"), hasNote(null))))); + } } diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/FeeInvoice01.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/FeeInvoice01.txt new file mode 100644 index 0000000000..539c212171 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/FeeInvoice01.txt @@ -0,0 +1,41 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +Ginmon Vermögensverwaltung GmbH, Mainzer Landstraße 33a, 60329 Frankfurt am Main +Herr +Vorname Nachname +Straße 1 +12345 Ort +Deutschland +Rechnungsdatum / Invoice date: 31.10.2024 +Rechnungsnummer /Invoice no: 00000002024101 +Kundennummer /Customer ID: GM0000000 +Gebührenabrechnung Oktober +Invoice October +Zeitraum vom 01.10.2024 – 31.10.2024 +Period of 01.10.2024 – 31.10.2024 +Position Berechungsbasis Gebühr Betrag +Calculation Fee Amount +Grundgebühr 57.60 € 0.7500% p.a. 0.04 € +Base fee (Ø AuM in 31 Tagen / days) +Discount 0.00 € +Depotführung inklusive 0.00 € +Handling charge included +Transaktionskosten inklusive 0.00 € +Transaction fees included +MwSt. inkl. von 19% 0.01 € +VAT included of 19% +Rechnungsbetrag 0.04 € +Total amount +Der ausstehende Betrag wird in den kommenden Tagen automatisch aus Ihrem Ginmon Konto +entnommen. Sie müssen hierfür nichts weiter unternehmen. +The amount will automatically be deducted from your Ginmon account within the upcoming days. There +is no further action required on your side. +Ginmon GmbH Geschäftssitz Bankverbindung +Ginmon Vermögensverwaltung Geschäftsführer: Lars Reiner IBAN: DE66 7012 0400 2569 4200 09 +Mainzer Landstraße 33a Amtsgericht: Frankfurt am Main BIC: DABBDEMMXXX +60329 Frankfurt am Main HRB 102248 / HRB 107290 DAB BNP Paribas +service@ginmon.de USt-IdNr. DE298791666 + +``` \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kauf14.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kauf14.txt new file mode 100644 index 0000000000..9d133b65ea --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kauf14.txt @@ -0,0 +1,50 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +BELEGDRUCK=J +ORIGINAL=1 +FAXVERSAND=N +EMAILVERSAND=N +DEPOTNUMMER=0000000000 +Wertpapierabrechnung DEPOTUNTERBEZEICHNUNG= +VERSANDARTENSCHLUESSEL=DRUCK +ADRESSZEILE1=Herr +Kauf ADRESSZEILE2=Vorname Nachname +Kommissionsgeschäft ADRESSZEILE3=Straße 1 +ADRESSZEILE4=12345 Ort +Depot-Nr. Abrechnungs-Nr. ADRESSZEILE5= +0000000000 92328727 / 29.08.2024 ADRESSZEILE6= +BELEGNUMMER=11349 +Herr SEITENNUMMER=1 +Vorname Nachname STEUERERSTATTUNG=N +Straße 1 Depotinhaber +12345 Ort Vorname Nachname +München, 29.08.2024 +Wir haben für Sie gekauft +Gattungsbezeichnung ISIN +SPDR MSCI Wrld Small Cap U.ETF Registered Shares o.N. IE00BCBJG560 +Nominal Kurs +STK 0,0425 EUR 97,1400 +Handelstag 29.08.2024 Kurswert EUR 4,13- +Handelszeit 12:59* +Börse Tradegate/EDG +Verwahrart Wertpapierrechnung +Lagerland Irland +Wert Konto-Nr. Betrag zu Ihren Lasten +02.09.2024 0000000000 EUR 4,13 +Die Höhe des von der KVG festgelegten Ausgabeauf- bzw. Rücknahmeabschlages sowie die jährlich zu zahlende Ver- +waltungsvergütung und die Gesamtkostenquote sind dem Verkaufsprospekt bzw. den Vertragsbedingungen zu entnehmen. +Aggregierte Order ggf. zum Mischkurs. +* Die angegebene Zeit entspricht den Angaben der Handelspartner gemäß der lokalen Zeit in Deutschland (Mitteleuropäische Zeit bzw. Mitteleuropäische Sommerzeit). +Widerrufsbelehrung für den Erwerb von Anteilen oder Aktien eines offenen Investmentvermögens: Ist der Käufer von Anteilen oder Aktien eines offenen Investmentvermögens +durch mündliche Verhandlungen außerhalb der ständigen Geschäftsräume desjenigen, der die Anteile oder Aktien verkauft oder den Verkauf vermittelt hat, dazu bestimmt worden, +eine auf den Kauf gerichtete Willenserklärung abzugeben, so ist er an diese Erklärung nur gebunden, wenn er sie nicht innerhalb einer Frist von zwei Wochen bei der +Verwaltungsgesellschaft oder einem Repräsentanten im Sinne des § 319 KAGB schriftlich widerruft. +Dieser Beleg wird maschinell erstellt und daher nicht unterschrieben. +BNP Paribas S.A. Niederlassung Deutschland > Standort: München > Landsberger Straße 300 > 80687 München > Postadresse: DAB BNP Paribas > Postfach 2547 > +90011 Nürnberg > Sitz: Nürnberg HRB Nürnberg 31129 > USt.-Ident-Nr.: DE191528929 > Sitz der Hauptniederlassung der BNP Paribas S.A.: 16, boulevard des Italiens +> 75009 Paris > Frankreich > Registergericht: R.C.S. Paris 662 042 449 > Président du Conseil d‘Administration: Jean Lemierre > Directeur Général: Jean-Laurent Bonnafé +3.19/ABREABHNHANDKF/GABAUFTL/011349/290824/210432 + +``` \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze08.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze08.txt new file mode 100644 index 0000000000..42f8230012 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze08.txt @@ -0,0 +1,31 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +Kontoauszug DAB Verrechnungskonto Kontonummer: 0000000000 KOPIE +BLZ: 701 204 00 +IBAN: DE00000000000000000000 +BIC (SWIFT-Code): DABBDEMMXXX +Vorname Nachname +Letzter Auszug Nr. 000 vom 00.00.0000 +Umsatzzeitraum +Ginmon Vermögensverwaltung GmbH 28.08.2024 - 28.08.2024 Seite 1/1 +Mainzer Landstr. 33a +60329 Frankfurt Auszug Nr. 001 +28.08.2024 +Buchung Valuta Buchungsinformation Soll Haben +00.00. Alter Kontostand: EUR 0,00+ +28.08. 28.08. vermögenswirksame Leistung 26,59+ +Company where VL is payed from 000/UVXY VL +Nachname, Vo. +28.08. Neuer Kontostand: EUR 26,59+ +Hinweis +Der Kontostand /Saldo kann auch noch nicht wertgestellte Beträge enthalten, über die bis zur Wertstellung noch nicht ohne Abzug von Sollzinsen +verfügt werden kann. +Guthaben sind als Einlagen nach Maßgabe des Einlagensicherungsgesetztes entschädigungsfähig. Nähere Informationen können dem +„Informationsbogen für den Einleger“ entnommen werden. +BNP Paribas S.A. Niederlassung Deutschland > Standort: München > Landsberger Straße 300 > 80687 München > Postadresse: DAB BNP Paribas > Postfach 2547 > +90011 Nürnberg > Sitz: Nürnberg HRB Nürnberg 31129 > USt.-Ident-Nr.: DE 191528929 > Sitz der Hauptniederlassung der BNP Paribas S.A.: 16, boulevard des Italiens, +75009 Paris, Frankreich, Registergericht: R.C.S. Paris 662 042 449 > Président du Conseil d‘Administration: Jean Lemierre, Directeur Général: Jean-Laurent Bonnafé + +``` \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze09.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze09.txt new file mode 100644 index 0000000000..b6f0aba3ff --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze09.txt @@ -0,0 +1,34 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +Kontoauszug DAB Verrechnungskonto Kontonummer: 0000000000 KOPIE +BLZ: 701 204 00 +IBAN: DE00000000000000000000 +BIC (SWIFT-Code): DABBDEMMXXX +Vorname Nachname +Letzter Auszug Nr. 004 vom 27.09.2024 +Umsatzzeitraum +Ginmon Vermögensverwaltung GmbH 28.09.2024 - 09.10.2024 Seite 1/1 +Mainzer Landstr. 33a +60329 Frankfurt Auszug Nr. 005 +09.10.2024 +Buchung Valuta Buchungsinformation Soll Haben +27.09. Alter Kontostand: EUR 0,60+ +09.10. 09.10. Verwalterpreis 0,02- +Ginmon Gebuehrenrechnung September 2024 End to End- +ID:SEPA-EINZUG +IBAN: DE62701204003335687004 +BIC: DABBDEMMXXX +Empfänger: Ginmon Vermoegensverwaltung GmbH +09.10. Neuer Kontostand: EUR 0,58+ +Hinweis +Der Kontostand /Saldo kann auch noch nicht wertgestellte Beträge enthalten, über die bis zur Wertstellung noch nicht ohne Abzug von Sollzinsen +verfügt werden kann. +Guthaben sind als Einlagen nach Maßgabe des Einlagensicherungsgesetztes entschädigungsfähig. Nähere Informationen können dem +„Informationsbogen für den Einleger“ entnommen werden. +BNP Paribas S.A. Niederlassung Deutschland > Standort: München > Landsberger Straße 300 > 80687 München > Postadresse: DAB BNP Paribas > Postfach 2547 > +90011 Nürnberg > Sitz: Nürnberg HRB Nürnberg 31129 > USt.-Ident-Nr.: DE 191528929 > Sitz der Hauptniederlassung der BNP Paribas S.A.: 16, boulevard des Italiens, +75009 Paris, Frankreich, Registergericht: R.C.S. Paris 662 042 449 > Président du Conseil d‘Administration: Jean Lemierre, Directeur Général: Jean-Laurent Bonnafé + +``` \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze10.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze10.txt new file mode 100644 index 0000000000..ed4e8c586c --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze10.txt @@ -0,0 +1,34 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +Kontoauszug DAB Verrechnungskonto Kontonummer: 0000000000 KOPIE +BLZ: 701 204 00 +IBAN: DE00000000000000000000 +BIC (SWIFT-Code): DABBDEMMXXX +Vorname Nachname +Letzter Auszug Nr. 009 vom 08.11.2024 +Umsatzzeitraum +Ginmon Vermögensverwaltung GmbH 09.11.2024 - 11.11.2024 Seite 1/1 +Mainzer Landstr. 33a +60329 Frankfurt Auszug Nr. 010 +11.11.2024 +Buchung Valuta Buchungsinformation Soll Haben +08.11. Alter Kontostand: EUR 50,32+ +11.11. 11.11. SEPA-Überweisung 50,00- +AGKRGWWWRHABNBNBOZSPCR Ginmon End to End- +ID:DAB/B3/480606009/2024-11-11 +IBAN: DE00000000000000000000 +BIC: BICXXXXX001 +Empfänger: Vorname Nachname +11.11. Neuer Kontostand: EUR 0,32+ +Hinweis +Der Kontostand /Saldo kann auch noch nicht wertgestellte Beträge enthalten, über die bis zur Wertstellung noch nicht ohne Abzug von Sollzinsen +verfügt werden kann. +Guthaben sind als Einlagen nach Maßgabe des Einlagensicherungsgesetztes entschädigungsfähig. Nähere Informationen können dem +„Informationsbogen für den Einleger“ entnommen werden. +BNP Paribas S.A. Niederlassung Deutschland > Standort: München > Landsberger Straße 300 > 80687 München > Postadresse: DAB BNP Paribas > Postfach 2547 > +90011 Nürnberg > Sitz: Nürnberg HRB Nürnberg 31129 > USt.-Ident-Nr.: DE 191528929 > Sitz der Hauptniederlassung der BNP Paribas S.A.: 16, boulevard des Italiens, +75009 Paris, Frankreich, Registergericht: R.C.S. Paris 662 042 449 > Président du Conseil d‘Administration: Jean Lemierre, Directeur Général: Jean-Laurent Bonnafé + +``` \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze11.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze11.txt new file mode 100644 index 0000000000..3d530a0deb --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze11.txt @@ -0,0 +1,30 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +Kontoauszug DAB Verrechnungskonto Kontonummer: 0000000000 KOPIE +BLZ: 701 204 00 +IBAN: DE00000000000000000000 +BIC (SWIFT-Code): DABBDEMMXXX +Vorname Nachname +Letzter Auszug Nr. 007 vom 29.10.2024 +Umsatzzeitraum +Ginmon Vermögensverwaltung GmbH 30.10.2024 - 07.11.2024 +dstr. 33a Seite 1/1Mainzer Lan +60329 Frankfurt Auszug Nr. 008 +07.11.2024 +Buchung Valuta Buchungsinformation Soll Haben +29.10. Alter Kontostand: EUR 1,24+ +07.11. 11.11. Wertpapierverkauf 0,49+ +VKF A2061191320241107 IE00B52MJY50* 0,003 +07.11. Neuer Kontostand: EUR 50,36+ +Hinweis +Der Kontostand /Saldo kann auch noch nicht wertgestellte Beträge enthalten, über die bis zur Wertstellung noch nicht ohne Abzug von Sollzinsen +verfügt werden kann. +Guthaben sind als Einlagen nach Maßgabe des Einlagensicherungsgesetztes entschädigungsfähig. Nähere Informationen können dem +„Informationsbogen für den Einleger“ entnommen werden. +BNP Paribas S.A. Niederlassung Deutschland > Standort: München > Landsberger Straße 300 > 80687 München > Postadresse: DAB BNP Paribas > Postfach 2547 > +90011 Nürnberg > Sitz: Nürnberg HRB Nürnberg 31129 > USt.-Ident-Nr.: DE 191528929 > Sitz der Hauptniederlassung der BNP Paribas S.A.: 16, boulevard des Italiens, +75009 Paris, Frankreich, Registergericht: R.C.S. Paris 662 042 449 > Président du Conseil d‘Administration: Jean Lemierre, Directeur Général: Jean-Laurent Bonnafé + +``` \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze12.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze12.txt new file mode 100644 index 0000000000..9331e61b93 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Kontoumsaetze12.txt @@ -0,0 +1,30 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.3.qualifier +----------------------------------------- +Kontoauszug DAB Verrechnungskonto Kontonummer: 0000000000 KOPIE +BLZ: 701 204 00 +IBAN: DE00000000000000000000 +BIC (SWIFT-Code): DABBDEMMXXX +Vorname Nachname +Letzter Auszug Nr. 003 vom 26.09.2024 +Umsatzzeitraum +Ginmon Vermögensverwaltung GmbH 27.09.2024 - 27.09.2024 +dstr. 33a Seite 1/1Mainzer Lan +60329 Frankfurt Auszug Nr. 004 +27.09.2024 +Buchung Valuta Buchungsinformation Soll Haben +26.09. Alter Kontostand: EUR 27,30+ +27.09. 01.10. Wertpapierkauf 6,26- +KAUF A6239874820240927 IE00BL25JM42* 0,150 +27.09. Neuer Kontostand: EUR 0,60+ +Hinweis +Der Kontostand /Saldo kann auch noch nicht wertgestellte Beträge enthalten, über die bis zur Wertstellung noch nicht ohne Abzug von Sollzinsen +verfügt werden kann. +Guthaben sind als Einlagen nach Maßgabe des Einlagensicherungsgesetztes entschädigungsfähig. Nähere Informationen können dem +„Informationsbogen für den Einleger“ entnommen werden. +BNP Paribas S.A. Niederlassung Deutschland > Standort: München > Landsberger Straße 300 > 80687 München > Postadresse: DAB BNP Paribas > Postfach 2547 > +90011 Nürnberg > Sitz: Nürnberg HRB Nürnberg 31129 > USt.-Ident-Nr.: DE 191528929 > Sitz der Hauptniederlassung der BNP Paribas S.A.: 16, boulevard des Italiens, +75009 Paris, Frankreich, Registergericht: R.C.S. Paris 662 042 449 > Président du Conseil d‘Administration: Jean Lemierre, Directeur Général: Jean-Laurent Bonnafé + +``` \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Verkauf14.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Verkauf14.txt new file mode 100644 index 0000000000..36aebc89ce --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/Verkauf14.txt @@ -0,0 +1,89 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +BELEGDRUCK=J +ORIGINAL=1 +FAXVERSAND=N +EMAILVERSAND=N +DEPOTNUMMER=0000000000 +Wertpapierabrechnung DEPOTUNTERBEZEICHNUNG= +VERSANDARTENSCHLUESSEL=DRUCK +ADRESSZEILE1=Herr +Verkauf ADRESSZEILE2=Vorname Nachname +Kommissionsgeschäft ADRESSZEILE3=Straße 1 +ADRESSZEILE4=12345 Ort +Depot-Nr. Abrechnungs-Nr. ADRESSZEILE5= +0000000000 64518224 / 07.11.2024 ADRESSZEILE6= +BELEGNUMMER=8907 +Herr SEITENNUMMER=1 +Vorname Nachname STEUERERSTATTUNG=N +Straße 1 Depotinhaber +12345 Ort Vorname Nachname +München, 07.11.2024 +Wir haben für Sie verkauft +Gattungsbezeichnung ISIN +Xtr.(IE) - MSCI World Value Registered Shares 1C USD o.N. IE00BL25JM42 +Nominal Kurs +STK 0,2741 EUR 42,5700 +Handelstag 07.11.2024 Kurswert EUR 11,67 +Handelszeit 16:00* Kapitalertragsteuer EUR 0,06- +Börse Tradegate/EDG Solidaritätszuschlag EUR 0,01- +Verwahrart Wertpapierrechnung +Lagerland Irland +Wert Konto-Nr. Betrag zu Ihren Gunsten +11.11.2024 0000000000 EUR 11,60 +Hinweise zur steuerlichen Verrechnung: vorher aktuell +Gesamtveräußerungsergebnis vor Anwendung einer TFQ EUR 0,33 +Veräußerungsgewinn Fonds EUR 0,23 +Aktienverlusttopf EUR 0,00 0,00 +allgemeiner Verlusttopf EUR 0,00 0,00 +Quellensteuertopf EUR 0,00 0,00 +zu versteuern EUR 0,23 +im laufenden Jahr einbehaltene Kapitalertragsteuer EUR 0,22 +im laufenden Jahr einbehaltener Solidaritätszuschlag EUR 0,01 +Kapitalertragsteuer, Solidaritätszuschlag und ggf. Kirchensteuer nach gemeldetem Kirchensteuersatz verrechnet mit dem +Finanzamt Frankfurt am Main, Steuernummer 014/220/15370. +Die Höhe des von der KVG festgelegten Ausgabeauf- bzw. Rücknahmeabschlages sowie die jährlich zu zahlende Ver- +waltungsvergütung und die Gesamtkostenquote sind dem Verkaufsprospekt bzw. den Vertragsbedingungen zu entnehmen. +Es folgt Seite 2 +BNP Paribas S.A. Niederlassung Deutschland > Standort: München > Landsberger Straße 300 > 80687 München > Postadresse: DAB BNP Paribas > Postfach 2547 > +90011 Nürnberg > Sitz: Nürnberg HRB Nürnberg 31129 > USt.-Ident-Nr.: DE191528929 > Sitz der Hauptniederlassung der BNP Paribas S.A.: 16, boulevard des Italiens +> 75009 Paris > Frankreich > Registergericht: R.C.S. Paris 662 042 449 > Président du Conseil d‘Administration: Jean Lemierre > Directeur Général: Jean-Laurent Bonnafé +3.19/ABREABHNHANDVK/POC1618/008907/071124/210753 +BELEGDRUCK=J +ORIGINAL=1 +FAXVERSAND=N +Depot-Nr. Abrechnungs-Nr. Seite-Nr. EMAILVERSAND=N +00000000000 64518224 2 DEPOTNUMMER=00000000000 +DEPOTUNTERBEZEICHNUNG= +VERSANDARTENSCHLUESSEL=DRUCK +ADRESSZEILE1=Herr +ADRESSZEILE2=Vorname Nachname +Fondsart: Aktienfonds (§ 2 Abs. 6 InvStG) ADRESSZEILE3=Straße 1 +Angewendete Teilfreistellungsquote: 30% ADRESSZEILE4=12345 Ort +Im Steuerabzugsverfahren werden generell - auch bei betrieblichen Anlegern - die Teilfreistellungsquoten (TFQ) für ADRESSZEILE5= +Privatanleger herangezogen. ADRESSZEILE6= +BELEGNUMMER=8907 +SEITENNUMMER=2 +Höhe der Teilfreistellung Privatanleger Betriebliche Anleger(natürliche Person) Körperschaft STEUERERSTATTUNG=N +Aktienfonds 30% 60% 80% +Mischfonds 15% 30% 40% +Immobilienfonds 60% 60% 60% +Immobilienfonds mit +überwiegend 80% 80% 80% +Auslandsimmobilien +Sonstiger Investmentfonds 0% 0% 0% +Aggregierte Order ggf. zum Mischkurs. +* Die angegebene Zeit entspricht den Angaben der Handelspartner gemäß der lokalen Zeit in Deutschland (Mitteleuropäische Zeit bzw. Mitteleuropäische Sommerzeit). +Widerrufsbelehrung für den Erwerb von Anteilen oder Aktien eines offenen Investmentvermögens: Ist der Käufer von Anteilen oder Aktien eines offenen Investmentvermögens +durch mündliche Verhandlungen außerhalb der ständigen Geschäftsräume desjenigen, der die Anteile oder Aktien verkauft oder den Verkauf vermittelt hat, dazu bestimmt worden, +eine auf den Kauf gerichtete Willenserklärung abzugeben, so ist er an diese Erklärung nur gebunden, wenn er sie nicht innerhalb einer Frist von zwei Wochen bei der +Verwaltungsgesellschaft oder einem Repräsentanten im Sinne des § 319 KAGB schriftlich widerruft. +Dieser Beleg wird maschinell erstellt und daher nicht unterschrieben. +BNP Paribas S.A. Niederlassung Deutschland > Standort: München > Landsberger Straße 300 > 80687 München > Postadresse: DAB BNP Paribas > Postfach 2547 > +90011 Nürnberg > Sitz: Nürnberg HRB Nürnberg 31129 > USt.-Ident-Nr.: DE191528929 > Sitz der Hauptniederlassung der BNP Paribas S.A.: 16, boulevard des Italiens +> 75009 Paris > Frankreich > Registergericht: R.C.S. Paris 662 042 449 > Président du Conseil d‘Administration: Jean Lemierre > Directeur Général: Jean-Laurent Bonnafé +3.19/ABREABHNHANDVK/POC1618/008907/071124/210753 + +``` \ No newline at end of file diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java index 7ea4089075..a427372460 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java @@ -29,6 +29,7 @@ public DABPDFExtractor(Client client) addBankIdentifier("DAB Bank"); addBankIdentifier("DAB bank AG"); addBankIdentifier("BNP Paribas S.A. Niederlassung Deutschland"); + addBankIdentifier("Ginmon GmbH"); addBuySellTransaction(); addDividendTransaction(); @@ -36,6 +37,7 @@ public DABPDFExtractor(Client client) addTaxAdjustmentTransaction(); addAdvanceTaxTransaction(); addAccountStatementTransaction(); + addNonImportableTransaction(); } @Override @@ -157,6 +159,21 @@ private void addBuySellTransaction() v.put("name", v.get("name") + " " + v.get("name1")); t.setSecurity(getOrCreateSecurity(v)); + }), + // @formatter:off + // SPDR MSCI Wrld Small Cap U.ETF Registered Shares o.N. IE00BCBJG560 + // Nominal Kurs + // STK 0,0425 EUR 97,1400 + // @formatter:on + section -> section // + .attributes("name", "isin", "currency") // + .match("^(?.*) (?[A-Z]{2}[A-Z0-9]{9}[0-9]).*$") // + .match("^(Nominal Kurs)$") // + .match("^(STK )(?[\\.,\\d]+) (?[\\w]{3}) ([\\.,\\d]+)$") // + .assign((t, v) -> { + t.setSecurity(getOrCreateSecurity(v)); + t.setShares(asShares(v.get("shares"))); + t.setDate(asDate(v.get("date"), v.get("time"))); })) // @formatter:off @@ -1026,7 +1043,7 @@ private void addBuySellTaxReturnBlock(DocumentType type) private void addAccountStatementTransaction() { - final DocumentType type = new DocumentType("(Verm.gensbericht|Verm.gensstatus)", // + final DocumentType type = new DocumentType("(Verm.gensbericht|Verm.gensstatus|Kontoauszug)", // documentContext -> documentContext // .oneOf( // // @formatter:off @@ -1044,6 +1061,21 @@ private void addAccountStatementTransaction() .match("^Referenzw.hrung (?.*)$") // .assign((ctx, v) -> { if ("Euro".equals(trim(v.get("currency")))) ctx.put("currency", "EUR"); + }), + // @formatter:off + // 28.08.2024 + // Buchung Valuta Buchungsinformation Soll Haben + // 00.00. Alter Kontostand: EUR 0,00+ + // @formatter:on + section -> section // + .attributes("year", "currency") // + .match("^[\\d]{2}\\.[\\d]{2}\\.(?[\\d]{4})$") // + .match("^Buchung Valuta Buchungsinformation Soll Haben$") // + .match("^[\\d]{2}\\.[\\d]{2}\\. Alter Kontostand: (?[\\w]{3}) [\\.,\\d]+\\+$") // + .assign((ctx, v) -> { + ctx.put("year", v.get("year")); + ctx.put("currency", asCurrencyCode( + v.get("currency"))); }))); this.addDocumentTyp(type); @@ -1221,6 +1253,138 @@ private void addAccountStatementTransaction() }) .wrap(TransactionItem::new)); + + // @formatter:off + // 28.08. 28.08. vermögenswirksame Leistung 26,59+ + // Company where VL is payed from 000/UVXY VL + // Nachname, Vo. + // @formatter:on + Block depositBlock_Format03 = new Block( + "^([\\d]{2}\\.[\\d]{2}\\.) ([\\d]{2}\\.[\\d]{2}\\.) (vermögenswirksame Leistung) ([\\.,\\d]+)\\+$"); + type.addBlock(depositBlock_Format03); + depositBlock_Format03.set(new Transaction() + + .subject(() -> { + AccountTransaction accountTransaction = new AccountTransaction(); + accountTransaction.setType(AccountTransaction.Type.DEPOSIT); + return accountTransaction; + }) + + .section("note", "date", "amount") // + .documentContext("year", "currency") // + .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (?vermögenswirksame Leistung) (?[\\.,\\d]+)\\+$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date") + v.get("year"))); + t.setCurrencyCode(v.get("currency")); + t.setAmount(asAmount(v.get("amount"))); + t.setNote(v.get("note")); + }) + + .wrap(TransactionItem::new)); + + // @formatter:off + // 11.11. 11.11. SEPA-Überweisung 50,00- + // AGKRGWWWRHABNBNBOZSPCR Ginmon End to End- + // ID:DAB/B3/480606009/2024-11-11 + // IBAN: DE00000000000000000000 + // BIC: BICXXXXX001 + // Empfänger: Vorname Nachname + // @formatter:on + Block removalBlock_Format02 = new Block( + "^([\\d]{2}\\.[\\d]{2}\\.) ([\\d]{2}\\.[\\d]{2}\\.) (SEPA\\-Überweisung) ([\\.,\\d]+)\\-$"); + type.addBlock(removalBlock_Format02); + removalBlock_Format02.set(new Transaction() + + .subject(() -> { + AccountTransaction accountTransaction = new AccountTransaction(); + accountTransaction.setType(AccountTransaction.Type.REMOVAL); + return accountTransaction; + }) + + .section("note", "date", "amount") // + .documentContext("year", "currency") // + .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (?SEPA\\-Überweisung) (?[\\.,\\d]+)\\-$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date") + v.get("year"))); + t.setCurrencyCode(v.get("currency")); + t.setAmount(asAmount(v.get("amount"))); + t.setNote(v.get("note")); + }) + + .wrap(TransactionItem::new)); + + // @formatter:off + // 09.10. 09.10. Verwalterpreis 0,02- + // Ginmon Gebuehrenrechnung September 2024 End to End- + // ID:SEPA-EINZUG + // IBAN: DE62701204003335687004 + // BIC: DABBDEMMXXX + // Empfänger: Ginmon Vermoegensverwaltung GmbH + // @formatter:on + Block feeBlock_Format01 = new Block( + "^([\\d]{2}\\.[\\d]{2}\\.) ([\\d]{2}\\.[\\d]{2}\\.) (Verwalterpreis) ([\\.,\\d]+)\\-$"); + type.addBlock(feeBlock_Format01); + feeBlock_Format01.set(new Transaction() + + .subject(() -> { + AccountTransaction accountTransaction = new AccountTransaction(); + accountTransaction.setType(AccountTransaction.Type.FEES); + return accountTransaction; + }) + + .section("amount", "date", "note") // + .documentContext("currency", "year") // + .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (Verwalterpreis) (?[\\.,\\d]+)\\-$") // + .match("^(?.*) End to End\\-") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date") + v.get("year"))); + t.setCurrencyCode(v.get("currency")); + t.setAmount(asAmount(v.get("amount"))); + t.setNote(v.get("note")); + }) + + .wrap(TransactionItem::new)); + + // @formatter:off + // 07.11. 11.11. Wertpapierverkauf 0,49+ + // VKF A2061191320241107 IE00B52MJY50* 0,003 + // + // 27.09. 01.10. Wertpapierkauf 6,26- + // KAUF A6239874820240927 IE00BL25JM42* 0,150 + // @formatter:on + Block BuySellBlock = new Block( + "^([\\d]{2}\\.[\\d]{2}\\.) ([\\d]{2}\\.[\\d]{2}\\.) (Wertpapierverkauf|Wertpapierkauf) ([\\.,\\d]+)[\\+\\-]$"); + type.addBlock(BuySellBlock); + BuySellBlock.set(new Transaction() + + .subject(() -> { + BuySellEntry portfolioTransaction = new BuySellEntry(); + portfolioTransaction.setType(PortfolioTransaction.Type.BUY); + return portfolioTransaction; + }) + + .section("amount", "date", "isin", "shares", "type") // + .documentContext("currency", "year") // + .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (?Wertpapierverkauf|Wertpapierkauf) (?[\\.,\\d]+)[\\+\\-]$") // + .match("^.* (?[A-Z]{2}[A-Z0-9]{9}[0-9])\\* +(?[\\.,\\d]+)$") // + .assign((t, v) -> { + if ("Wertpapierverkauf".equals(v.get("type"))) + t.setType(PortfolioTransaction.Type.SELL); + t.setSecurity(getOrCreateSecurity(v)); + t.setDate(asDate(v.get("date") + v.get("year"))); + t.setCurrencyCode(v.get("currency")); + t.setShares(asShares(v.get("shares"))); + t.setAmount(asAmount(v.get("amount"))); + v.getTransactionContext().put(FAILURE, + Messages.MsgErrorTransactionAlternativeDocumentRequired); + }) + + .wrap((t, ctx) -> { + BuySellEntryItem item = new BuySellEntryItem(t); + if (ctx.getString(FAILURE) != null) + item.setFailureMessage(ctx.getString(FAILURE)); + return item; + })); } private > void addTaxesSectionsTransaction(T transaction, DocumentType type) @@ -1425,4 +1589,64 @@ private > void addFeesSectionsTransaction(T transaction .match("^.*[\\s]{1,}Transaktionsentgelt (?[\\w]{3}) (?[\\.,\\d]+)\\-$") // .assign((t, v) -> processFeeEntries(t, v, type)); } + + private void addNonImportableTransaction() + { + final DocumentType type = new DocumentType("(Gebührenabrechnung)", // + documentContext -> documentContext // + // @formatter:off + // Rechnungsdatum / Invoice date: 31.10.2024 + // Rechnungsnummer /Invoice no: 00000002024101 + // @formatter:on + .section("date") // + .match("^Rechnungsdatum / Invoice date: (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4})$") // + .assign((ctx, v) -> { + ctx.put("date", v.get("date")); + })); + + this.addDocumentTyp(type); + + Transaction pdfTransaction = new Transaction<>(); + + Block firstRelevantLine = new Block("^(Gebührenabrechnung) (.*)$"); + type.addBlock(firstRelevantLine); + firstRelevantLine.set(pdfTransaction); + + pdfTransaction // + + .subject(() -> { + AccountTransaction accountTransaction = new AccountTransaction(); + accountTransaction.setType(AccountTransaction.Type.FEES); + return accountTransaction; + }) + + // @formatter:off + // Gebührenabrechnung Oktober + // Invoice October + // Zeitraum vom 01.10.2024 – 31.10.2024 + // Period of 01.10.2024 – 31.10.2024 + // Position Berechungsbasis Gebühr Betrag + // Calculation Fee Amount + // Grundgebühr 57.60 € 0.7500% p.a. 0.04 € + // @formatter:on + .section("amount", "currency") // + .documentContext("date") // + .match("^Rechnungsbetrag (?[\\.,\\d]+) (?\\p{Sc})$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + t.setAmount(asAmount(v.get("amount"), "en", "US")); + v.getTransactionContext().put(FAILURE, + Messages.MsgErrorTransactionAlternativeDocumentRequired); + }) + + .wrap((t, ctx) -> { + TransactionItem item = new TransactionItem(t); + + if (ctx.getString(FAILURE) != null) + item.setFailureMessage(ctx.getString(FAILURE)); + + return item; + }); + } } \ No newline at end of file From a0339a7c30163a186b2b8e874ec793f2d1772bc3 Mon Sep 17 00:00:00 2001 From: chka2233 Date: Wed, 4 Dec 2024 20:54:29 +0100 Subject: [PATCH 2/3] Move invoice document to new created Ginmon specific importer. --- .../pdf/dab/DABPDFExtractorTest.java | 23 ----- .../pdf/{dab => ginmon}/FeeInvoice01.txt | 0 .../pdf/ginmon/GinmonPDFExtractorTest.java | 55 ++++++++++++ .../datatransfer/pdf/DABPDFExtractor.java | 61 ------------- .../datatransfer/pdf/GinmonPDFExtractor.java | 87 +++++++++++++++++++ .../datatransfer/pdf/PDFImportAssistant.java | 1 + 6 files changed, 143 insertions(+), 84 deletions(-) rename name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/{dab => ginmon}/FeeInvoice01.txt (100%) create mode 100644 name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/GinmonPDFExtractorTest.java create mode 100644 name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/GinmonPDFExtractor.java diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java index b7d552f518..8b9b835a6a 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java @@ -3835,27 +3835,4 @@ public void testKontoumsaetze12() purchase(hasDate("2024-10-01"), hasAmount("EUR", 6.26), hasShares(0.15), // hasSource("Kontoumsaetze12.txt"), hasNote(null))))); } - - @Test - public void testFeeInvoice01() - { - DABPDFExtractor extractor = new DABPDFExtractor(new Client()); - - List errors = new ArrayList<>(); - - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "FeeInvoice01.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(withFailureMessage( // - Messages.MsgErrorTransactionAlternativeDocumentRequired, - fee(hasDate("2024-10-31"), hasAmount("EUR", 0.04), // - hasSource("FeeInvoice01.txt"), hasNote(null))))); - } } diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/FeeInvoice01.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/FeeInvoice01.txt similarity index 100% rename from name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/FeeInvoice01.txt rename to name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/FeeInvoice01.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/GinmonPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/GinmonPDFExtractorTest.java new file mode 100644 index 0000000000..9085dd9acb --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/GinmonPDFExtractorTest.java @@ -0,0 +1,55 @@ +package name.abuchen.portfolio.datatransfer.pdf.ginmon; + +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.fee; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasAmount; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasDate; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasNote; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasSource; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.withFailureMessage; +import static name.abuchen.portfolio.datatransfer.ExtractorTestUtilities.countAccountTransactions; +import static name.abuchen.portfolio.datatransfer.ExtractorTestUtilities.countBuySell; +import static name.abuchen.portfolio.datatransfer.ExtractorTestUtilities.countSecurities; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsEmptyCollection.empty; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import name.abuchen.portfolio.Messages; +import name.abuchen.portfolio.datatransfer.Extractor.Item; +import name.abuchen.portfolio.datatransfer.actions.AssertImportActions; +import name.abuchen.portfolio.datatransfer.pdf.GinmonPDFExtractor; +import name.abuchen.portfolio.datatransfer.pdf.PDFInputFile; +import name.abuchen.portfolio.model.Client; +import name.abuchen.portfolio.money.CurrencyUnit; + +@SuppressWarnings("nls") +public class GinmonPDFExtractorTest +{ + @Test + public void testFeeInvoice01() + { + GinmonPDFExtractor extractor = new GinmonPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "FeeInvoice01.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(withFailureMessage( // + Messages.MsgErrorTransactionAlternativeDocumentRequired, + fee(hasDate("2024-10-31"), hasAmount("EUR", 0.04), // + hasSource("FeeInvoice01.txt"), hasNote(null))))); + } +} diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java index a427372460..b0bb59342f 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java @@ -29,7 +29,6 @@ public DABPDFExtractor(Client client) addBankIdentifier("DAB Bank"); addBankIdentifier("DAB bank AG"); addBankIdentifier("BNP Paribas S.A. Niederlassung Deutschland"); - addBankIdentifier("Ginmon GmbH"); addBuySellTransaction(); addDividendTransaction(); @@ -37,7 +36,6 @@ public DABPDFExtractor(Client client) addTaxAdjustmentTransaction(); addAdvanceTaxTransaction(); addAccountStatementTransaction(); - addNonImportableTransaction(); } @Override @@ -1590,63 +1588,4 @@ private > void addFeesSectionsTransaction(T transaction .assign((t, v) -> processFeeEntries(t, v, type)); } - private void addNonImportableTransaction() - { - final DocumentType type = new DocumentType("(Gebührenabrechnung)", // - documentContext -> documentContext // - // @formatter:off - // Rechnungsdatum / Invoice date: 31.10.2024 - // Rechnungsnummer /Invoice no: 00000002024101 - // @formatter:on - .section("date") // - .match("^Rechnungsdatum / Invoice date: (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4})$") // - .assign((ctx, v) -> { - ctx.put("date", v.get("date")); - })); - - this.addDocumentTyp(type); - - Transaction pdfTransaction = new Transaction<>(); - - Block firstRelevantLine = new Block("^(Gebührenabrechnung) (.*)$"); - type.addBlock(firstRelevantLine); - firstRelevantLine.set(pdfTransaction); - - pdfTransaction // - - .subject(() -> { - AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.FEES); - return accountTransaction; - }) - - // @formatter:off - // Gebührenabrechnung Oktober - // Invoice October - // Zeitraum vom 01.10.2024 – 31.10.2024 - // Period of 01.10.2024 – 31.10.2024 - // Position Berechungsbasis Gebühr Betrag - // Calculation Fee Amount - // Grundgebühr 57.60 € 0.7500% p.a. 0.04 € - // @formatter:on - .section("amount", "currency") // - .documentContext("date") // - .match("^Rechnungsbetrag (?[\\.,\\d]+) (?\\p{Sc})$") // - .assign((t, v) -> { - t.setDateTime(asDate(v.get("date"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - t.setAmount(asAmount(v.get("amount"), "en", "US")); - v.getTransactionContext().put(FAILURE, - Messages.MsgErrorTransactionAlternativeDocumentRequired); - }) - - .wrap((t, ctx) -> { - TransactionItem item = new TransactionItem(t); - - if (ctx.getString(FAILURE) != null) - item.setFailureMessage(ctx.getString(FAILURE)); - - return item; - }); - } } \ No newline at end of file diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/GinmonPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/GinmonPDFExtractor.java new file mode 100644 index 0000000000..8a42100840 --- /dev/null +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/GinmonPDFExtractor.java @@ -0,0 +1,87 @@ +package name.abuchen.portfolio.datatransfer.pdf; + +import name.abuchen.portfolio.Messages; +import name.abuchen.portfolio.datatransfer.pdf.PDFParser.Block; +import name.abuchen.portfolio.datatransfer.pdf.PDFParser.DocumentType; +import name.abuchen.portfolio.datatransfer.pdf.PDFParser.Transaction; +import name.abuchen.portfolio.model.AccountTransaction; +import name.abuchen.portfolio.model.Client; + +@SuppressWarnings("nls") +public class GinmonPDFExtractor extends AbstractPDFExtractor +{ + public GinmonPDFExtractor(Client client) + { + super(client); + + addBankIdentifier("Ginmon GmbH"); + + addNonImportableTransaction(); + } + + @Override + public String getLabel() + { + return "Ginmon GmbH"; + } + + private void addNonImportableTransaction() + { + final DocumentType type = new DocumentType("(Gebührenabrechnung)", // + documentContext -> documentContext // + // @formatter:off + // Rechnungsdatum / Invoice date: 31.10.2024 + // Rechnungsnummer /Invoice no: 00000002024101 + // @formatter:on + .section("date") // + .match("^Rechnungsdatum / Invoice date: (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4})$") // + .assign((ctx, v) -> { + ctx.put("date", v.get("date")); + })); + + this.addDocumentTyp(type); + + Transaction pdfTransaction = new Transaction<>(); + + Block firstRelevantLine = new Block("^(Gebührenabrechnung) (.*)$"); + type.addBlock(firstRelevantLine); + firstRelevantLine.set(pdfTransaction); + + pdfTransaction // + + .subject(() -> { + AccountTransaction accountTransaction = new AccountTransaction(); + accountTransaction.setType(AccountTransaction.Type.FEES); + return accountTransaction; + }) + + // @formatter:off + // Gebührenabrechnung Oktober + // Invoice October + // Zeitraum vom 01.10.2024 – 31.10.2024 + // Period of 01.10.2024 – 31.10.2024 + // Position Berechungsbasis Gebühr Betrag + // Calculation Fee Amount + // Grundgebühr 57.60 € 0.7500% p.a. 0.04 € + // @formatter:on + .section("amount", "currency") // + .documentContext("date") // + .match("^Rechnungsbetrag (?[\\.,\\d]+) (?\\p{Sc})$") // + .assign((t, v) -> { + t.setDateTime(asDate(v.get("date"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + t.setAmount(asAmount(v.get("amount"), "en", "US")); + v.getTransactionContext().put(FAILURE, + Messages.MsgErrorTransactionAlternativeDocumentRequired); + }) + + .wrap((t, ctx) -> { + TransactionItem item = new TransactionItem(t); + + if (ctx.getString(FAILURE) != null) + item.setFailureMessage(ctx.getString(FAILURE)); + + return item; + }); + } +} \ No newline at end of file diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/PDFImportAssistant.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/PDFImportAssistant.java index 2338afb139..c4763e8942 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/PDFImportAssistant.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/PDFImportAssistant.java @@ -73,6 +73,7 @@ public PDFImportAssistant(Client client, List files) extractors.add(new FinTechGroupBankPDFExtractor(client)); extractors.add(new FirstradeSecuritiesIncPDFExtractor(client)); extractors.add(new GenoBrokerPDFExtractor(client)); + extractors.add(new GinmonPDFExtractor(client)); extractors.add(new GladbacherBankAGPDFExtractor(client)); extractors.add(new HargreavesLansdownPlcExtractor(client)); extractors.add(new HelloBankPDFExtractor(client)); From cbb234b3c9fd57f30e31d151a37e5ecbd4f14ddd Mon Sep 17 00:00:00 2001 From: Alexander Ott Date: Sat, 7 Dec 2024 12:11:25 +0100 Subject: [PATCH 3/3] Add and improve DAB and Ginmon PDF-Importer Add new Ginmon PDF-Importer --- .../pdf/dab/DABPDFExtractorTest.java | 29 ++- .../pdf/ginmon/GinmonPDFExtractorTest.java | 8 +- .../datatransfer/pdf/DABPDFExtractor.java | 205 +++++++++--------- .../datatransfer/pdf/GinmonPDFExtractor.java | 68 +++--- 4 files changed, 164 insertions(+), 146 deletions(-) diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java index 8b9b835a6a..31f6ff3c68 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dab/DABPDFExtractorTest.java @@ -3753,8 +3753,13 @@ public void testKontoumsaetze09() new AssertImportActions().check(results, CurrencyUnit.EUR); // assert transaction - assertThat(results, hasItem(fee(hasDate("2024-10-09"), hasAmount("EUR", 0.02), // - hasSource("Kontoumsaetze09.txt"), hasNote("Ginmon Gebuehrenrechnung September 2024")))); + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionAlternativeDocumentRequired, // + fee( // + hasDate("2024-10-09"), // + hasSource("Kontoumsaetze09.txt"), // + hasNote("Ginmon Gebuehrenrechnung September 2024"), // + hasAmount("EUR", 0.02))))); } @Test @@ -3802,9 +3807,13 @@ public void testKontoumsaetze11() // assert transaction assertThat(results, hasItem(withFailureMessage( // - Messages.MsgErrorTransactionAlternativeDocumentRequired, - sale(hasDate("2024-11-11"), hasAmount("EUR", 0.49), hasShares(0.003), // - hasSource("Kontoumsaetze11.txt"), hasNote(null))))); + Messages.MsgErrorTransactionAlternativeDocumentRequired, // + sale( // + hasDate("2024-11-11"), hasShares(0.003), // + hasSource("Kontoumsaetze11.txt"), // + hasNote(null), // + hasAmount("EUR", 0.49), hasGrossValue("EUR", 0.49), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test @@ -3831,8 +3840,12 @@ public void testKontoumsaetze12() // assert transaction assertThat(results, hasItem(withFailureMessage( // - Messages.MsgErrorTransactionAlternativeDocumentRequired, - purchase(hasDate("2024-10-01"), hasAmount("EUR", 6.26), hasShares(0.15), // - hasSource("Kontoumsaetze12.txt"), hasNote(null))))); + Messages.MsgErrorTransactionAlternativeDocumentRequired, // + purchase(// + hasDate("2024-10-01"), hasShares(0.15), // + hasSource("Kontoumsaetze12.txt"), // + hasNote(null), // + hasAmount("EUR", 6.26), hasGrossValue("EUR", 6.26), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } } diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/GinmonPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/GinmonPDFExtractorTest.java index 9085dd9acb..c874d7567f 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/GinmonPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/ginmon/GinmonPDFExtractorTest.java @@ -5,7 +5,6 @@ import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasDate; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasNote; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasSource; -import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.withFailureMessage; import static name.abuchen.portfolio.datatransfer.ExtractorTestUtilities.countAccountTransactions; import static name.abuchen.portfolio.datatransfer.ExtractorTestUtilities.countBuySell; import static name.abuchen.portfolio.datatransfer.ExtractorTestUtilities.countSecurities; @@ -19,7 +18,6 @@ import org.junit.Test; -import name.abuchen.portfolio.Messages; import name.abuchen.portfolio.datatransfer.Extractor.Item; import name.abuchen.portfolio.datatransfer.actions.AssertImportActions; import name.abuchen.portfolio.datatransfer.pdf.GinmonPDFExtractor; @@ -47,9 +45,7 @@ public void testFeeInvoice01() new AssertImportActions().check(results, CurrencyUnit.EUR); // assert transaction - assertThat(results, hasItem(withFailureMessage( // - Messages.MsgErrorTransactionAlternativeDocumentRequired, - fee(hasDate("2024-10-31"), hasAmount("EUR", 0.04), // - hasSource("FeeInvoice01.txt"), hasNote(null))))); + assertThat(results, hasItem(fee(hasDate("2024-10-31"), hasAmount("EUR", 0.04), // + hasSource("FeeInvoice01.txt"), hasNote("R.-Nr.: 00000002024101 | 01.10.2024 – 31.10.2024")))); } } diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java index b0bb59342f..845d043edf 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DABPDFExtractor.java @@ -166,8 +166,8 @@ private void addBuySellTransaction() section -> section // .attributes("name", "isin", "currency") // .match("^(?.*) (?[A-Z]{2}[A-Z0-9]{9}[0-9]).*$") // - .match("^(Nominal Kurs)$") // - .match("^(STK )(?[\\.,\\d]+) (?[\\w]{3}) ([\\.,\\d]+)$") // + .find("Nominal Kurs") // + .match("^STK (?[\\.,\\d]+) (?[\\w]{3}) [\\.,\\d]+$") // .assign((t, v) -> { t.setSecurity(getOrCreateSecurity(v)); t.setShares(asShares(v.get("shares"))); @@ -1058,7 +1058,8 @@ private void addAccountStatementTransaction() .attributes("currency") // .match("^Referenzw.hrung (?.*)$") // .assign((ctx, v) -> { - if ("Euro".equals(trim(v.get("currency")))) ctx.put("currency", "EUR"); + if ("Euro".equals(trim(v.get("currency")))) + ctx.put("currency", "EUR"); }), // @formatter:off // 28.08.2024 @@ -1068,12 +1069,11 @@ private void addAccountStatementTransaction() section -> section // .attributes("year", "currency") // .match("^[\\d]{2}\\.[\\d]{2}\\.(?[\\d]{4})$") // - .match("^Buchung Valuta Buchungsinformation Soll Haben$") // + .find("Buchung Valuta Buchungsinformation Soll Haben") // .match("^[\\d]{2}\\.[\\d]{2}\\. Alter Kontostand: (?[\\w]{3}) [\\.,\\d]+\\+$") // .assign((ctx, v) -> { ctx.put("year", v.get("year")); - ctx.put("currency", asCurrencyCode( - v.get("currency"))); + ctx.put("currency", asCurrencyCode(v.get("currency"))); }))); this.addDocumentTyp(type); @@ -1105,75 +1105,75 @@ private void addAccountStatementTransaction() .wrap(TransactionItem::new)); // @formatter:off - // SEPA-Überweisung MUSTERMANN, MAX 05.07.19 15.000,00 // no minus sign! - // SEPA-Dauerauftrag MUSTERMANN, MAX 15.07.19 300,00 // no minus sign! + // 23.09.2022 23.09.2022 SEPA-Überweisung Anlage 2.000,00 EUR // @formatter:on - Block removalBlock_Format01 = new Block("^(SEPA\\-.berweisung|SEPA\\-Dauerauftrag) .* [\\d]{2}\\.[\\d]{2}\\.[\\d]{2} [\\.,\\d]+$"); - type.addBlock(removalBlock_Format01); - removalBlock_Format01.set(new Transaction() + Block depositBlock_Format02 = new Block("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} SEPA\\-.berweisung .* [\\.,\\d]+ [\\w]{3}$"); + type.addBlock(depositBlock_Format02); + depositBlock_Format02.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.REMOVAL); + accountTransaction.setType(AccountTransaction.Type.DEPOSIT); return accountTransaction; }) - .section("note", "date", "amount") // - .documentContext("currency") // - .match("^(?(SEPA\\-.berweisung|SEPA\\-Dauerauftrag)) .* (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{2}) (?[\\.,\\d]+)$") // + .section("date", "note", "amount", "currency") // + .match("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) (?SEPA\\-.berweisung) .* (?[\\.,\\d]+) (?[\\w]{3})$") // .assign((t, v) -> { t.setDateTime(asDate(v.get("date"))); t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(v.get("currency")); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); t.setNote(v.get("note")); }) .wrap(TransactionItem::new)); // @formatter:off - // Belastung Porto 05.04.16 0,70 // no minus sign! + // 28.08. 28.08. vermögenswirksame Leistung 26,59+ // @formatter:on - Block feesBlock_Format01 = new Block("^Belastung .* [\\d]{2}\\.[\\d]{2}\\.[\\d]{2} [\\.,\\d]+$"); - type.addBlock(feesBlock_Format01); - feesBlock_Format01.set(new Transaction() + Block depositBlock_Format03 = new Block("^[\\d]{2}\\.[\\d]{2}\\. [\\d]{2}\\.[\\d]{2}\\. verm.genswirksame Leistung [\\.,\\d]+\\+$"); + type.addBlock(depositBlock_Format03); + depositBlock_Format03.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.FEES); + accountTransaction.setType(AccountTransaction.Type.DEPOSIT); return accountTransaction; }) - .section("note", "date", "amount") // - .documentContext("currency") // - .match("^Belastung (?.*) (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{2}) (?[\\.,\\d]+)$") // + .section("date", "note", "amount") // + .documentContext("year", "currency") // + .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (?verm.genswirksame Leistung) (?[\\.,\\d]+)\\+$") // .assign((t, v) -> { - t.setDateTime(asDate(v.get("date"))); - t.setAmount(asAmount(v.get("amount"))); + t.setDateTime(asDate(v.get("date") + v.get("year"))); t.setCurrencyCode(v.get("currency")); + t.setAmount(asAmount(v.get("amount"))); t.setNote(v.get("note")); }) .wrap(TransactionItem::new)); // @formatter:off - // 23.09.2022 23.09.2022 SEPA-Überweisung Anlage 2.000,00 EUR + // SEPA-Überweisung MUSTERMANN, MAX 05.07.19 15.000,00 // no minus sign! + // SEPA-Dauerauftrag MUSTERMANN, MAX 15.07.19 300,00 // no minus sign! // @formatter:on - Block depositBlock_Format02 = new Block("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} SEPA\\-.berweisung .* [\\.,\\d]+ [\\w]{3}$"); - type.addBlock(depositBlock_Format02); - depositBlock_Format02.set(new Transaction() + Block removalBlock_Format01 = new Block("^(SEPA\\-.berweisung|SEPA\\-Dauerauftrag) .* [\\d]{2}\\.[\\d]{2}\\.[\\d]{2} [\\.,\\d]+$"); + type.addBlock(removalBlock_Format01); + removalBlock_Format01.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.DEPOSIT); + accountTransaction.setType(AccountTransaction.Type.REMOVAL); return accountTransaction; }) - .section("note", "date", "amount", "currency") // - .match("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) (?SEPA\\-.berweisung) .* (?[\\.,\\d]+) (?[\\w]{3})$") // + .section("note", "date", "amount") // + .documentContext("currency") // + .match("^(?(SEPA\\-.berweisung|SEPA\\-Dauerauftrag)) .* (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{2}) (?[\\.,\\d]+)$") // .assign((t, v) -> { t.setDateTime(asDate(v.get("date"))); t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); + t.setCurrencyCode(v.get("currency")); t.setNote(v.get("note")); }) @@ -1182,9 +1182,9 @@ private void addAccountStatementTransaction() // @formatter:off // 23.09.2022 23.09.2022 SEPA-Überweisung Entsparen -2.000,00 EUR // @formatter:on - Block removalBlock = new Block("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} SEPA\\-.berweisung .* -[\\.,\\d]+ [\\w]{3}$"); - type.addBlock(removalBlock); - removalBlock.set(new Transaction() + Block removalBlock_Format02 = new Block("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} SEPA\\-.berweisung .* -[\\.,\\d]+ [\\w]{3}$"); + type.addBlock(removalBlock_Format02); + removalBlock_Format02.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); @@ -1192,7 +1192,7 @@ private void addAccountStatementTransaction() return accountTransaction; }) - .section("note", "date", "amount", "currency") // + .section("date", "note", "amount", "currency") // .match("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) (?SEPA\\-.berweisung) .* -(?[\\.,\\d]+) (?[\\w]{3})$") // .assign((t, v) -> { t.setDateTime(asDate(v.get("date"))); @@ -1204,35 +1204,36 @@ private void addAccountStatementTransaction() .wrap(TransactionItem::new)); // @formatter:off - // 23.09.2022 23.09.2022 Sollzinsen -100,00 EUR + // 11.11. 11.11. SEPA-Überweisung 50,00- // @formatter:on - Block interestChargeBlock = new Block("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} Sollzinsen -[\\.,\\d]+ [\\w]{3}$"); - type.addBlock(interestChargeBlock); - interestChargeBlock.set(new Transaction() + Block removalBlock_Format03 = new Block("^[\\d]{2}\\.[\\d]{2}\\. [\\d]{2}\\.[\\d]{2}\\. SEPA\\-.berweisung [\\.,\\d]+\\-$"); + type.addBlock(removalBlock_Format03); + removalBlock_Format03.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.INTEREST_CHARGE); + accountTransaction.setType(AccountTransaction.Type.REMOVAL); return accountTransaction; }) - .section("note", "date", "amount", "currency") // - .match("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) (?Sollzinsen) -(?[\\.,\\d]+) (?[\\w]{3})$") // + .section("note", "date", "amount") // + .documentContext("year", "currency") // + .match("^[\\d]{2}\\.[\\d]{2}\\. (?[\\d]{2}\\.[\\d]{2}\\.) (?SEPA\\-.berweisung) (?[\\.,\\d]+)\\-$") // .assign((t, v) -> { - t.setDateTime(asDate(v.get("date"))); + t.setDateTime(asDate(v.get("date") + v.get("year"))); + t.setCurrencyCode(v.get("currency")); t.setAmount(asAmount(v.get("amount"))); - t.setCurrencyCode(asCurrencyCode(v.get("currency"))); t.setNote(v.get("note")); }) .wrap(TransactionItem::new)); // @formatter:off - // SEPA-Lastschrift Lastschrift Managementgebühr 29.06.20 53,02 + // Belastung Porto 05.04.16 0,70 // no minus sign! // @formatter:on - Block feesBlock = new Block("^SEPA\\-Lastschrift Lastschrift Managementgeb.hr .*$"); - type.addBlock(feesBlock); - feesBlock.set(new Transaction() + Block feesBlock_Format01 = new Block("^Belastung .* [\\d]{2}\\.[\\d]{2}\\.[\\d]{2} [\\.,\\d]+$"); + type.addBlock(feesBlock_Format01); + feesBlock_Format01.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); @@ -1242,7 +1243,7 @@ private void addAccountStatementTransaction() .section("note", "date", "amount") // .documentContext("currency") // - .match("^SEPA\\-Lastschrift Lastschrift (?Managementgeb.hr) (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{2}) (?[\\.,\\d]+)$") // + .match("^Belastung (?.*) (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{2}) (?[\\.,\\d]+)$") // .assign((t, v) -> { t.setDateTime(asDate(v.get("date"))); t.setAmount(asAmount(v.get("amount"))); @@ -1252,92 +1253,88 @@ private void addAccountStatementTransaction() .wrap(TransactionItem::new)); - // @formatter:off - // 28.08. 28.08. vermögenswirksame Leistung 26,59+ - // Company where VL is payed from 000/UVXY VL - // Nachname, Vo. + // @formatter:off + // SEPA-Lastschrift Lastschrift Managementgebühr 29.06.20 53,02 // @formatter:on - Block depositBlock_Format03 = new Block( - "^([\\d]{2}\\.[\\d]{2}\\.) ([\\d]{2}\\.[\\d]{2}\\.) (vermögenswirksame Leistung) ([\\.,\\d]+)\\+$"); - type.addBlock(depositBlock_Format03); - depositBlock_Format03.set(new Transaction() + Block feesBlock_Format02 = new Block("^SEPA\\-Lastschrift Lastschrift Managementgeb.hr .*$"); + type.addBlock(feesBlock_Format02); + feesBlock_Format02.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.DEPOSIT); + accountTransaction.setType(AccountTransaction.Type.FEES); return accountTransaction; }) .section("note", "date", "amount") // - .documentContext("year", "currency") // - .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (?vermögenswirksame Leistung) (?[\\.,\\d]+)\\+$") // + .documentContext("currency") // + .match("^SEPA\\-Lastschrift Lastschrift (?Managementgeb.hr) (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{2}) (?[\\.,\\d]+)$") // .assign((t, v) -> { - t.setDateTime(asDate(v.get("date") + v.get("year"))); - t.setCurrencyCode(v.get("currency")); + t.setDateTime(asDate(v.get("date"))); t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(v.get("currency")); t.setNote(v.get("note")); }) .wrap(TransactionItem::new)); // @formatter:off - // 11.11. 11.11. SEPA-Überweisung 50,00- - // AGKRGWWWRHABNBNBOZSPCR Ginmon End to End- - // ID:DAB/B3/480606009/2024-11-11 - // IBAN: DE00000000000000000000 - // BIC: BICXXXXX001 - // Empfänger: Vorname Nachname + // 09.10. 09.10. Verwalterpreis 0,02- + // Ginmon Gebuehrenrechnung September 2024 End to End- // @formatter:on - Block removalBlock_Format02 = new Block( - "^([\\d]{2}\\.[\\d]{2}\\.) ([\\d]{2}\\.[\\d]{2}\\.) (SEPA\\-Überweisung) ([\\.,\\d]+)\\-$"); - type.addBlock(removalBlock_Format02); - removalBlock_Format02.set(new Transaction() + Block feeBlock_Format03 = new Block("^[\\d]{2}\\.[\\d]{2}\\. [\\d]{2}\\.[\\d]{2}\\. Verwalterpreis [\\.,\\d]+\\-$"); + type.addBlock(feeBlock_Format03); + feeBlock_Format03.setMaxSize(2); + feeBlock_Format03.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.REMOVAL); + accountTransaction.setType(AccountTransaction.Type.FEES); return accountTransaction; }) - .section("note", "date", "amount") // - .documentContext("year", "currency") // - .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (?SEPA\\-Überweisung) (?[\\.,\\d]+)\\-$") // + .section("amount", "date", "note") // + .documentContext("currency", "year") // + .match("^[\\d]{2}\\.[\\d]{2}\\. (?[\\d]{2}\\.[\\d]{2}\\.) Verwalterpreis (?[\\.,\\d]+)\\-$") // + .match("^(?.*) End to End\\-") // .assign((t, v) -> { t.setDateTime(asDate(v.get("date") + v.get("year"))); t.setCurrencyCode(v.get("currency")); t.setAmount(asAmount(v.get("amount"))); t.setNote(v.get("note")); + + if (v.get("note").startsWith("Ginmon Gebuehrenrechnung")) + v.getTransactionContext().put(FAILURE, Messages.MsgErrorTransactionAlternativeDocumentRequired); }) - .wrap(TransactionItem::new)); + .wrap((t, ctx) -> { + TransactionItem item = new TransactionItem(t); + + if (ctx.getString(FAILURE) != null) + item.setFailureMessage(ctx.getString(FAILURE)); + + return item; + })); // @formatter:off - // 09.10. 09.10. Verwalterpreis 0,02- - // Ginmon Gebuehrenrechnung September 2024 End to End- - // ID:SEPA-EINZUG - // IBAN: DE62701204003335687004 - // BIC: DABBDEMMXXX - // Empfänger: Ginmon Vermoegensverwaltung GmbH + // 23.09.2022 23.09.2022 Sollzinsen -100,00 EUR // @formatter:on - Block feeBlock_Format01 = new Block( - "^([\\d]{2}\\.[\\d]{2}\\.) ([\\d]{2}\\.[\\d]{2}\\.) (Verwalterpreis) ([\\.,\\d]+)\\-$"); - type.addBlock(feeBlock_Format01); - feeBlock_Format01.set(new Transaction() + Block interestChargeBlock = new Block("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} Sollzinsen -[\\.,\\d]+ [\\w]{3}$"); + type.addBlock(interestChargeBlock); + interestChargeBlock.set(new Transaction() .subject(() -> { AccountTransaction accountTransaction = new AccountTransaction(); - accountTransaction.setType(AccountTransaction.Type.FEES); + accountTransaction.setType(AccountTransaction.Type.INTEREST_CHARGE); return accountTransaction; }) - .section("amount", "date", "note") // - .documentContext("currency", "year") // - .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (Verwalterpreis) (?[\\.,\\d]+)\\-$") // - .match("^(?.*) End to End\\-") // + .section("note", "date", "amount", "currency") // + .match("^[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) (?Sollzinsen) -(?[\\.,\\d]+) (?[\\w]{3})$") // .assign((t, v) -> { - t.setDateTime(asDate(v.get("date") + v.get("year"))); - t.setCurrencyCode(v.get("currency")); + t.setDateTime(asDate(v.get("date"))); t.setAmount(asAmount(v.get("amount"))); + t.setCurrencyCode(asCurrencyCode(v.get("currency"))); t.setNote(v.get("note")); }) @@ -1350,8 +1347,7 @@ private void addAccountStatementTransaction() // 27.09. 01.10. Wertpapierkauf 6,26- // KAUF A6239874820240927 IE00BL25JM42* 0,150 // @formatter:on - Block BuySellBlock = new Block( - "^([\\d]{2}\\.[\\d]{2}\\.) ([\\d]{2}\\.[\\d]{2}\\.) (Wertpapierverkauf|Wertpapierkauf) ([\\.,\\d]+)[\\+\\-]$"); + Block BuySellBlock = new Block("^[\\d]{2}\\.[\\d]{2}\\. [\\d]{2}\\.[\\d]{2}\\. (Wertpapierverkauf|Wertpapierkauf) [\\.,\\d]+[\\+\\-]$"); type.addBlock(BuySellBlock); BuySellBlock.set(new Transaction() @@ -1363,24 +1359,27 @@ private void addAccountStatementTransaction() .section("amount", "date", "isin", "shares", "type") // .documentContext("currency", "year") // - .match("^([\\d]{2}\\.[\\d]{2}\\.) (?[\\d]{2}\\.[\\d]{2}\\.) (?Wertpapierverkauf|Wertpapierkauf) (?[\\.,\\d]+)[\\+\\-]$") // - .match("^.* (?[A-Z]{2}[A-Z0-9]{9}[0-9])\\* +(?[\\.,\\d]+)$") // + .match("^[\\d]{2}\\.[\\d]{2}\\. (?[\\d]{2}\\.[\\d]{2}\\.) (?Wertpapierverkauf|Wertpapierkauf) (?[\\.,\\d]+)[\\+\\-]$") // + .match("^.* (?[A-Z]{2}[A-Z0-9]{9}[0-9])\\*[\\s]{1,}(?[\\.,\\d]+)$") // .assign((t, v) -> { if ("Wertpapierverkauf".equals(v.get("type"))) t.setType(PortfolioTransaction.Type.SELL); + t.setSecurity(getOrCreateSecurity(v)); + t.setDate(asDate(v.get("date") + v.get("year"))); t.setCurrencyCode(v.get("currency")); t.setShares(asShares(v.get("shares"))); t.setAmount(asAmount(v.get("amount"))); - v.getTransactionContext().put(FAILURE, - Messages.MsgErrorTransactionAlternativeDocumentRequired); + v.getTransactionContext().put(FAILURE, Messages.MsgErrorTransactionAlternativeDocumentRequired); }) .wrap((t, ctx) -> { BuySellEntryItem item = new BuySellEntryItem(t); + if (ctx.getString(FAILURE) != null) item.setFailureMessage(ctx.getString(FAILURE)); + return item; })); } diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/GinmonPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/GinmonPDFExtractor.java index 8a42100840..afbfa33d5d 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/GinmonPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/GinmonPDFExtractor.java @@ -1,11 +1,15 @@ package name.abuchen.portfolio.datatransfer.pdf; -import name.abuchen.portfolio.Messages; +import static name.abuchen.portfolio.util.TextUtil.concatenate; +import static name.abuchen.portfolio.util.TextUtil.trim; + +import name.abuchen.portfolio.datatransfer.ExtractorUtils; import name.abuchen.portfolio.datatransfer.pdf.PDFParser.Block; import name.abuchen.portfolio.datatransfer.pdf.PDFParser.DocumentType; import name.abuchen.portfolio.datatransfer.pdf.PDFParser.Transaction; import name.abuchen.portfolio.model.AccountTransaction; import name.abuchen.portfolio.model.Client; +import name.abuchen.portfolio.money.Values; @SuppressWarnings("nls") public class GinmonPDFExtractor extends AbstractPDFExtractor @@ -14,7 +18,7 @@ public GinmonPDFExtractor(Client client) { super(client); - addBankIdentifier("Ginmon GmbH"); + addBankIdentifier("Ginmon Vermögensverwaltung GmbH"); addNonImportableTransaction(); } @@ -22,28 +26,17 @@ public GinmonPDFExtractor(Client client) @Override public String getLabel() { - return "Ginmon GmbH"; + return "Ginmon Vermögensverwaltung GmbH"; } private void addNonImportableTransaction() { - final DocumentType type = new DocumentType("(Gebührenabrechnung)", // - documentContext -> documentContext // - // @formatter:off - // Rechnungsdatum / Invoice date: 31.10.2024 - // Rechnungsnummer /Invoice no: 00000002024101 - // @formatter:on - .section("date") // - .match("^Rechnungsdatum / Invoice date: (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4})$") // - .assign((ctx, v) -> { - ctx.put("date", v.get("date")); - })); - + final DocumentType type = new DocumentType("Geb.hrenabrechnung", "Kontoauszug"); this.addDocumentTyp(type); Transaction pdfTransaction = new Transaction<>(); - Block firstRelevantLine = new Block("^(Gebührenabrechnung) (.*)$"); + Block firstRelevantLine = new Block("^Rechnungsdatum.*$"); type.addBlock(firstRelevantLine); firstRelevantLine.set(pdfTransaction); @@ -56,25 +49,36 @@ private void addNonImportableTransaction() }) // @formatter:off - // Gebührenabrechnung Oktober - // Invoice October - // Zeitraum vom 01.10.2024 – 31.10.2024 - // Period of 01.10.2024 – 31.10.2024 - // Position Berechungsbasis Gebühr Betrag - // Calculation Fee Amount - // Grundgebühr 57.60 € 0.7500% p.a. 0.04 € + // Rechnungsbetrag 0.04 € // @formatter:on .section("amount", "currency") // - .documentContext("date") // .match("^Rechnungsbetrag (?[\\.,\\d]+) (?\\p{Sc})$") // .assign((t, v) -> { - t.setDateTime(asDate(v.get("date"))); t.setCurrencyCode(asCurrencyCode(v.get("currency"))); - t.setAmount(asAmount(v.get("amount"), "en", "US")); - v.getTransactionContext().put(FAILURE, - Messages.MsgErrorTransactionAlternativeDocumentRequired); + t.setAmount(asAmount(v.get("amount"))); }) + // @formatter:off + // Rechnungsdatum / Invoice date: 31.10.2024 + // @formatter:on + .section("date") // + .match("^Rechnungsdatum / Invoice date: (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4})$") // + .assign((t, v) -> t.setDateTime(asDate(v.get("date")))) + + // @formatter:off + // Rechnungsnummer /Invoice no: 00000002024101 + // @formatter:on + .section("note").optional() // + .match("^Rechnungsnummer.*: (?.*)$") // + .assign((t, v) -> t.setNote("R.-Nr.: " + trim(v.get("note")))) + + // @formatter:off + // Zeitraum vom 01.10.2024 – 31.10.2024 + // @formatter:on + .section("note").optional() // + .match("^Zeitraum vom (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4} \\– [\\d]{2}\\.[\\d]{2}\\.[\\d]{4})$") // + .assign((t, v) -> t.setNote(concatenate(t.getNote(), trim(v.get("note")), " | "))) + .wrap((t, ctx) -> { TransactionItem item = new TransactionItem(t); @@ -84,4 +88,10 @@ private void addNonImportableTransaction() return item; }); } -} \ No newline at end of file + + @Override + protected long asAmount(String value) + { + return ExtractorUtils.convertToNumberLong(value, Values.Amount, "en", "US"); + } +}