From 3bf6d1ebbce8b46eb0c062675c6f67948598bb47 Mon Sep 17 00:00:00 2001 From: Nirus2000 Date: Mon, 29 Aug 2022 09:48:28 +0200 Subject: [PATCH] Modify DZ Bank PDF-Importer to support joint account Fixes #2953 Fixes security currency check in all testcase Overwrite the duplicate test file (Dividende05.txt is the same as Dividende06.txt) --- .../DZBankGruppePDFExtractorTest.java | 250 ++++++++++++++++++ .../pdf/dzbankgruppe/Dividende06.txt | 86 +++--- .../pdf/DZBankGruppePDFExtractor.java | 109 +++++++- 3 files changed, 408 insertions(+), 37 deletions(-) diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dzbankgruppe/DZBankGruppePDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dzbankgruppe/DZBankGruppePDFExtractorTest.java index a64aa0da95..6d0b2790b6 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dzbankgruppe/DZBankGruppePDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dzbankgruppe/DZBankGruppePDFExtractorTest.java @@ -15,9 +15,12 @@ import name.abuchen.portfolio.datatransfer.Extractor.Item; import name.abuchen.portfolio.datatransfer.Extractor.SecurityItem; import name.abuchen.portfolio.datatransfer.Extractor.TransactionItem; +import name.abuchen.portfolio.datatransfer.ImportAction.Status; import name.abuchen.portfolio.datatransfer.actions.AssertImportActions; +import name.abuchen.portfolio.datatransfer.actions.CheckCurrenciesAction; import name.abuchen.portfolio.datatransfer.pdf.DZBankGruppePDFExtractor; import name.abuchen.portfolio.datatransfer.pdf.PDFInputFile; +import name.abuchen.portfolio.model.Account; import name.abuchen.portfolio.model.AccountTransaction; import name.abuchen.portfolio.model.BuySellEntry; import name.abuchen.portfolio.model.Client; @@ -606,6 +609,7 @@ public void testWertpapierDividende01() assertThat(security.getIsin(), is("PLOPTTC00011")); assertThat(security.getWkn(), is("534356")); assertThat(security.getName(), is("CD PROJEKT S.A. INHABER-AKTIEN C ZY 1")); + assertThat(security.getCurrencyCode(), is("PLN")); // check dividends transaction AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) @@ -626,6 +630,56 @@ public void testWertpapierDividende01() is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.59 + 1.89 + 0.11)))); assertThat(transaction.getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + + Unit grossValueUnit = transaction.getUnit(Unit.Type.GROSS_VALUE).orElseThrow(IllegalArgumentException::new); + assertThat(grossValueUnit.getForex(), is(Money.of("PLN", Values.Amount.factorize(85.00)))); + } + + @Test + public void testWertpapierDividende01WithSecurityinEUR() + { + Security security = new Security("CD PROJEKT S.A. INHABER-AKTIEN C ZY 1", CurrencyUnit.EUR); + security.setIsin("PLOPTTC00011"); + security.setWkn("534356"); + + Client client = new Client(); + client.addSecurity(security); + + DZBankGruppePDFExtractor extractor = new DZBankGruppePDFExtractor(client); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende01.txt"), errors); + + assertThat(errors, empty()); + assertThat(results.size(), is(1)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check dividends transaction + AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) + .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); + + assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); + + assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2021-06-10T00:00"))); + assertThat(transaction.getShares(), is(Values.Share.factorize(17))); + assertThat(transaction.getSource(), is("Dividende01.txt")); + assertNull(transaction.getNote()); + + assertThat(transaction.getMonetaryAmount(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(13.28)))); + assertThat(transaction.getGrossValue(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(18.87)))); + assertThat(transaction.getUnitSum(Unit.Type.TAX), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.59 + 1.89 + 0.11)))); + assertThat(transaction.getUnitSum(Unit.Type.FEE), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process(transaction, account); + assertThat(s, is(Status.OK_STATUS)); } @Test @@ -647,6 +701,51 @@ public void testWertpapierDividende02() assertThat(security.getIsin(), is("CA0679011084")); assertThat(security.getWkn(), is("870450")); assertThat(security.getName(), is("BARRICK GOLD CORP. SHARES REGISTERED SHARES O.N.")); + assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); + + // check dividends transaction + AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) + .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); + + assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); + + assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2021-03-17T00:00"))); + assertThat(transaction.getShares(), is(Values.Share.factorize(205))); + assertThat(transaction.getSource(), is("Dividende02.txt")); + assertThat(transaction.getNote(), is("Quartalsdividende")); + + assertThat(transaction.getMonetaryAmount(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(9.92)))); + assertThat(transaction.getGrossValue(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.39)))); + assertThat(transaction.getUnitSum(Unit.Type.TAX), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(2.31 + 1.54 + 0.08 + (1.85 / 1.1989))))); + assertThat(transaction.getUnitSum(Unit.Type.FEE), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + + Unit grossValueUnit = transaction.getUnit(Unit.Type.GROSS_VALUE).orElseThrow(IllegalArgumentException::new); + assertThat(grossValueUnit.getForex(), is(Money.of(CurrencyUnit.USD, Values.Amount.factorize(18.45)))); + } + + @Test + public void testWertpapierDividende02WithSecurityinEUR() + { + Security security = new Security("BARRICK GOLD CORP. SHARES REGISTERED SHARES O.N.", CurrencyUnit.EUR); + security.setIsin("CA0679011084"); + security.setWkn("870450"); + + Client client = new Client(); + client.addSecurity(security); + + DZBankGruppePDFExtractor extractor = new DZBankGruppePDFExtractor(client); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende02.txt"), errors); + + assertThat(errors, empty()); + assertThat(results.size(), is(1)); + new AssertImportActions().check(results, CurrencyUnit.EUR); // check dividends transaction AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) @@ -667,6 +766,12 @@ public void testWertpapierDividende02() is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(2.31 + 1.54 + 0.08 + (1.85 / 1.1989))))); assertThat(transaction.getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process(transaction, account); + assertThat(s, is(Status.OK_STATUS)); } @Test @@ -688,6 +793,7 @@ public void testWertpapierDividende03() assertThat(security.getIsin(), is("DE0007236101")); assertThat(security.getWkn(), is("723610")); assertThat(security.getName(), is("SIEMENS AG NAMENS-AKTIEN O.N.")); + assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); // check dividends transaction AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) @@ -729,6 +835,51 @@ public void testWertpapierDividende04() assertThat(security.getIsin(), is("IE00BYYXBF44")); assertThat(security.getWkn(), is("A2AHZU")); assertThat(security.getName(), is("I.M.III-I.FTSE EM H.D.L.V.UETF REG. SHARES DIS O.N.")); + assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); + + // check dividends transaction + AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) + .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); + + assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); + + assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2021-03-24T00:00"))); + assertThat(transaction.getShares(), is(Values.Share.factorize(350))); + assertThat(transaction.getSource(), is("Dividende04.txt")); + assertNull(transaction.getNote()); + + assertThat(transaction.getMonetaryAmount(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(61.58)))); + assertThat(transaction.getGrossValue(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(61.58)))); + assertThat(transaction.getUnitSum(Unit.Type.TAX), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(transaction.getUnitSum(Unit.Type.FEE), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + + Unit grossValueUnit = transaction.getUnit(Unit.Type.GROSS_VALUE).orElseThrow(IllegalArgumentException::new); + assertThat(grossValueUnit.getForex(), is(Money.of(CurrencyUnit.USD, Values.Amount.factorize(73.43)))); + } + + @Test + public void testWertpapierDividende04WithSecurityinEUR() + { + Security security = new Security("I.M.III-I.FTSE EM H.D.L.V.UETF REG. SHARES DIS O.N.", CurrencyUnit.EUR); + security.setIsin("IE00BYYXBF44"); + security.setWkn("A2AHZU"); + + Client client = new Client(); + client.addSecurity(security); + + DZBankGruppePDFExtractor extractor = new DZBankGruppePDFExtractor(client); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende04.txt"), errors); + + assertThat(errors, empty()); + assertThat(results.size(), is(1)); + new AssertImportActions().check(results, CurrencyUnit.EUR); // check dividends transaction AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) @@ -749,6 +900,12 @@ public void testWertpapierDividende04() is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); assertThat(transaction.getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process(transaction, account); + assertThat(s, is(Status.OK_STATUS)); } @Test @@ -770,6 +927,7 @@ public void testWertpapierDividende05() assertThat(security.getIsin(), is("DE000A0Z2ZZ5")); assertThat(security.getWkn(), is("A0Z2ZZ")); assertThat(security.getName(), is("FREENET AG NAMENS-AKTIEN O.N.")); + assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); // check dividends transaction AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) @@ -792,6 +950,98 @@ public void testWertpapierDividende05() is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); } + @Test + public void testWertpapierDividende06() + { + DZBankGruppePDFExtractor extractor = new DZBankGruppePDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende06.txt"), errors); + + assertThat(errors, empty()); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check security + Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() + .orElseThrow(IllegalArgumentException::new).getSecurity(); + assertThat(security.getIsin(), is("IE00BK1PV551")); + assertThat(security.getWkn(), is("A1XEY2")); + assertThat(security.getName(), is("XTR.(IE) - MSCI WORLD REGISTERED SHARES 1D O.N.")); + assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); + + // check dividends transaction + AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) + .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); + + assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); + + assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2022-06-21T00:00"))); + assertThat(transaction.getShares(), is(Values.Share.factorize(102))); + assertThat(transaction.getSource(), is("Dividende06.txt")); + assertNull(transaction.getNote()); + + assertThat(transaction.getMonetaryAmount(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.60)))); + assertThat(transaction.getGrossValue(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(30.54)))); + assertThat(transaction.getUnitSum(Unit.Type.TAX), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(2.62 + 0.14 + 0.21 + 2.62 + 0.14 + 0.21)))); + assertThat(transaction.getUnitSum(Unit.Type.FEE), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + + Unit grossValueUnit = transaction.getUnit(Unit.Type.GROSS_VALUE).orElseThrow(IllegalArgumentException::new); + assertThat(grossValueUnit.getForex(), is(Money.of(CurrencyUnit.USD, Values.Amount.factorize(32.33)))); + } + + @Test + public void testWertpapierDividende06WithSecurityinEUR() + { + Security security = new Security("XTR.(IE) - MSCI WORLD REGISTERED SHARES 1D O.N.", CurrencyUnit.EUR); + security.setIsin("IE00BK1PV551"); + security.setWkn("A1XEY2"); + + Client client = new Client(); + client.addSecurity(security); + + DZBankGruppePDFExtractor extractor = new DZBankGruppePDFExtractor(client); + + List errors = new ArrayList<>(); + + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende06.txt"), errors); + + assertThat(errors, empty()); + assertThat(results.size(), is(1)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check dividends transaction + AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) + .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); + + assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); + + assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2022-06-21T00:00"))); + assertThat(transaction.getShares(), is(Values.Share.factorize(102))); + assertThat(transaction.getSource(), is("Dividende06.txt")); + assertNull(transaction.getNote()); + + assertThat(transaction.getMonetaryAmount(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.60)))); + assertThat(transaction.getGrossValue(), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(30.54)))); + assertThat(transaction.getUnitSum(Unit.Type.TAX), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(2.62 + 0.14 + 0.21 + 2.62 + 0.14 + 0.21)))); + assertThat(transaction.getUnitSum(Unit.Type.FEE), + is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process(transaction, account); + assertThat(s, is(Status.OK_STATUS)); + } + @Test public void testUmsatzuebersicht01() { diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dzbankgruppe/Dividende06.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dzbankgruppe/Dividende06.txt index e27467b8d8..849be469a2 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dzbankgruppe/Dividende06.txt +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/dzbankgruppe/Dividende06.txt @@ -1,36 +1,58 @@ -PDF Autor: 'User' -PDFBox Version: 1.8.16 +PDFBox Version: 1.8.16 ----------------------------------------- -VR-Bank Erding eG · Zollnerstraße 4 · 85435 Erding -Depotnummer 12345678 - - Kundennummer 123456789 -Vorname und Vorname Name - Abrechnungsnr. 67305449999 -Vorname und Vorname Name Datum 22.06.2021 -Gustav-Pauli-Platz 6 Ihr Berater Herr Vorname Name -04711 Bremen Telefon 0999 299-9999 -Telefax 08122 200-50 - -Ertragsgutschrift nach § 27 KStG +VR-Bank Musterort eG · Musterstr. 23 · 12345 Musterort Seite 1 +Depotnummer + 99999999 + Kundennummer 99999999 +Max und Maria Mustermann Max und + Maria Mustermann +Max und Maria Mustermann Abrechnungsnr. 99999999999 +Musterweg 42 Datum 20.06.2022 +12345 Musterort Ihr Berater Max Mustermann +Telefon 01234/567890 +Ausschüttung Investmentfonds Nominale Wertpapierbezeichnung ISIN (WKN) -Stück 250 FREENET AG DE000A0Z2ZZ5 (A0Z2ZZ) -NAMENS-AKTIEN O.N. -Zahlbarkeitstag 23.06.2021 Ertrag pro Stück 1,65 EUR -Bestandsstichtag 18.06.2021 -Ex-Tag 21.06.2021 -Geschäftsjahr 01.01.2020 - 31.12.2020 -Dividendengutschrift nach § 27 KStG 412,50+ EUR -Ausmachender Betrag 412,50+ EUR -Lagerstelle CBF w/7268 w/DZ Bank (600502 / 72680000) -Den Betrag buchen wir mit Wertstellung 23.06.2021 zu Gunsten des Kontos 1234567 (IBAN DE37 1234 9605 0007 1234 -30), BLZ 701 696 05 (BIC GENODEF1XYZ). -Keine Steuerbescheinigung. -Es handelt sich bei der Ausschüttung um Leistungen aus dem steuerlichen Einlagekonto der Kapitalgesellschaft (§27 Abs. -1-7 KStG). Dieser Ertrag unterliegt laut Gesetz zum Zeitpunkt des Zuflusses keinem Steuerabzug und ist -einkommensteuerfrei. Er mindert jedoch im Nachhinein den Kaufkurs der bezogenen Aktie, so dass bei deren Verkauf -möglicherweise ein entsprechend höherer Kursgewinn zu versteuern ist. -Dieses Dokument wurde maschinell erstellt und wird nicht unterschrieben. +Stück 102 XTR.(IE) - MSCI WORLD IE00BK1PV551 (A1XEY2) +REGISTERED SHARES 1D O.N. +Zahlbarkeitstag 17.06.2022 Ausschüttung pro St. 0,317000000 USD +Bestandsstichtag 07.06.2022 mit Teilfreistellung (Aktien- +Ex-Tag 08.06.2022 fonds) 0,221900000 USD +Geschäftsjahr 01.01.2022 - 31.12.2022 Herkunftsland Irland +Devisenkurs EUR / USD 1,0585 +Devisenkursdatum 20.06.2022 +Ausschüttung 32,33 USD 30,54+ EUR +davon steuerfreier Anteil wg. Teilfreistellung 9,70 USD +Kapitalertragsteuerpfl. Ertrag nach Teilfreistellung 22,63 USD +Umrechnung in EUR 21,38 EUR +Berechnungsgrundlage für die Kapitalertragsteuer 21,38 EUR +Anteilige Berechnungsgrundlage für Maria Mustermann (50,00 %) entspricht 10,69 EUR +Kapitalertragsteuer 24,51 % auf 10,69 EUR 2,62- EUR +Solidaritätszuschlag 5,5 % auf 2,62 EUR 0,14- EUR +Kirchensteuer 8 % auf 2,62 EUR 0,21- EUR +Anteilige Berechnungsgrundlage für Max Mustermann (50,00 %) entspricht 10,69 EUR +Kapitalertragsteuer 24,51 % auf 10,69 EUR 2,62- EUR +Solidaritätszuschlag 5,5 % auf 2,62 EUR 0,14- EUR +Kirchensteuer 8 % auf 2,62 EUR 0,21- EUR +Ausmachender Betrag 24,60+ EUR +Lagerstelle CBFI (999999 / 99999) +Den Betrag buchen wir mit Wertstellung 21.06.2022 zu Gunsten des Kontos 999999 (IBAN DE99 9999 9999 9999 9999 +99), BLZ 999 999 99 (BIC XYXYZYX9XYZ). Bitte ggf. Rückseite beachten. -6352.06230101.0000020ER01 +9999.99999999.99999999X99 +Seite 2 +Depotnummer 99999999 +Kundennummer 99999999 +Abrechnungsnr. 99999999999 +Datum 20.06.2022 +Keine Steuerbescheinigung. +Nachrichtlich die Übersicht Ihrer Verrechnungs- und Steuertopfsalden zum Zeitpunkt der Erstellung der Abrechnung. +Verrechnungstöpfe 2022 Berechnungsgrundlage +der gezahlten Steuern +Euro Aktien Sonstige Sparer- anrechenbare Aktien und Sonstige +Pauschbetrag Quellensteuer +Vorher 0,00 0,00 0,00 0,00 99,99 +Ertrag 0,00 0,00 0,00 0,00 21,38 +Nachher 0,00 0,00 0,00 0,00 121,37 +Dieses Dokument wurde maschinell erstellt und wird nicht unterschrieben. +9999.99999999.99999999X99 \ No newline at end of file diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DZBankGruppePDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DZBankGruppePDFExtractor.java index 6f558ac92b..fcfd41cc42 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DZBankGruppePDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/DZBankGruppePDFExtractor.java @@ -9,10 +9,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.function.BiConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; import name.abuchen.portfolio.datatransfer.pdf.PDFParser.Block; +import name.abuchen.portfolio.datatransfer.pdf.PDFParser.DocumentContext; import name.abuchen.portfolio.datatransfer.pdf.PDFParser.DocumentType; import name.abuchen.portfolio.datatransfer.pdf.PDFParser.Transaction; import name.abuchen.portfolio.model.AccountTransaction; @@ -26,6 +28,28 @@ @SuppressWarnings("nls") public class DZBankGruppePDFExtractor extends AbstractPDFExtractor { + private static final String isJointAccount = "isJointAccount"; //$NON-NLS-1$ + + BiConsumer jointAccount = (context, lines) -> { + Pattern pJointAccount = Pattern.compile("Anteilige Berechnungsgrundlage .* \\(50,00 %\\).*"); //$NON-NLS-1$ + Boolean bJointAccount = false; + + for (String line : lines) + { + Matcher m = pJointAccount.matcher(line); + if (m.matches()) + { + context.put(isJointAccount, Boolean.TRUE.toString()); + bJointAccount = true; + break; + } + } + + if (!bJointAccount) + context.put(isJointAccount, Boolean.FALSE.toString()); + + }; + public DZBankGruppePDFExtractor(Client client) { super(client); @@ -50,7 +74,7 @@ public String getLabel() private void addBuySellTransaction() { - DocumentType type = new DocumentType("Wertpapier Abrechnung (Kauf|Verkauf)"); + DocumentType type = new DocumentType("Wertpapier Abrechnung (Kauf|Verkauf)", jointAccount); this.addDocumentTyp(type); Transaction pdfTransaction = new Transaction<>(); @@ -136,7 +160,7 @@ private void addBuySellTransaction() private void addDividendeTransaction() { - DocumentType type = new DocumentType("(Dividendengutschrift|Aussch.ttung Investmentfonds|Ertragsgutschrift)"); + DocumentType type = new DocumentType("(Dividendengutschrift|Aussch.ttung Investmentfonds|Ertragsgutschrift)", jointAccount); this.addDocumentTyp(type); Block block = new Block("^(Dividendengutschrift|Aussch.ttung Investmentfonds|Ertragsgutschrift .*)$"); @@ -841,22 +865,97 @@ private > void addTaxesSectionsTransaction(T transactio .match("^Finanztransaktionssteuer (?[\\.,\\d]+)\\- (?[\\w]{3})$") .assign((t, v) -> processTaxEntries(t, v, type)) + // Kapitalertragsteuer (Account) // Kapitalertragsteuer 25 % auf 7,55 EUR 1,89- EUR // Kapitalertragsteuer 25,00% auf 143,95 EUR 35,99- EUR .section("tax", "currency").optional() .match("^Kapitalertragsteuer [\\.,\\d]+([\\s]+)?% .* (?[\\.,\\d]+)\\- (?[\\w]{3})$") - .assign((t, v) -> processTaxEntries(t, v, type)) + .assign((t, v) -> { + if (!Boolean.parseBoolean(type.getCurrentContext().get(isJointAccount))) + processTaxEntries(t, v, type); + }) + + // Kapitalerstragsteuer (Joint Account) + // Kapitalertragsteuer 24,51 % auf 10,69 EUR 2,62- EUR + // Kapitalertragsteuer 24,51 % auf 10,69 EUR 2,62- EUR + .section("tax1", "currency1", "tax2", "currency2").optional() + .match("^Kapitalertragsteuer [\\.,\\d]+([\\s]+)?% .* (?[\\.,\\d]+)\\- (?[\\w]{3})$") + .match("^Kapitalertragsteuer [\\.,\\d]+([\\s]+)?% .* (?[\\.,\\d]+)\\- (?[\\w]{3})$") + .assign((t, v) -> { + if (Boolean.parseBoolean(type.getCurrentContext().get(isJointAccount))) + { + // Account 1 + v.put("currency", v.get("currency1")); + v.put("tax", v.get("tax1")); + processTaxEntries(t, v, type); + + // Account 2 + v.put("currency", v.get("currency2")); + v.put("tax", v.get("tax2")); + processTaxEntries(t, v, type); + } + }) + // Solidaritätszuschlag (Account) // Solidaritätszuschlag 5,5 % auf 1,89 EUR 0,11- EUR // Solidaritätszuschlag 5,50% auf 35,99 EUR 1,98- EUR .section("tax", "currency").optional() .match("^Solidarit.tszuschlag [\\.,\\d]+([\\s]+)?% .* (?[\\.,\\d]+)\\- (?[\\w]{3})$") - .assign((t, v) -> processTaxEntries(t, v, type)) + .assign((t, v) -> { + if (!Boolean.parseBoolean(type.getCurrentContext().get(isJointAccount))) + processTaxEntries(t, v, type); + }) + + // Solitaritätszuschlag (Joint Account) + // Solidaritätszuschlag 5,5 % auf 2,62 EUR 0,14- EUR + // Solidaritätszuschlag 5,5 % auf 2,62 EUR 0,14- EUR + .section("tax1", "currency1", "tax2", "currency2").optional() + .match("^Solidarit.tszuschlag [\\.,\\d]+([\\s]+)?% .* (?[\\.,\\d]+)\\- (?[\\w]{3})$") + .match("^Solidarit.tszuschlag [\\.,\\d]+([\\s]+)?% .* (?[\\.,\\d]+)\\- (?[\\w]{3})$") + .assign((t, v) -> { + if (Boolean.parseBoolean(type.getCurrentContext().get(isJointAccount))) + { + // Account 1 + v.put("currency", v.get("currency1")); + v.put("tax", v.get("tax1")); + processTaxEntries(t, v, type); + + // Account 2 + v.put("currency", v.get("currency2")); + v.put("tax", v.get("tax2")); + processTaxEntries(t, v, type); + } + }) + // Kirchensteuer (Account) // Kirchensteuer 7 % auf 2,89 EUR 2,11- EUR .section("tax", "currency").optional() .match("^Kirchensteuer [\\.,\\d]+([\\s]+)?% .* (?[\\d.]+,\\d+)\\- (?[\\w]{3})$") - .assign((t, v) -> processTaxEntries(t, v, type)) + .assign((t, v) -> { + if (!Boolean.parseBoolean(type.getCurrentContext().get(isJointAccount))) + processTaxEntries(t, v, type); + }) + + // Kirchensteuer (Joint Account) + // Kirchensteuer 8 % auf 2,62 EUR 0,21- EUR + // Kirchensteuer 8 % auf 2,62 EUR 0,21- EUR + .section("tax1", "currency1", "tax2", "currency2").optional() + .match("^Kirchensteuer [\\.,\\d]+([\\s]+)?% .* (?[\\d.]+,\\d+)\\- (?[\\w]{3})$") + .match("^Kirchensteuer [\\.,\\d]+([\\s]+)?% .* (?[\\d.]+,\\d+)\\- (?[\\w]{3})$") + .assign((t, v) -> { + if (Boolean.parseBoolean(type.getCurrentContext().get(isJointAccount))) + { + // Account 1 + v.put("currency", v.get("currency1")); + v.put("tax", v.get("tax1")); + processTaxEntries(t, v, type); + + // Account 2 + v.put("currency", v.get("currency2")); + v.put("tax", v.get("tax2")); + processTaxEntries(t, v, type); + } + }) // Einbehaltene Quellensteuer 19 % auf 85,00 PLN 3,59- EUR .section("withHoldingTax", "currency").optional()