diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/Dividende07.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/Dividende07.txt new file mode 100644 index 0000000000..f0f102adf1 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/Dividende07.txt @@ -0,0 +1,42 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +TARGOBANK AG +Postfach 10 02 30 +47002 Duisburg +TARGOBANK AG - Postfach 10 02 30 - 47002 Duisburg www.targobank.de +HERR MAX MUSTERMANN +FRAU MAXI MUSTERMANN +STRASSE 7 +11111 STADT +Depotnummer 111111111111 +........................................................................................................................................................................................................ +Dividendengutschrift 19.12.2024 +Rechnungsnummer: CPS-2024-0223620171-0003969 +MAX MUSTERMANN & MAXI MUSTERMANN +Wir informieren Sie über die folgende Dividendenzahlung: +Wertpapier Northrop Grumman Corp. - Registered Shares DL 1 +WKN / ISIN 851915 / US6668071029 +Stück 4 +Dividende pro Stück 2,06 USD +Ex-Tag 02.12.2024 +Zahlbar 18.12.2024 +Ursprungsland Vereinigte Staaten von Amerika +Geschäftsjahr 2024 +Geschäftsnummer 35424CG007898O00 +Bruttoertrag 8,24 USD +Devisenkurs zur Handelswährung USD/EUR 1,043858 +Bruttoertrag in EUR 7,89 EUR +15 % Ausländische Quellensteuer (US) 1,18 EUR +Gutschrift auf Ihrem Konto mit Wertstellung zum 18. Dezember 2024 +Konto-Nr. 1111111111 6,71 EUR +Dieser Beleg wurde maschinell erstellt und wird nicht unterschrieben. Irrtum vorbehalten. +Seite 1 +TARGOBANK AG | Vorstand: Isabelle Chevelard (Vorsitzende); Christophe Jéhan (stellv. Vorsitzender); Berthold Rüsing; Maria Topaler; Marco Voosen +Vorsitzender des Aufsichtsrates: René Dangel | Sitz der Gesellschaft: Düsseldorf +Handelsregister Amtsgericht Düsseldorf HRB 83351 | USt-ID-Nr.: DE 811 285 485 +USt-ID-Nr. des umsatzsteuerlichen Organträgers: DE 811 623 326 +KH.20241220.020646.5002.0001.12042 X 0 R + +``` diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende01.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende01.txt similarity index 100% rename from name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende01.txt rename to name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende01.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende02.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende02.txt similarity index 100% rename from name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende02.txt rename to name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende02.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende03.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende03.txt similarity index 100% rename from name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende03.txt rename to name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende03.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende04.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende04.txt similarity index 100% rename from name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende04.txt rename to name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende04.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende05.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende05.txt similarity index 100% rename from name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende05.txt rename to name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende05.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende06.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende06.txt similarity index 100% rename from name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungDividende06.txt rename to name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende06.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende07.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende07.txt new file mode 100644 index 0000000000..687901ada8 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonDividende07.txt @@ -0,0 +1,51 @@ +``` +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.72.2 +----------------------------------------- +TARGOBANK AG +Postfach 10 02 30 +47002 Duisburg +TARGOBANK AG - Postfach 10 02 30 - 47002 Duisburg www.targobank.de +HERR MAX MUSTERMANN +FRAU MAXI MUSTERMANN +STRASSE 7 +11111 STADT +Depotnummer 111111111111 +........................................................................................................................................................................................................ +Dividendengutschrift (Steuerbeilage) 19.12.2024 +MAX MUSTERMANN & MAXI MUSTERMANN +Wertpapier Northrop Grumman Corp. - Registered Shares DL 1 +WKN / ISIN 851915 / US6668071029 +Stück 4 +Ex-Tag 02.12.2024 +Ursprungsland Vereinigte Staaten von Amerika +Kapitalertragsteuer Solidaritätszuschlag +25,00 % * 5,50 % +Transaktionsreferenz INDTBK35424CG007898O00 +Steuerliche Bemessungsgrundlagen - keine Steuerbescheinigung +Dividendenanteil auf ausländische Dividenden, Veräußerungsgewinne, Stillhalterprämien und 7,89 EUR +Termingeschäfte (§ 20 Abs. 2 EStG) +Anrechenbare ausländische Quellensteuer 1,18 EUR +Erträge/Verluste 7,89 EUR +Auf- oder Abbau von steuerlichen Verrechnungsmöglichkeiten +Verlustverrechnung aus Aktienhandel: 0,00 EUR +Verlustverrechnung aus sonstigen Geschäften: 0,00 EUR +Nutzung des Sparerpauschbetrages/Freistellungsauftrages 0,00 EUR +Anrechnung ausländischer Quellensteuer ** - 4,72 EUR +Bemessungsgrundlage 3,17 EUR +Kapitalertragsteuer (KESt): 0,79 EUR +Solidaritätszuschlag auf KESt: 0,04 EUR +Kirchensteuer auf KESt: 0,00 EUR +Gesamtsumme Steuern 0,83 EUR +Belastung Ihres Kontos 1111111111 mit Wertstellung zum 18. Dezember 2024. +* KESt grundsätzlich 25%. Bei Einbehalt von Kirchensteuer ändert sich der KESt-Satz entsprechend Ihres Kirchensteuersatzes. +** Quellensteuer multipliziert mit 4 als Ertragsäquivalent +Dieser Beleg wurde maschinell erstellt und wird nicht unterschrieben. Irrtum vorbehalten. +Seite 1 +TARGOBANK AG | Vorstand: Isabelle Chevelard (Vorsitzende); Christophe Jéhan (stellv. Vorsitzender); Berthold Rüsing; Maria Topaler; Marco Voosen +Vorsitzender des Aufsichtsrates: René Dangel | Sitz der Gesellschaft: Düsseldorf +Handelsregister Amtsgericht Düsseldorf HRB 83351 | USt-ID-Nr.: DE 811 285 485 +USt-ID-Nr. des umsatzsteuerlichen Organträgers: DE 811 623 326 +KH.20241220.083558.5001.0010.1452 X 0 R + +``` diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungVerkauf02.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonVerkauf02.txt similarity index 100% rename from name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuermitteilungVerkauf02.txt rename to name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonVerkauf02.txt diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonVerkauf03.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonVerkauf03.txt new file mode 100644 index 0000000000..bd8227cd7e --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/SteuerbehandlungVonVerkauf03.txt @@ -0,0 +1,41 @@ +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.61.3 +----------------------------------------- +TARGOBANK AG +Postfach 10 02 30 +47002 Duisburg +TARGOBANK AG - Postfach 10 02 30 - 47002 Duisburg www.targobank.de +HERR +JERKO SABALIC +TAIMERHOFSTR. 7 +81927 MUENCHEN +Depotnummer 101167153000 +........................................................................................................................................................................................................ +Effektenabrechnung (Steuerbeilage) 03.01.2023 +JERKO SABALIC +Transaktionstyp Verkauf +Stück 4.000 +Wertpapier UBS AG (London Branch) - FaktS O.End DJIA 34446,1281 +WKN / ISIN UH3GTU / DE000UH3GTU5 +Handelsplatz außerbörs. Echtzeithandel +Schlusstag / Handelszeit 03.01.2023 / 12:04:02 +Kurs 0,001 EUR +Verwahrart Girosammelverwahrung +Kapitalertragsteuer Solidaritätszuschlag +25,00 % * 5,50 % +Transaktionsreferenz TR TBK00323B007292O001 +Steuerliche Bemessungsgrundlagen - keine Steuerbescheinigung +Veräußerungsverlust - 1.311,10 EUR +Erträge/Verluste - 1.311,10 EUR +Auf- oder Abbau von steuerlichen Verrechnungsmöglichkeiten +Verlustverrechnung aus Aktienhandel: 0,00 EUR +Verlustverrechnung aus sonstigen Geschäften: 0,00 EUR +* KESt grundsätzlich 25%. Bei Einbehalt von Kirchensteuer ändert sich der KESt-Satz entsprechend Ihres Kirchensteuersatzes. +Dieses Produkt ist keine Bankeinlage. Es unterliegt nicht der Einlagensicherung. Die vergangene Performance lässt keine Rückschlüsse +auf die zukünftige Wertentwicklung zu. Der Wert der Anlage kann schwanken. Ein teilweiser oder ganzer Verlust ist möglich. Dieser Beleg +wurde maschinell erstellt und wird nicht unterschrieben. Irrtum vorbehalten. +TARGOBANK AG | Vorstand: Isabelle Chevelard (Vorsitzende); Christophe Jéhan (stellv. Vorsitzender); Berthold Rüsing; Maria Topaler +Vorsitzender des Aufsichtsrates: René Dangel | Sitz der Gesellschaft: Düsseldorf +Handelsregister Amtsgericht Düsseldorf HRB 83351 | USt-ID-Nr.: DE 811 285 485 +USt-ID-Nr. des umsatzsteuerlichen Organträgers: DE 811 623 326 +KH.20230104.083335.5001.0004.15979 X 0 R \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/TargobankPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/TargobankPDFExtractorTest.java index 4964fcbeb1..9f81d51a1c 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/TargobankPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/TargobankPDFExtractorTest.java @@ -1,21 +1,41 @@ package name.abuchen.portfolio.datatransfer.pdf.targobank; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.check; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.dividend; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasAmount; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasCurrencyCode; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasDate; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasFees; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasForexGrossValue; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasGrossValue; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasIsin; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasName; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasNote; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasShares; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasSource; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasTaxes; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasTicker; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasWkn; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.purchase; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.sale; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.security; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.taxes; +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 static org.junit.Assert.assertNull; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import org.junit.Test; import name.abuchen.portfolio.Messages; -import name.abuchen.portfolio.datatransfer.Extractor.BuySellEntryItem; 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; @@ -23,15 +43,9 @@ import name.abuchen.portfolio.datatransfer.pdf.TargobankPDFExtractor; import name.abuchen.portfolio.model.Account; import name.abuchen.portfolio.model.AccountTransaction; -import name.abuchen.portfolio.model.BuySellEntry; import name.abuchen.portfolio.model.Client; -import name.abuchen.portfolio.model.PortfolioTransaction; import name.abuchen.portfolio.model.Security; -import name.abuchen.portfolio.model.Transaction; -import name.abuchen.portfolio.model.Transaction.Unit; import name.abuchen.portfolio.money.CurrencyUnit; -import name.abuchen.portfolio.money.Money; -import name.abuchen.portfolio.money.Values; @SuppressWarnings("nls") public class TargobankPDFExtractorTest @@ -46,38 +60,25 @@ public void testWertpapierKauf01() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf01.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("DE0000ABC123")); - assertThat(security.getWkn(), is("ABC123")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("FanCy shaRe. nAmE X0-X0")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("DE0000ABC123"), hasWkn("ABC123"), hasTicker(null), // + hasName("FanCy shaRe. nAmE X0-X0"), // + hasCurrencyCode("EUR")))); // check buy sell transaction - BuySellEntry entry = (BuySellEntry) results.stream().filter(BuySellEntryItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.BUY)); - assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY)); - - assertThat(entry.getPortfolioTransaction().getDateTime(), is(LocalDateTime.parse("2020-01-02T13:01:00"))); - assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(987.654))); - assertThat(entry.getSource(), is("Kauf01.txt")); - assertNull(entry.getNote()); - - assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1008.91)))); - assertThat(entry.getPortfolioTransaction().getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1000.01)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(8.90)))); + assertThat(results, hasItem(purchase( // + hasDate("2020-01-02T13:01:00"), hasShares(987.654), // + hasSource("Kauf01.txt"), // + hasNote("R.-Nr.: BOE-2020-0223620085-0000068 | Ref.-Nr.: 555666777888"), // + hasAmount("EUR", 1008.91), hasGrossValue("EUR", 1000.01), // + hasTaxes("EUR", 0.00), hasFees("EUR", 8.90)))); } @Test @@ -90,38 +91,25 @@ public void testWertpapierKauf02() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf02.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("DE0000ABC123")); - assertThat(security.getWkn(), is("ABC123")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Muster AG")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("DE0000ABC123"), hasWkn("ABC123"), hasTicker(null), // + hasName("Muster AG"), // + hasCurrencyCode("EUR")))); // check buy sell transaction - BuySellEntry entry = (BuySellEntry) results.stream().filter(BuySellEntryItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.BUY)); - assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY)); - - assertThat(entry.getPortfolioTransaction().getDateTime(), is(LocalDateTime.parse("2020-09-21T19:27:00"))); - assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(1710))); - assertThat(entry.getSource(), is("Kauf02.txt")); - assertNull(entry.getNote()); - - assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1187.94)))); - assertThat(entry.getPortfolioTransaction().getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1187.94)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(purchase( // + hasDate("2020-09-21T19:27:00"), hasShares(1710.00), // + hasSource("Kauf02.txt"), // + hasNote("R.-Nr.: NUMMER | Ref.-Nr.: NUMMER"), // + hasAmount("EUR", 1187.94), hasGrossValue("EUR", 1187.94), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test @@ -134,38 +122,25 @@ public void testWertpapierVerkauf01() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Verkauf01.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("LU0000ZYX987")); - assertThat(security.getWkn(), is("ZYX987")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("an0tHer vERy FNcY NaMe")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("LU0000ZYX987"), hasWkn("ZYX987"), hasTicker(null), // + hasName("an0tHer vERy FNcY NaMe"), // + hasCurrencyCode("EUR")))); // check buy sell transaction - BuySellEntry entry = (BuySellEntry) results.stream().filter(BuySellEntryItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.SELL)); - assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.SELL)); - - assertThat(entry.getPortfolioTransaction().getDateTime(), is(LocalDateTime.parse("2020-01-10T00:00"))); - assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(10))); - assertThat(entry.getSource(), is("Verkauf01.txt")); - assertNull(entry.getNote()); - - assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1239.00)))); - assertThat(entry.getPortfolioTransaction().getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1239.00)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(sale( // + hasDate("2020-01-10T00:00"), hasShares(10.00), // + hasSource("Verkauf01.txt"), // + hasNote("R.-Nr.: BGH-2020-0223620085-0000068 | Ref.-Nr.: 0291235DH0293422"), // + hasAmount("EUR", 1239.00), hasGrossValue("EUR", 1239.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test @@ -178,401 +153,293 @@ public void testWertpapierVerkauf02() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Verkauf02.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("SE0006425815")); - assertThat(security.getWkn(), is("A14TK6")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("PowerCell Sweden AB (publ) - Namn-Aktier SK-,022")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("SE0006425815"), hasWkn("A14TK6"), hasTicker(null), // + hasName("PowerCell Sweden AB (publ) - Namn-Aktier SK-,022"), // + hasCurrencyCode("EUR")))); // check buy sell transaction - BuySellEntry entry = (BuySellEntry) results.stream().filter(BuySellEntryItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.SELL)); - assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.SELL)); - - assertThat(entry.getPortfolioTransaction().getDateTime(), is(LocalDateTime.parse("2020-05-26T20:32:00"))); - assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(300))); - assertThat(entry.getSource(), is("Verkauf02.txt")); - assertNull(entry.getNote()); - - assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(7439.35)))); - assertThat(entry.getPortfolioTransaction().getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(7458.00)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(18.65)))); + assertThat(results, hasItem(sale( // + hasDate("2020-05-26T20:32:00"), hasShares(300.00), // + hasSource("Verkauf02.txt"), // + hasNote("R.-Nr.: BOE-2020-0223620168-0003824 | Ref.-Nr.: 2005262032215246"), // + hasAmount("EUR", 7439.35), hasGrossValue("EUR", 7458.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 18.65)))); } @Test - public void testWertpapierVerkaufWithTaxTreatmentWertpapierVerkauf02() + public void testSteuerbehandlungVonVerkauf02() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Verkauf02.txt", "SteuermitteilungVerkauf02.txt"), errors); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonVerkauf02.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("SE0006425815")); - assertThat(security.getWkn(), is("A14TK6")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("PowerCell Sweden AB (publ) - Namn-Aktier SK-,022")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); - - // check buy sell transaction - BuySellEntry entry = (BuySellEntry) results.stream().filter(BuySellEntryItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.SELL)); - assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.SELL)); - - assertThat(entry.getPortfolioTransaction().getDateTime(), is(LocalDateTime.parse("2020-05-26T20:32:00"))); - assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(300))); - assertThat(entry.getSource(), is("Verkauf02.txt; SteuermitteilungVerkauf02.txt")); - assertNull(entry.getNote()); - - assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(6615.59)))); - assertThat(entry.getPortfolioTransaction().getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(7458.00)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(780.82 + 42.94)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(18.65)))); + assertThat(results, hasItem(security( // + hasIsin("SE0006425815"), hasWkn("A14TK6"), hasTicker(null), // + hasName("PowerCell Sweden AB (publ) - Namn-Aktier SK-,022"), // + hasCurrencyCode("EUR")))); + + // check taxes transaction + assertThat(results, hasItem(taxes( // + hasDate("2020-05-26T20:32:00"), hasShares(300.00), // + hasSource("SteuerbehandlungVonVerkauf02.txt"), // + hasNote("Tr.-Nr.: TBK14720B024746O001"), // + hasAmount("EUR", 823.76), hasGrossValue("EUR", 823.76), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test - public void testWertpapierVerkaufWithTaxTreatmentReversedWertpapierVerkauf02() + public void testVerkauf02MitSteuerbehandlungVonVerkauf02() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungVerkauf02.txt", "Verkauf02.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Verkauf02.txt", "SteuerbehandlungVonVerkauf02.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("SE0006425815")); - assertThat(security.getWkn(), is("A14TK6")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("PowerCell Sweden AB (publ) - Namn-Aktier SK-,022")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("SE0006425815"), hasWkn("A14TK6"), hasTicker(null), // + hasName("PowerCell Sweden AB (publ) - Namn-Aktier SK-,022"), // + hasCurrencyCode("EUR")))); // check buy sell transaction - BuySellEntry entry = (BuySellEntry) results.stream().filter(BuySellEntryItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.SELL)); - assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.SELL)); - - assertThat(entry.getPortfolioTransaction().getDateTime(), is(LocalDateTime.parse("2020-05-26T20:32:00"))); - assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(300))); - assertThat(entry.getSource(), is("Verkauf02.txt; SteuermitteilungVerkauf02.txt")); - assertNull(entry.getNote()); - - assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(6615.59)))); - assertThat(entry.getPortfolioTransaction().getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(7458.00)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(780.82 + 42.94)))); - assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(18.65)))); + assertThat(results, hasItem(sale( // + hasDate("2020-05-26T20:32:00"), hasShares(300.00), // + hasSource("Verkauf02.txt; SteuerbehandlungVonVerkauf02.txt"), // + hasNote("R.-Nr.: BOE-2020-0223620168-0003824 | Ref.-Nr.: 2005262032215246 | Tr.-Nr.: TBK14720B024746O001"), // + hasAmount("EUR", 6615.59), hasGrossValue("EUR", 7458.00), // + hasTaxes("EUR", 823.76), hasFees("EUR", 18.65)))); } @Test - public void testTaxTreatmentWertpapierVerkauf02() + public void testVerkauf02MitSteuerbehandlungVonVerkauf02_SourceFilesReversed() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungVerkauf02.txt"), + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonVerkauf02.txt", "Verkauf02.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("SE0006425815")); - assertThat(security.getWkn(), is("A14TK6")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("PowerCell Sweden AB (publ) - Namn-Aktier SK-,022")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); - - // check tax transaction - AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) - .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(transaction.getType(), is(AccountTransaction.Type.TAXES)); - - assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-05-26T20:32:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(300))); - assertThat(transaction.getSource(), is("SteuermitteilungVerkauf02.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(780.82 + 42.94)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(780.82 + 42.94)))); - 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)))); + assertThat(results, hasItem(security( // + hasIsin("SE0006425815"), hasWkn("A14TK6"), hasTicker(null), // + hasName("PowerCell Sweden AB (publ) - Namn-Aktier SK-,022"), // + hasCurrencyCode("EUR")))); + + // check buy sell transaction + assertThat(results, hasItem(sale( // + hasDate("2020-05-26T20:32:00"), hasShares(300.00), // + hasSource("Verkauf02.txt; SteuerbehandlungVonVerkauf02.txt"), // + hasNote("R.-Nr.: BOE-2020-0223620168-0003824 | Ref.-Nr.: 2005262032215246 | Tr.-Nr.: TBK14720B024746O001"), // + hasAmount("EUR", 6615.59), hasGrossValue("EUR", 7458.00), // + hasTaxes("EUR", 823.76), hasFees("EUR", 18.65)))); } @Test - public void testDividende01() + public void testWertpapierVerkauf03() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende01.txt"), errors); + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Verkauf03.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("IE00BKX55T58")); - assertThat(security.getWkn(), is("A12CX1")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); + assertThat(results, hasItem(security( // + hasIsin("DE000UH3GTU5"), hasWkn("UH3GTU"), hasTicker(null), // + hasName("UBS AG (London Branch) - FaktS O.End DJIA 34446,1281"), // + hasCurrencyCode("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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("Dividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - 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(23.77)))); + // check buy sell transaction + assertThat(results, hasItem(sale( // + hasDate("2023-01-03T12:04:02"), hasShares(4000.00), // + hasSource("Verkauf03.txt"), // + hasNote("R.-Nr.: BOE-2023-0223620153-0000031 | Ref.-Nr.: 9301031204028497"), // + hasAmount("EUR", 0.01), hasGrossValue("EUR", 4.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 3.99)))); } @Test - public void testDividende01WithSecurityInEUR() + public void testSteuerbehandlungVonVerkauf03() { - Security security = new Security("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN", CurrencyUnit.EUR); - security.setIsin("IE00BKX55T58"); - security.setWkn("A12CX1"); - - Client client = new Client(); - client.addSecurity(security); - - TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende01.txt"), errors); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonVerkauf03.txt"), errors); assertThat(errors, empty()); - assertThat(results.size(), is(1)); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); 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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("Dividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - 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)))); - - CheckCurrenciesAction c = new CheckCurrenciesAction(); - Account account = new Account(); - account.setCurrencyCode(CurrencyUnit.EUR); - Status s = c.process(transaction, account); - assertThat(s, is(Status.OK_STATUS)); + // check security + assertThat(results, hasItem(security( // + hasIsin("DE000UH3GTU5"), hasWkn("UH3GTU"), hasTicker(null), // + hasName("UBS AG (London Branch) - FaktS O.End DJIA 34446,1281"), // + hasCurrencyCode("EUR")))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2023-01-03T12:04:02"), hasShares(4000.00), // + hasSource("SteuerbehandlungVonVerkauf03.txt"), // + hasNote("Tr.-Nr.: TBK00323B007292O001"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test - public void testTaxTreatmentForDividende01() + public void testVerkauf03MitSteuerbehandlungVonVerkauf03() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende01.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Verkauf03.txt", "SteuerbehandlungVonVerkauf03.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("IE00BKX55T58")); - assertThat(security.getWkn(), is("A12CX1")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); - - // check tax transaction - AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) - .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(transaction.getType(), is(AccountTransaction.Type.TAXES)); - - assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("SteuermitteilungDividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(5.30 + 0.29)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(5.30 + 0.29)))); - 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)))); + assertThat(results, hasItem(security( // + hasIsin("DE000UH3GTU5"), hasWkn("UH3GTU"), hasTicker(null), // + hasName("UBS AG (London Branch) - FaktS O.End DJIA 34446,1281"), // + hasCurrencyCode("EUR")))); + + // check buy sell transaction + assertThat(results, hasItem(sale( // + hasDate("2023-01-03T12:04:02"), hasShares(4000.00), // + hasSource("Verkauf03.txt; SteuerbehandlungVonVerkauf03.txt"), // + hasNote("R.-Nr.: BOE-2023-0223620153-0000031 | Ref.-Nr.: 9301031204028497 | Tr.-Nr.: TBK00323B007292O001"), // + hasAmount("EUR", 0.01), hasGrossValue("EUR", 4.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 3.99)))); } @Test - public void testDividendeWithTaxTreatmentForDividende01() + public void testVerkauf03MitSteuerbehandlungVonVerkauf03_SourceFilesReversed() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende01.txt", "SteuermitteilungDividende01.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonVerkauf03.txt", "Verkauf03.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 - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("IE00BKX55T58")); - assertThat(security.getWkn(), is("A12CX1")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); + assertThat(results, hasItem(security( // + hasIsin("DE000UH3GTU5"), hasWkn("UH3GTU"), hasTicker(null), // + hasName("UBS AG (London Branch) - FaktS O.End DJIA 34446,1281"), // + hasCurrencyCode("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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("Dividende01.txt; SteuermitteilungDividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.59)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(5.30 + 0.29)))); - 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(23.77)))); + // check buy sell transaction + assertThat(results, hasItem(sale( // + hasDate("2023-01-03T12:04:02"), hasShares(4000.00), // + hasSource("Verkauf03.txt; SteuerbehandlungVonVerkauf03.txt"), // + hasNote("R.-Nr.: BOE-2023-0223620153-0000031 | Ref.-Nr.: 9301031204028497 | Tr.-Nr.: TBK00323B007292O001"), // + hasAmount("EUR", 0.01), hasGrossValue("EUR", 4.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 3.99)))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende01() + public void testDividende01() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende01.txt", "Dividende01.txt"), errors); + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende01.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("IE00BKX55T58")); - assertThat(security.getWkn(), is("A12CX1")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("IE00BKX55T58"), hasWkn("A12CX1"), hasTicker(null), // + hasName("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN"), // + hasCurrencyCode("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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("Dividende01.txt; SteuermitteilungDividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.59)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(5.30 + 0.29)))); - assertThat(transaction.getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(81.00), // + hasSource("Dividende01.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234"), // + hasAmount("EUR", 21.18), hasGrossValue("EUR", 21.18), // + hasForexGrossValue("USD", 23.77), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentForDividende01WithSecurityInEUR() + public void testDividende01WithSecurityInEUR() { - Security security = new Security("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN", CurrencyUnit.EUR); + Security security = new Security("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN", + CurrencyUnit.EUR); security.setIsin("IE00BKX55T58"); security.setWkn("A12CX1"); @@ -583,90 +450,102 @@ public void testDividendeWithTaxTreatmentForDividende01WithSecurityInEUR() List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende01.txt", "SteuermitteilungDividende01.txt"), errors); + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende01.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); // 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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("Dividende01.txt; SteuermitteilungDividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.59)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(5.30 + 0.29)))); - 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)); + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(81.00), // + hasSource("Dividende01.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234"), // + hasAmount("EUR", 21.18), hasGrossValue("EUR", 21.18), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende01WithSecurityInEUR() + public void testSteuerbehandlungVonDividende01() { - Security security = new Security("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN", CurrencyUnit.EUR); - security.setIsin("IE00BKX55T58"); - security.setWkn("A12CX1"); + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); - Client client = new Client(); - client.addSecurity(security); + List errors = new ArrayList<>(); - TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende01.txt"), errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check security + assertThat(results, hasItem(security( // + hasIsin("IE00BKX55T58"), hasWkn("A12CX1"), hasTicker(null), // + hasName("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN"), // + hasCurrencyCode("EUR")))); + + // check taxes transaction + assertThat(results, hasItem(taxes( // + hasDate("2020-06-24T00:00"), hasShares(81.00), // + hasSource("SteuerbehandlungVonDividende01.txt"), // + hasNote("Tr.-Nr.: INDTBK1234567890"), // + hasAmount("EUR", 5.59), hasGrossValue("EUR", 5.59), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + } + + @Test + public void testDividende01MitSteuerbehandlungVonDividende01() + { + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende01.txt", "Dividende01.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende01.txt", "SteuerbehandlungVonDividende01.txt"), + errors); assertThat(errors, empty()); - assertThat(results.size(), is(1)); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); new AssertImportActions().check(results, CurrencyUnit.EUR); + // check security + assertThat(results, hasItem(security( // + hasIsin("IE00BKX55T58"), hasWkn("A12CX1"), hasTicker(null), // + hasName("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN"), // + hasCurrencyCode("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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("Dividende01.txt; SteuermitteilungDividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.59)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(5.30 + 0.29)))); - 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)); + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(81.00), // + hasSource("Dividende01.txt; SteuerbehandlungVonDividende01.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234 | Tr.-Nr.: INDTBK1234567890"), // + hasAmount("EUR", 15.59), hasGrossValue("EUR", 21.18), // + hasForexGrossValue("USD", 23.77), // + hasTaxes("EUR", 5.59), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentForDividende01WithSecurityInUSD() + public void testDividende01MitSteuerbehandlungVonDividende01WithSecurityInEUR() { - Security security = new Security("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN", CurrencyUnit.USD); + Security security = new Security("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN", + CurrencyUnit.EUR); security.setIsin("IE00BKX55T58"); security.setWkn("A12CX1"); @@ -677,46 +556,71 @@ public void testDividendeWithTaxTreatmentForDividende01WithSecurityInUSD() List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende01.txt", "SteuermitteilungDividende01.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende01.txt", "Dividende01.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); // 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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("Dividende01.txt; SteuermitteilungDividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.59)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(5.30 + 0.29)))); - 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(23.77)))); - - CheckCurrenciesAction c = new CheckCurrenciesAction(); - Account account = new Account(); - account.setCurrencyCode(CurrencyUnit.EUR); - Status s = c.process(transaction, account); - assertThat(s, is(Status.OK_STATUS)); + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(81.00), // + hasSource("Dividende01.txt; SteuerbehandlungVonDividende01.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234 | Tr.-Nr.: INDTBK1234567890"), // + hasAmount("EUR", 15.59), hasGrossValue("EUR", 21.18), // + hasTaxes("EUR", 5.59), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); + } + + @Test + public void testDividende01MitSteuerbehandlungVonDividende01_SourceFilesReversed() + { + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende01.txt", "Dividende01.txt"), + errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check security + assertThat(results, hasItem(security( // + hasIsin("IE00BKX55T58"), hasWkn("A12CX1"), hasTicker(null), // + hasName("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN"), // + hasCurrencyCode("EUR")))); + + // check dividends transaction + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(81.00), // + hasSource("Dividende01.txt; SteuerbehandlungVonDividende01.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234 | Tr.-Nr.: INDTBK1234567890"), // + hasAmount("EUR", 15.59), hasGrossValue("EUR", 21.18), // + hasTaxes("EUR", 5.59), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende01WithSecurityInUSD() + public void testDividende01MitSteuerbehandlungVonDividende01WithSecurityInEUR_SourceFilesReversed() { - Security security = new Security("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN", CurrencyUnit.USD); + Security security = new Security("Vang.FTSE Develop.World U.ETF - Registered Shares USD Dis.oN", + CurrencyUnit.EUR); security.setIsin("IE00BKX55T58"); security.setWkn("A12CX1"); @@ -727,40 +631,31 @@ public void testDividendeWithTaxTreatmentReversedForDividende01WithSecurityInUSD List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende01.txt", "Dividende01.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende01.txt", "SteuerbehandlungVonDividende01.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); // 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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(81))); - assertThat(transaction.getSource(), is("Dividende01.txt; SteuermitteilungDividende01.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.59)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(21.18)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(5.30 + 0.29)))); - 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(23.77)))); - - CheckCurrenciesAction c = new CheckCurrenciesAction(); - Account account = new Account(); - account.setCurrencyCode(CurrencyUnit.EUR); - Status s = c.process(transaction, account); - assertThat(s, is(Status.OK_STATUS)); + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(81.00), // + hasSource("Dividende01.txt; SteuerbehandlungVonDividende01.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234 | Tr.-Nr.: INDTBK1234567890"), // + hasAmount("EUR", 15.59), hasGrossValue("EUR", 21.18), // + hasTaxes("EUR", 5.59), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } @Test @@ -773,201 +668,145 @@ public void testDividende02() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende02.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("IE00BKX55S42")); - assertThat(security.getWkn(), is("A12CXZ")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Vang.FTSE Dev.Eur.ex UK U.ETF - Registered Shares EUR Dis. o")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("IE00BKX55S42"), hasWkn("A12CXZ"), hasTicker(null), // + hasName("Vang.FTSE Dev.Eur.ex UK U.ETF - Registered Shares EUR Dis. o"), // + hasCurrencyCode("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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(61))); - assertThat(transaction.getSource(), is("Dividende02.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.29)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.29)))); - 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)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(61.00), // + hasSource("Dividende02.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234"), // + hasAmount("EUR", 15.29), hasGrossValue("EUR", 15.29), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test - public void testTaxTreatmentForDividende02() + public void testSteuerbehandlungVonDividende02() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende02.txt"), errors); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende02.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("IE00BKX55S42")); - assertThat(security.getWkn(), is("A12CXZ")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Vang.FTSE Dev.Eur.ex UK U.ETF - Registered Shares EUR Dis. o")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); - - // check cancellation (Storno) (0,00) transaction - TransactionItem cancellation = (TransactionItem) results.stream() // - .filter(i -> i.isFailure()) // - .filter(TransactionItem.class::isInstance) // - .findFirst().orElseThrow(IllegalArgumentException::new); - - assertThat(((AccountTransaction) cancellation.getSubject()).getType(), is(AccountTransaction.Type.TAXES)); - assertThat(cancellation.getFailureMessage(), is(Messages.MsgErrorTransactionTypeNotSupported)); - - assertThat(((Transaction) cancellation.getSubject()).getDateTime(), is(LocalDateTime.parse("2020-06-11T00:00"))); - assertThat(((Transaction) cancellation.getSubject()).getShares(), is(Values.Share.factorize(61))); - assertThat(((Transaction) cancellation.getSubject()).getSource(), is("SteuermitteilungDividende02.txt")); - assertNull(((Transaction) cancellation.getSubject()).getNote()); - - assertThat(((Transaction) cancellation.getSubject()).getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(((Transaction) cancellation.getSubject()).getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(((Transaction) cancellation.getSubject()).getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(((Transaction) cancellation.getSubject()).getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(security( // + hasIsin("IE00BKX55S42"), hasWkn("A12CXZ"), hasTicker(null), // + hasName("Vang.FTSE Dev.Eur.ex UK U.ETF - Registered Shares EUR Dis. o"), // + hasCurrencyCode("EUR")))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-06-11T00:00"), hasShares(61.00), // + hasSource("SteuerbehandlungVonDividende02.txt"), // + hasNote("Tr.-Nr.: INDTBK1234567890"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test - public void testDividendeWithTaxTreatmentForDividende02() + public void testDividende02MitSteuerbehandlungVonDividende02() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende02.txt", "SteuermitteilungDividende02.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende02.txt", "SteuerbehandlungVonDividende02.txt"), + errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(2L)); assertThat(results.size(), is(3)); 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("IE00BKX55S42")); - assertThat(security.getWkn(), is("A12CXZ")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Vang.FTSE Dev.Eur.ex UK U.ETF - Registered Shares EUR Dis. o")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("IE00BKX55S42"), hasWkn("A12CXZ"), hasTicker(null), // + hasName("Vang.FTSE Dev.Eur.ex UK U.ETF - Registered Shares EUR Dis. o"), // + hasCurrencyCode("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("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(61))); - assertThat(transaction.getSource(), is("Dividende02.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.29)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.29)))); - 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)))); - - // check cancellation (Storno) (0,00) transaction - TransactionItem cancellation = (TransactionItem) results.stream() // - .filter(i -> i.isFailure()) // - .filter(TransactionItem.class::isInstance) // - .findFirst().orElseThrow(IllegalArgumentException::new); - - assertThat(((AccountTransaction) cancellation.getSubject()).getType(), is(AccountTransaction.Type.TAXES)); - assertThat(cancellation.getFailureMessage(), is(Messages.MsgErrorTransactionTypeNotSupported)); - - assertThat(((Transaction) cancellation.getSubject()).getDateTime(), is(LocalDateTime.parse("2020-06-11T00:00"))); - assertThat(((Transaction) cancellation.getSubject()).getShares(), is(Values.Share.factorize(61))); - assertThat(((Transaction) cancellation.getSubject()).getSource(), is("SteuermitteilungDividende02.txt")); - assertNull(((Transaction) cancellation.getSubject()).getNote()); - - assertThat(((Transaction) cancellation.getSubject()).getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(((Transaction) cancellation.getSubject()).getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(((Transaction) cancellation.getSubject()).getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); - assertThat(((Transaction) cancellation.getSubject()).getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(61.00), // + hasSource("Dividende02.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234"), // + hasAmount("EUR", 15.29), hasGrossValue("EUR", 15.29), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-06-11T00:00"), hasShares(61.00), // + hasSource("SteuerbehandlungVonDividende02.txt"), // + hasNote("Tr.-Nr.: INDTBK1234567890"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende02() + public void testDividende02MitSteuerbehandlungVonDividende02_SourceFilesReversed() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende02.txt", "Dividende02.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende02.txt", "Dividende02.txt"), + errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(2L)); assertThat(results.size(), is(3)); 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("IE00BKX55S42")); - assertThat(security.getWkn(), is("A12CXZ")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Vang.FTSE Dev.Eur.ex UK U.ETF - Registered Shares EUR Dis. o")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("IE00BKX55S42"), hasWkn("A12CXZ"), hasTicker(null), // + hasName("Vang.FTSE Dev.Eur.ex UK U.ETF - Registered Shares EUR Dis. o"), // + hasCurrencyCode("EUR")))); // check dividends transaction - AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) - .skip(1).findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); - - assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-06-24T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(61))); - assertThat(transaction.getSource(), is("Dividende02.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.29)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(15.29)))); - 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)))); - - // check transaction - TransactionItem cancellation = (TransactionItem) results.stream() // - .filter(i -> i.isFailure()) // - .filter(TransactionItem.class::isInstance) // - .findFirst().orElseThrow(IllegalArgumentException::new); - - assertThat(cancellation.getFailureMessage(), is(Messages.MsgErrorTransactionTypeNotSupported)); - assertThat(cancellation.getSource(), is("SteuermitteilungDividende02.txt")); + assertThat(results, hasItem(dividend( // + hasDate("2020-06-24T00:00"), hasShares(61.00), // + hasSource("Dividende02.txt"), // + hasNote("R.-Nr.: CPS-2020-0123456789-0001234"), // + hasAmount("EUR", 15.29), hasGrossValue("EUR", 15.29), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-06-11T00:00"), hasShares(61.00), // + hasSource("SteuerbehandlungVonDividende02.txt"), // + hasNote("Tr.-Nr.: INDTBK1234567890"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test @@ -980,40 +819,26 @@ public void testDividende03() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende03.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("LU0875160326")); - assertThat(security.getWkn(), is("DBX0NK")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N.")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); + assertThat(results, hasItem(security( // + hasIsin("LU0875160326"), hasWkn("DBX0NK"), hasTicker(null), // + hasName("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N."), // + hasCurrencyCode("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("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("Dividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - 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(304.81)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-04-27T00:00"), hasShares(1700.00), // + hasSource("Dividende03.txt"), // + hasNote("R.-Nr.: CPS-2020-0223620168-0001148"), // + hasAmount("EUR", 279.64), hasGrossValue("EUR", 279.64), // + hasForexGrossValue("USD", 304.81), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test @@ -1033,170 +858,96 @@ public void testDividende03WithSecurityInEUR() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende03.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); // 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("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("Dividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - 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)))); - - 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 testTaxTreatmentForDividende03() - { - TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); - - List errors = new ArrayList<>(); - - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende03.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("LU0875160326")); - assertThat(security.getWkn(), is("DBX0NK")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N.")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); - - // check tax transaction - AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) - .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(transaction.getType(), is(AccountTransaction.Type.TAXES)); - - assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("SteuermitteilungDividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(48.94 + 2.69)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(48.94 + 2.69)))); - 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)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-04-27T00:00"), hasShares(1700.00), // + hasSource("Dividende03.txt"), // + hasNote("R.-Nr.: CPS-2020-0223620168-0001148"), // + hasAmount("EUR", 279.64), hasGrossValue("EUR", 279.64), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } @Test - public void testDividendeWithTaxTreatmentForDividende03() + public void testSteuerbehandlungVonDividende03() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende03.txt", "SteuermitteilungDividende03.txt"), errors); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende03.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("LU0875160326")); - assertThat(security.getWkn(), is("DBX0NK")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Xtrackers Harvest CSI300 - Inhaber-Anteile 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("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("Dividende03.txt; SteuermitteilungDividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(228.01)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(48.94 + 2.69)))); - 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(304.81)))); + assertThat(results, hasItem(security( // + hasIsin("LU0875160326"), hasWkn("DBX0NK"), hasTicker(null), // + hasName("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N."), // + hasCurrencyCode("EUR")))); + + // check taxes transaction + assertThat(results, hasItem(taxes( // + hasDate("2020-04-27T00:00"), hasShares(1700.00), // + hasSource("SteuerbehandlungVonDividende03.txt"), // + hasNote("Tr.-Nr.: INDTBK12120CG000130O00"), // + hasAmount("EUR", 51.63), hasGrossValue("EUR", 51.63), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende03() + public void testDividende03MitSteuerbehandlungVonDividende03() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende03.txt", "Dividende03.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende03.txt", "SteuerbehandlungVonDividende03.txt"), + errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("LU0875160326")); - assertThat(security.getWkn(), is("DBX0NK")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N.")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("LU0875160326"), hasWkn("DBX0NK"), hasTicker(null), // + hasName("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N."), // + hasCurrencyCode("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("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("Dividende03.txt; SteuermitteilungDividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(228.01)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(48.94 + 2.69)))); - assertThat(transaction.getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-04-27T00:00"), hasShares(1700.00), // + hasSource("Dividende03.txt; SteuerbehandlungVonDividende03.txt"), // + hasNote("R.-Nr.: CPS-2020-0223620168-0001148 | Tr.-Nr.: INDTBK12120CG000130O00"), // + hasAmount("EUR", 228.01), hasGrossValue("EUR", 279.64), // + hasForexGrossValue("USD", 304.81), // + hasTaxes("EUR", 51.63), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentForDividende03WithSecurityInEUR() + public void testDividende03MitSteuerbehandlungVonDividende03WithSecurityInEUR() { Security security = new Security("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N.", CurrencyUnit.EUR); security.setIsin("LU0875160326"); @@ -1209,140 +960,70 @@ public void testDividendeWithTaxTreatmentForDividende03WithSecurityInEUR() List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende03.txt", "SteuermitteilungDividende03.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende03.txt", "Dividende03.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); // 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("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("Dividende03.txt; SteuermitteilungDividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(228.01)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(48.94 + 2.69)))); - 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)); + assertThat(results, hasItem(dividend( // + hasDate("2020-04-27T00:00"), hasShares(1700.00), // + hasSource("Dividende03.txt; SteuerbehandlungVonDividende03.txt"), // + hasNote("R.-Nr.: CPS-2020-0223620168-0001148 | Tr.-Nr.: INDTBK12120CG000130O00"), // + hasAmount("EUR", 228.01), hasGrossValue("EUR", 279.64), // + hasTaxes("EUR", 51.63), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende03WithSecurityInEUR() + public void testDividende03MitSteuerbehandlungVonDividende03_SourceFilesReversed() { - Security security = new Security("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N.", CurrencyUnit.EUR); - security.setIsin("LU0875160326"); - security.setWkn("DBX0NK"); - - Client client = new Client(); - client.addSecurity(security); - - TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende03.txt", "Dividende03.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende03.txt", "Dividende03.txt"), + errors); assertThat(errors, empty()); - assertThat(results.size(), is(1)); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); 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("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("Dividende03.txt; SteuermitteilungDividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(228.01)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(48.94 + 2.69)))); - 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 testDividendeWithTaxTreatmentForDividende03WithSecurityInUSD() - { - Security security = new Security("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N.", CurrencyUnit.USD); - security.setIsin("LU0875160326"); - security.setWkn("DBX0NK"); - - Client client = new Client(); - client.addSecurity(security); - - TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); - - List errors = new ArrayList<>(); - - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende03.txt", "SteuermitteilungDividende03.txt"), errors); - - assertThat(errors, empty()); - assertThat(results.size(), is(1)); - new AssertImportActions().check(results, CurrencyUnit.EUR); + // check security + assertThat(results, hasItem(security( // + hasIsin("LU0875160326"), hasWkn("DBX0NK"), hasTicker(null), // + hasName("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N."), // + hasCurrencyCode("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("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("Dividende03.txt; SteuermitteilungDividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(228.01)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(48.94 + 2.69)))); - 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(304.81)))); - - CheckCurrenciesAction c = new CheckCurrenciesAction(); - Account account = new Account(); - account.setCurrencyCode(CurrencyUnit.EUR); - Status s = c.process(transaction, account); - assertThat(s, is(Status.OK_STATUS)); + assertThat(results, hasItem(dividend( // + hasDate("2020-04-27T00:00"), hasShares(1700.00), // + hasSource("Dividende03.txt; SteuerbehandlungVonDividende03.txt"), // + hasNote("R.-Nr.: CPS-2020-0223620168-0001148 | Tr.-Nr.: INDTBK12120CG000130O00"), // + hasAmount("EUR", 228.01), hasGrossValue("EUR", 279.64), // + hasTaxes("EUR", 51.63), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende03WithSecurityInUSD() + public void testDividende03MitSteuerbehandlungVonDividende03WithSecurityInEUR_SourceFilesReversed() { - Security security = new Security("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N.", CurrencyUnit.USD); + Security security = new Security("Xtrackers Harvest CSI300 - Inhaber-Anteile 1D o.N.", CurrencyUnit.EUR); security.setIsin("LU0875160326"); security.setWkn("DBX0NK"); @@ -1353,40 +1034,31 @@ public void testDividendeWithTaxTreatmentReversedForDividende03WithSecurityInUSD List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende03.txt", "Dividende03.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende03.txt", "SteuerbehandlungVonDividende03.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); // 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("2020-04-27T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1700))); - assertThat(transaction.getSource(), is("Dividende03.txt; SteuermitteilungDividende03.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(228.01)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(279.64)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(48.94 + 2.69)))); - 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(304.81)))); - - CheckCurrenciesAction c = new CheckCurrenciesAction(); - Account account = new Account(); - account.setCurrencyCode(CurrencyUnit.EUR); - Status s = c.process(transaction, account); - assertThat(s, is(Status.OK_STATUS)); + assertThat(results, hasItem(dividend( // + hasDate("2020-04-27T00:00"), hasShares(1700.00), // + hasSource("Dividende03.txt; SteuerbehandlungVonDividende03.txt"), // + hasNote("R.-Nr.: CPS-2020-0223620168-0001148 | Tr.-Nr.: INDTBK12120CG000130O00"), // + hasAmount("EUR", 228.01), hasGrossValue("EUR", 279.64), // + hasTaxes("EUR", 51.63), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } @Test @@ -1399,164 +1071,145 @@ public void testDividende04() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende04.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("DE0123456789")); - assertThat(security.getWkn(), is("ABC0DE")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Aktiengesellschaft AG")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("DE0123456789"), hasWkn("ABC0DE"), hasTicker(null), // + hasName("Aktiengesellschaft AG"), // + hasCurrencyCode("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("2020-07-10T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1790))); - assertThat(transaction.getSource(), is("Dividende04.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(17.90)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(17.90)))); - 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)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-07-10T00:00"), hasShares(1790.00), // + hasSource("Dividende04.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 17.90), hasGrossValue("EUR", 17.90), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test - public void testTaxTreatmentForDividende04() + public void testSteuerbehandlungVonDividende04() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende04.txt"), errors); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende04.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); assertThat(results.size(), is(2)); new AssertImportActions().check(results, CurrencyUnit.EUR); - // check tax transaction - TransactionItem cancellation = (TransactionItem) results.stream() // - .filter(i -> i.isFailure()) // - .filter(TransactionItem.class::isInstance) // - .findFirst().orElseThrow(IllegalArgumentException::new); - - assertThat(cancellation.getFailureMessage(), is(Messages.MsgErrorTransactionTypeNotSupported)); - assertThat(cancellation.getSource(), is("SteuermitteilungDividende04.txt")); + // check security + assertThat(results, hasItem(security( // + hasIsin("DE0123456789"), hasWkn("ABC0DE"), hasTicker(null), // + hasName("Aktiengesellschaft AG"), // + hasCurrencyCode("EUR")))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-07-08T00:00"), hasShares(1790.00), // + hasSource("SteuerbehandlungVonDividende04.txt"), // + hasNote("Tr.-Nr.: NUMMER"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test - public void testDividendeWithTaxTreatmentForDividende04() + public void testDividende04MitSteuerbehandlungVonDividende04() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende04.txt", "SteuermitteilungDividende04.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende04.txt", "SteuerbehandlungVonDividende04.txt"), + errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(2L)); assertThat(results.size(), is(3)); 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("DE0123456789")); - assertThat(security.getWkn(), is("ABC0DE")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Aktiengesellschaft AG")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("DE0123456789"), hasWkn("ABC0DE"), hasTicker(null), // + hasName("Aktiengesellschaft AG"), // + hasCurrencyCode("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("2020-07-10T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1790))); - assertThat(transaction.getSource(), is("Dividende04.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(17.90)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(17.90)))); - 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)))); - - // check transaction - TransactionItem cancellation = (TransactionItem) results.stream() // - .filter(i -> i.isFailure()) // - .filter(TransactionItem.class::isInstance) // - .findFirst().orElseThrow(IllegalArgumentException::new); - - assertThat(cancellation.getFailureMessage(), is(Messages.MsgErrorTransactionTypeNotSupported)); - assertThat(cancellation.getSource(), is("SteuermitteilungDividende04.txt")); + assertThat(results, hasItem(dividend( // + hasDate("2020-07-10T00:00"), hasShares(1790.00), // + hasSource("Dividende04.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 17.90), hasGrossValue("EUR", 17.90), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-07-08T00:00"), hasShares(1790.00), // + hasSource("SteuerbehandlungVonDividende04.txt"), // + hasNote("Tr.-Nr.: NUMMER"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende04() + public void testDividende04MitSteuerbehandlungVonDividende04_SourceFilesReversed() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende04.txt", "Dividende04.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende04.txt", "Dividende04.txt"), + errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(2L)); assertThat(results.size(), is(3)); 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("DE0123456789")); - assertThat(security.getWkn(), is("ABC0DE")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Aktiengesellschaft AG")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("DE0123456789"), hasWkn("ABC0DE"), hasTicker(null), // + hasName("Aktiengesellschaft AG"), // + hasCurrencyCode("EUR")))); // check dividends transaction - AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) - .skip(1).findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); - - assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-07-10T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1790))); - assertThat(transaction.getSource(), is("Dividende04.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(17.90)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(17.90)))); - 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)))); - - // check transaction - TransactionItem cancellation = (TransactionItem) results.stream() // - .filter(i -> i.isFailure()) // - .filter(TransactionItem.class::isInstance) // - .findFirst().orElseThrow(IllegalArgumentException::new); - - assertThat(cancellation.getFailureMessage(), is(Messages.MsgErrorTransactionTypeNotSupported)); - assertThat(cancellation.getSource(), is("SteuermitteilungDividende04.txt")); + assertThat(results, hasItem(dividend( // + hasDate("2020-07-10T00:00"), hasShares(1790.00), // + hasSource("Dividende04.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 17.90), hasGrossValue("EUR", 17.90), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-07-08T00:00"), hasShares(1790.00), // + hasSource("SteuerbehandlungVonDividende04.txt"), // + hasNote("Tr.-Nr.: NUMMER"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test @@ -1569,40 +1222,26 @@ public void testDividende05() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende05.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("DE0123456789")); - assertThat(security.getWkn(), is("ABC0DE")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Aktiengesellschaft AG")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); + assertThat(results, hasItem(security( // + hasIsin("DE0123456789"), hasWkn("ABC0DE"), hasTicker(null), // + hasName("Aktiengesellschaft AG"), // + hasCurrencyCode("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("2020-08-31T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("Dividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(20.82)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.49)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - 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(29.41)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-08-31T00:00"), hasShares(235.00), // + hasSource("Dividende05.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 20.82), hasGrossValue("EUR", 20.82), // + hasForexGrossValue("USD", 25.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test @@ -1622,170 +1261,209 @@ public void testDividende05WithSecurityInEUR() List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende05.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); // 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("2020-08-31T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("Dividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(20.82)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.49)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - 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)); + assertThat(results, hasItem(dividend( // + hasDate("2020-08-31T00:00"), hasShares(235.00), // + hasSource("Dividende05.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 20.82), hasGrossValue("EUR", 20.82), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } @Test - public void testTaxTreatmentForDividende05() + public void testSteuerbehandlungVonDividende05() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende05.txt"), errors); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende05.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("DE0123456789")); - assertThat(security.getWkn(), is("ABC0DE")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Aktiengesellschaft AG")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); - - // check tax transaction - AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) - .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(transaction.getType(), is(AccountTransaction.Type.TAXES)); - - assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-08-21T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("SteuermitteilungDividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - 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)))); + assertThat(results, hasItem(security( // + hasIsin("DE0123456789"), hasWkn("ABC0DE"), hasTicker(null), // + hasName("Aktiengesellschaft AG"), // + hasCurrencyCode("EUR")))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-08-21T00:00"), hasShares(235.00), // + hasSource("SteuerbehandlungVonDividende05.txt"), // + hasNote("Tr.-Nr.: NUMMER"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test - public void testDividendeWithTaxTreatmentForDividende05() + public void testDividende05MitSteuerbehandlungVonDividende05() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende05.txt", "SteuermitteilungDividende05.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende05.txt", "SteuerbehandlungVonDividende05.txt"), + errors); assertThat(errors, empty()); - assertThat(results.size(), is(2)); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(2L)); + assertThat(results.size(), is(3)); 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("DE0123456789")); - assertThat(security.getWkn(), is("ABC0DE")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Aktiengesellschaft AG")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD)); + assertThat(results, hasItem(security( // + hasIsin("DE0123456789"), hasWkn("ABC0DE"), hasTicker(null), // + hasName("Aktiengesellschaft AG"), // + hasCurrencyCode("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("2020-08-31T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("Dividende05.txt; SteuermitteilungDividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(20.82)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.49)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - 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(29.41)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-08-31T00:00"), hasShares(235.00), // + hasSource("Dividende05.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 20.82), hasGrossValue("EUR", 20.82), // + hasForexGrossValue("USD", 25.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-08-21T00:00"), hasShares(235.00), // + hasSource("SteuerbehandlungVonDividende05.txt"), // + hasNote("Tr.-Nr.: NUMMER"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende05() + public void testDividende05MitSteuerbehandlungVonDividende05WithSecurityInEUR() { - TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); + Security security = new Security("Aktiengesellschaft AG", CurrencyUnit.EUR); + security.setIsin("DE0123456789"); + security.setWkn("ABC0DE"); + + Client client = new Client(); + client.addSecurity(security); + + TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende05.txt", "Dividende05.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende05.txt", "Dividende05.txt"), + errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(0L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(2L)); assertThat(results.size(), is(2)); new AssertImportActions().check(results, CurrencyUnit.EUR); + // check dividends transaction + assertThat(results, hasItem(dividend( // + hasDate("2020-08-31T00:00"), hasShares(235.00), // + hasSource("Dividende05.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 20.82), hasGrossValue("EUR", 20.82), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-08-21T00:00"), hasShares(235.00), // + hasSource("SteuerbehandlungVonDividende05.txt"), // + hasNote("Tr.-Nr.: NUMMER"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + }))))); + } + + @Test + public void testDividende05MitSteuerbehandlungVonDividende05_SourceFilesReversed() + { + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende05.txt", "Dividende05.txt"), + errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(2L)); + assertThat(results.size(), is(3)); + 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("DE0123456789")); - assertThat(security.getWkn(), is("ABC0DE")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("Aktiengesellschaft AG")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("DE0123456789"), hasWkn("ABC0DE"), hasTicker(null), // + hasName("Aktiengesellschaft AG"), // + hasCurrencyCode("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("2020-08-31T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("Dividende05.txt; SteuermitteilungDividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(20.82)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.49)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - assertThat(transaction.getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(dividend( // + hasDate("2020-08-31T00:00"), hasShares(235.00), // + hasSource("Dividende05.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 20.82), hasGrossValue("EUR", 20.82), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-08-21T00:00"), hasShares(235.00), // + hasSource("SteuerbehandlungVonDividende05.txt"), // + hasNote("Tr.-Nr.: NUMMER"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))))); } @Test - public void testDividendeWithTaxTreatmentForDividende05WithSecurityInEUR() + public void testDividende05MitSteuerbehandlungVonDividende05WithSecurityInEUR_SourceFilesReversed() { Security security = new Security("Aktiengesellschaft AG", CurrencyUnit.EUR); security.setIsin("DE0123456789"); @@ -1798,142 +1476,217 @@ public void testDividendeWithTaxTreatmentForDividende05WithSecurityInEUR() List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende05.txt", "SteuermitteilungDividende05.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende05.txt", "SteuerbehandlungVonDividende05.txt"), + errors); assertThat(errors, empty()); - assertThat(results.size(), is(1)); + assertThat(countSecurities(results), is(0L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(2L)); + assertThat(results.size(), is(2)); 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("2020-08-31T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("Dividende05.txt; SteuermitteilungDividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(20.82)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.49)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - 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)); + assertThat(results, hasItem(dividend( // + hasDate("2020-08-31T00:00"), hasShares(235.00), // + hasSource("Dividende05.txt"), // + hasNote("R.-Nr.: NUMMER"), // + hasAmount("EUR", 20.82), hasGrossValue("EUR", 20.82), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); + + // check cancellation transaction + assertThat(results, hasItem(withFailureMessage( // + Messages.MsgErrorTransactionTypeNotSupported, // + taxes( // + hasDate("2020-08-21T00:00"), hasShares(235.00), // + hasSource("SteuerbehandlungVonDividende05.txt"), // + hasNote("Tr.-Nr.: NUMMER"), // + hasAmount("EUR", 0.00), hasGrossValue("EUR", 0.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + }))))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende05WithSecurityInEUR() + public void testDividende06() { - Security security = new Security("Aktiengesellschaft AG", CurrencyUnit.EUR); - security.setIsin("DE0123456789"); - security.setWkn("ABC0DE"); + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); - Client client = new Client(); - client.addSecurity(security); + List errors = new ArrayList<>(); - TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende06.txt"), errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check security + assertThat(results, hasItem(security( // + hasIsin("DE0002635307"), hasWkn("263530"), hasTicker(null), // + hasName("iSh.STOXX Europe 600 U.ETF DE - Inhaber-Anteile"), // + hasCurrencyCode("EUR")))); + + // check dividends transaction + assertThat(results, hasItem(dividend( // + hasDate("2022-12-15T00:00"), hasShares(1227.00), // + hasSource("Dividende06.txt"), // + hasNote("R.-Nr.: CPS-2022-0223620024-0002215"), // + hasAmount("EUR", 217.69), hasGrossValue("EUR", 217.69), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + } + + @Test + public void testSteuerbehandlungVonDividende06() + { + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende05.txt", "Dividende05.txt"), errors); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende06.txt"), errors); assertThat(errors, empty()); - assertThat(results.size(), is(1)); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check security + assertThat(results, hasItem(security( // + hasIsin("DE0002635307"), hasWkn("263530"), hasTicker(null), // + hasName("iSh.STOXX Europe 600 U.ETF DE - Inhaber-Anteile"), // + hasCurrencyCode("EUR")))); + + // check taxes transaction + assertThat(results, hasItem(taxes( // + hasDate("2022-12-15T00:00"), hasShares(1227.00), // + hasSource("SteuerbehandlungVonDividende06.txt"), // + hasNote("Tr.-Nr.: INDTBK34822CG020886O00"), // + hasAmount("EUR", 42.65), hasGrossValue("EUR", 42.65), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); + } + + @Test + public void testDividende06MitSteuerbehandlungVonDividende06() + { + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); + + List errors = new ArrayList<>(); + + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende06.txt", "SteuerbehandlungVonDividende06.txt"), + errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); new AssertImportActions().check(results, CurrencyUnit.EUR); + // check security + assertThat(results, hasItem(security( // + hasIsin("DE0002635307"), hasWkn("263530"), hasTicker(null), // + hasName("iSh.STOXX Europe 600 U.ETF DE - Inhaber-Anteile"), // + hasCurrencyCode("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("2020-08-31T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("Dividende05.txt; SteuermitteilungDividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(20.82)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.49)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - 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)); + assertThat(results, hasItem(dividend( // + hasDate("2022-12-15T00:00"), hasShares(1227.00), // + hasSource("Dividende06.txt; SteuerbehandlungVonDividende06.txt"), // + hasNote("R.-Nr.: CPS-2022-0223620024-0002215 | Tr.-Nr.: INDTBK34822CG020886O00"), // + hasAmount("EUR", 175.04), hasGrossValue("EUR", 217.69), // + hasTaxes("EUR", 42.65), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentForDividende05WithSecurityInUSD() + public void testDividende06MitSteuerbehandlungVonDividende06_SourceFilesReversed() { - Security security = new Security("Aktiengesellschaft AG", CurrencyUnit.USD); - security.setIsin("DE0123456789"); - security.setWkn("ABC0DE"); + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); - Client client = new Client(); - client.addSecurity(security); + List errors = new ArrayList<>(); - TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende06.txt", "Dividende06.txt"), + errors); + + assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); + new AssertImportActions().check(results, CurrencyUnit.EUR); + + // check security + assertThat(results, hasItem(security( // + hasIsin("DE0002635307"), hasWkn("263530"), hasTicker(null), // + hasName("iSh.STOXX Europe 600 U.ETF DE - Inhaber-Anteile"), // + hasCurrencyCode("EUR")))); + + // check dividends transaction + assertThat(results, hasItem(dividend( // + hasDate("2022-12-15T00:00"), hasShares(1227.00), // + hasSource("Dividende06.txt; SteuerbehandlungVonDividende06.txt"), // + hasNote("R.-Nr.: CPS-2022-0223620024-0002215 | Tr.-Nr.: INDTBK34822CG020886O00"), // + hasAmount("EUR", 175.04), hasGrossValue("EUR", 217.69), // + hasTaxes("EUR", 42.65), hasFees("EUR", 0.00)))); + } + + @Test + public void testDividende07() + { + TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende05.txt", "SteuermitteilungDividende05.txt"), errors); + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende07.txt"), errors); assertThat(errors, empty()); - assertThat(results.size(), is(1)); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(2)); new AssertImportActions().check(results, CurrencyUnit.EUR); + // check security + assertThat(results, hasItem(security( // + hasIsin("US6668071029"), hasWkn("851915"), hasTicker(null), // + hasName("Northrop Grumman Corp. - Registered Shares DL 1"), // + hasCurrencyCode("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("2020-08-31T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("Dividende05.txt; SteuermitteilungDividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(20.82)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.49)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - 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(29.41)))); - - CheckCurrenciesAction c = new CheckCurrenciesAction(); - Account account = new Account(); - account.setCurrencyCode(CurrencyUnit.EUR); - Status s = c.process(transaction, account); - assertThat(s, is(Status.OK_STATUS)); + assertThat(results, hasItem(dividend( // + hasDate("2024-12-18T00:00"), hasShares(4.00), // + hasSource("Dividende07.txt"), // + hasNote("R.-Nr.: CPS-2024-0223620171-0003969"), // + hasAmount("EUR", 6.71), hasGrossValue("EUR", 6.71), // + hasForexGrossValue("USD", 7.00), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende05WithSecurityInUSD() + public void testDividende07WithSecurityInEUR() { - Security security = new Security("Aktiengesellschaft AG", CurrencyUnit.USD); - security.setIsin("DE0123456789"); - security.setWkn("ABC0DE"); + Security security = new Security("Northrop Grumman Corp. - Registered Shares DL 1", CurrencyUnit.EUR); + security.setIsin("US6668071029"); + security.setWkn("851915"); Client client = new Client(); client.addSecurity(security); @@ -1942,211 +1695,209 @@ public void testDividendeWithTaxTreatmentReversedForDividende05WithSecurityInUSD List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende05.txt", "Dividende05.txt"), errors); + List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende07.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); // 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("2020-08-31T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(235))); - assertThat(transaction.getSource(), is("Dividende05.txt; SteuermitteilungDividende05.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(20.82)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(24.49)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(3.67)))); - 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(29.41)))); - - CheckCurrenciesAction c = new CheckCurrenciesAction(); - Account account = new Account(); - account.setCurrencyCode(CurrencyUnit.EUR); - Status s = c.process(transaction, account); - assertThat(s, is(Status.OK_STATUS)); + assertThat(results, hasItem(dividend( // + hasDate("2024-12-18T00:00"), hasShares(4.00), // + hasSource("Dividende07.txt"), // + hasNote("R.-Nr.: CPS-2024-0223620171-0003969"), // + hasAmount("EUR", 6.71), hasGrossValue("EUR", 6.71), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } @Test - public void testDividende06() + public void testSteuerbehandlungVonDividende07() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende06.txt"), errors); + List results = extractor + .extract(PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende07.txt"), errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("DE0002635307")); - assertThat(security.getWkn(), is("263530")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("iSh.STOXX Europe 600 U.ETF DE - Inhaber-Anteile")); - assertThat(security.getCurrencyCode(), is(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-12-15T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1227))); - assertThat(transaction.getSource(), is("Dividende06.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(217.69)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(217.69)))); - 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)))); + assertThat(results, hasItem(security( // + hasIsin("US6668071029"), hasWkn("851915"), hasTicker(null), // + hasName("Northrop Grumman Corp. - Registered Shares DL 1"), // + hasCurrencyCode("EUR")))); + + // check taxes transaction + assertThat(results, hasItem(taxes( // + hasDate("2024-12-18T00:00"), hasShares(4.00), // + hasSource("SteuerbehandlungVonDividende07.txt"), // + hasNote("Tr.-Nr.: INDTBK35424CG007898O00"), // + hasAmount("EUR", 0.83), hasGrossValue("EUR", 0.83), // + hasTaxes("EUR", 0.00), hasFees("EUR", 0.00)))); } @Test - public void testTaxTreatmentForDividende06() + public void testDividende07MitSteuerbehandlungVonDividende07() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende06.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende07.txt", "SteuerbehandlungVonDividende07.txt"), + errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("DE0002635307")); - assertThat(security.getWkn(), is("263530")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("iSh.STOXX Europe 600 U.ETF DE - Inhaber-Anteile")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); - - // check tax transaction - AccountTransaction transaction = (AccountTransaction) results.stream().filter(TransactionItem.class::isInstance) - .findFirst().orElseThrow(IllegalArgumentException::new).getSubject(); - - assertThat(transaction.getType(), is(AccountTransaction.Type.TAXES)); - - assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2022-12-15T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1227))); - assertThat(transaction.getSource(), is("SteuermitteilungDividende06.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(37.26 + 2.04 + 3.35)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(37.26 + 2.04 + 3.35)))); - 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)))); + assertThat(results, hasItem(security( // + hasIsin("US6668071029"), hasWkn("851915"), hasTicker(null), // + hasName("Northrop Grumman Corp. - Registered Shares DL 1"), // + hasCurrencyCode("USD")))); + + // check dividends transaction + assertThat(results, hasItem(dividend( // + hasDate("2024-12-18T00:00"), hasShares(4.00), // + hasSource("Dividende07.txt; SteuerbehandlungVonDividende07.txt"), // + hasNote("R.-Nr.: CPS-2024-0223620171-0003969 | Tr.-Nr.: INDTBK35424CG007898O00"), // + hasAmount("EUR", 7.06), hasGrossValue("EUR", 7.89), // + hasForexGrossValue("USD", 8.24), // + hasTaxes("EUR", 0.83), hasFees("EUR", 0.00)))); } @Test - public void testDividendeWithTaxTreatmentForDividende06() + public void testDividende07MitSteuerbehandlungVonDividende03WithSecurityInEUR() { - TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); + Security security = new Security("Northrop Grumman Corp. - Registered Shares DL 1", CurrencyUnit.EUR); + security.setIsin("US6668071029"); + security.setWkn("851915"); + + Client client = new Client(); + client.addSecurity(security); + + TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende06.txt", "SteuermitteilungDividende06.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende07.txt", "Dividende07.txt"), + errors); assertThat(errors, empty()); - assertThat(results.size(), is(2)); + assertThat(countSecurities(results), is(0L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); + assertThat(results.size(), is(1)); new AssertImportActions().check(results, CurrencyUnit.EUR); - // check security - Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst() - .orElseThrow(IllegalArgumentException::new).getSecurity(); - assertThat(security.getIsin(), is("DE0002635307")); - assertThat(security.getWkn(), is("263530")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("iSh.STOXX Europe 600 U.ETF DE - Inhaber-Anteile")); - assertThat(security.getCurrencyCode(), is(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-12-15T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1227))); - assertThat(transaction.getSource(), is("Dividende06.txt; SteuermitteilungDividende06.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(175.04)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(217.69)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(37.26 + 2.04 + 3.35)))); - assertThat(transaction.getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(dividend( // + hasDate("2024-12-18T00:00"), hasShares(4.00), // + hasSource("Dividende07.txt; SteuerbehandlungVonDividende07.txt"), // + hasNote("R.-Nr.: CPS-2024-0223620171-0003969 | Tr.-Nr.: INDTBK35424CG007898O00"), // + hasAmount("EUR", 7.06), hasGrossValue("EUR", 7.89), // + hasTaxes("EUR", 0.83), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } @Test - public void testDividendeWithTaxTreatmentReversedForDividende06() + public void testDividende07MitSteuerbehandlungVonDividende07_SourceFilesReversed() { TargobankPDFExtractor extractor = new TargobankPDFExtractor(new Client()); List errors = new ArrayList<>(); - List results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SteuermitteilungDividende06.txt", "Dividende06.txt"), errors); + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "SteuerbehandlungVonDividende07.txt", "Dividende07.txt"), + errors); assertThat(errors, empty()); + assertThat(countSecurities(results), is(1L)); + assertThat(countBuySell(results), is(0L)); + assertThat(countAccountTransactions(results), is(1L)); 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("DE0002635307")); - assertThat(security.getWkn(), is("263530")); - assertNull(security.getTickerSymbol()); - assertThat(security.getName(), is("iSh.STOXX Europe 600 U.ETF DE - Inhaber-Anteile")); - assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR)); + assertThat(results, hasItem(security( // + hasIsin("US6668071029"), hasWkn("851915"), hasTicker(null), // + hasName("Northrop Grumman Corp. - Registered Shares DL 1"), // + hasCurrencyCode("EUR")))); + + // check dividends transaction + assertThat(results, hasItem(dividend( // + hasDate("2024-12-18T00:00"), hasShares(4.00), // + hasSource("Dividende07.txt; SteuerbehandlungVonDividende07.txt"), // + hasNote("R.-Nr.: CPS-2024-0223620171-0003969 | Tr.-Nr.: INDTBK35424CG007898O00"), // + hasAmount("EUR", 7.06), hasGrossValue("EUR", 7.89), // + hasTaxes("EUR", 0.83), hasFees("EUR", 0.00)))); + } + + @Test + public void testDividende07MitSteuerbehandlungVonDividende07WithSecurityInEUR_SourceFilesReversed() + { + Security security = new Security("Northrop Grumman Corp. - Registered Shares DL 1", CurrencyUnit.EUR); + security.setIsin("US6668071029"); + security.setWkn("851915"); + + Client client = new Client(); + client.addSecurity(security); + + TargobankPDFExtractor extractor = new TargobankPDFExtractor(client); + + List errors = new ArrayList<>(); + + List results = extractor.extract( + PDFInputFile.loadTestCase(getClass(), "Dividende07.txt", "SteuerbehandlungVonDividende07.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); // 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-12-15T00:00"))); - assertThat(transaction.getShares(), is(Values.Share.factorize(1227))); - assertThat(transaction.getSource(), is("Dividende06.txt; SteuermitteilungDividende06.txt")); - assertNull(transaction.getNote()); - - assertThat(transaction.getMonetaryAmount(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(175.04)))); - assertThat(transaction.getGrossValue(), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(217.69)))); - assertThat(transaction.getUnitSum(Unit.Type.TAX), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(37.26 + 2.04 + 3.35)))); - assertThat(transaction.getUnitSum(Unit.Type.FEE), - is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(0.00)))); + assertThat(results, hasItem(dividend( // + hasDate("2024-12-18T00:00"), hasShares(4.00), // + hasSource("Dividende07.txt; SteuerbehandlungVonDividende07.txt"), // + hasNote("R.-Nr.: CPS-2024-0223620171-0003969 | Tr.-Nr.: INDTBK35424CG007898O00"), // + hasAmount("EUR", 7.06), hasGrossValue("EUR", 7.89), // + hasTaxes("EUR", 0.83), hasFees("EUR", 0.00), // + check(tx -> { + CheckCurrenciesAction c = new CheckCurrenciesAction(); + Account account = new Account(); + account.setCurrencyCode(CurrencyUnit.EUR); + Status s = c.process((AccountTransaction) tx, account); + assertThat(s, is(Status.OK_STATUS)); + })))); } } diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/Verkauf03.txt b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/Verkauf03.txt new file mode 100644 index 0000000000..cc57cf6890 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/targobank/Verkauf03.txt @@ -0,0 +1,46 @@ +PDFBox Version: 1.8.17 +Portfolio Performance Version: 0.61.3 +----------------------------------------- +TARGOBANK AG +Postfach 10 02 30 +47002 Duisburg +TARGOBANK AG - Postfach 10 02 30 - 47002 Duisburg www.targobank.de +HERR +JERKO SABALIC +TAIMERHOFSTR. 7 +81927 MUENCHEN +Depotnummer 101167153000 +........................................................................................................................................................................................................ +Effektenabrechnung 03.01.2023 +Rechnungsnummer: BOE-2023-0223620153-0000031 +JERKO SABALIC +Transaktionstyp Verkauf +Stück 4.000 +Wertpapier UBS AG (London Branch) - FaktS O.End DJIA 34446,1281 +WKN / ISIN UH3GTU / DE000UH3GTU5 +Handelsplatz außerbörs. Echtzeithandel +Handelspartner UBS INVESTMENT BANK GBR +Schlusstag / Handelszeit 03.01.2023 / 12:04:02 +Kurs 0,001 EUR +Verwahrart Girosammelverwahrung +Neuer Bestand 0 +Geschäftsnummer 00323B007292O001 +Referenznummer 9301031204028497 +Kurswert 4,00 EUR +Provision 3,99 EUR +Gutschrift auf Ihrem Konto mit Wertstellung zum 5. Januar 2023 +Konto-Nr. 1011671530 0,01 EUR +Kommissionsgeschäft +Finanzdienstleistungen mit Leistungsort in der Europäischen Union sind umsatzsteuerfrei nach § 4 Nr. 8 UStG. +Finanzdienstleistungen mit Leistungsort in einem Drittland sind nicht umsatzsteuerbar. +Dieses Produkt ist keine Bankeinlage. Es unterliegt nicht der Einlagensicherung. Die vergangene Performance lässt +keine Rückschlüsse auf die zukünftige Wertentwicklung zu. Der Wert der Anlage kann schwanken. Ein teilweiser oder +ganzer Verlust ist möglich. Dieser Beleg wurde maschinell erstellt und wird nicht unterschrieben. Irrtum vorbehalten. +Seite 1 +TARGOBANK AG | Vorstand: Isabelle Chevelard (Vorsitzende); Christophe Jéhan (stellv. Vorsitzender); Berthold Rüsing; Maria Topaler +Vorsitzender des Aufsichtsrates: René Dangel | Sitz der Gesellschaft: Düsseldorf +Handelsregister Amtsgericht Düsseldorf HRB 83351 | USt-ID-Nr.: DE 811 285 485 +USt-ID-Nr. des umsatzsteuerlichen Organträgers: DE 811 623 326 +KH.20230104.020727.5002.0001.4843 X 0 R + +> Blockzitat \ No newline at end of file diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/TargobankPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/TargobankPDFExtractor.java index 3d311c43d4..50ed2ae0c3 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/TargobankPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/TargobankPDFExtractor.java @@ -2,52 +2,67 @@ import static name.abuchen.portfolio.datatransfer.ExtractorUtils.checkAndSetGrossUnit; import static name.abuchen.portfolio.util.TextUtil.concatenate; +import static name.abuchen.portfolio.util.TextUtil.trim; -import java.time.LocalDateTime; -import java.util.Iterator; +import java.time.LocalDate; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.Set; import name.abuchen.portfolio.Messages; import name.abuchen.portfolio.datatransfer.ExtrExchangeRate; +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.AttributeType; import name.abuchen.portfolio.model.BuySellEntry; import name.abuchen.portfolio.model.Client; import name.abuchen.portfolio.model.PortfolioTransaction; import name.abuchen.portfolio.model.Security; import name.abuchen.portfolio.model.Transaction.Unit; import name.abuchen.portfolio.money.Money; +import name.abuchen.portfolio.util.Pair; + +/** + * @formatter:off + * @implNote Targo bank provides two documents for the transaction. + * The security transaction and the taxes treatment. + * Both documents are provided as one PDF or as two PDFs. + * + * The security transaction includes the fees, but not the correct taxes + * and the taxes treatment includes all taxes (including withholding tax), + * but not all fees. + * + * Therefore, we use the documents based on their function and merge both documents, if possible, as one transaction. + * {@code + * matchTransactionPair(List transactionList,List taxesTreatmentList) + * } + * + * The separate taxes treatment does only contain taxes in the account currency. + * However, if the security currency differs, we need to provide the currency conversion. + * {@code + * fixMissingCurrencyConversionForSaleTaxesTransactions(Collection) + * } + * + * Always import the securities transaction and the taxes treatment for a correct transaction. + * Due to rounding differences, the correct gross amount is not always shown in the securities transaction. + * + * In postProcessing, we always finally delete the taxes treatment. + * @formatter:on + */ @SuppressWarnings("nls") public class TargobankPDFExtractor extends AbstractPDFExtractor { - /** - * @formatter:off - * Information: - * Targobank AG always creates two documents per transaction. - * - * 1. Transaction, e.g. sale or dividend - * 2. tax statement - * - * To offset the taxes due with the transaction, we use the ex-tag as a - * transaction date, which we later replace again with the payment date in - * postProcessing(). - * - * The reason for this is that sometimes the transaction - * date is different between the taxes document and the transaction. - * - * @Override public List postProcessing(List items) - * @formatter:on - */ + private static record TransactionTaxesPair(Item transaction, Item tax) + { + } - private static final String TO_BE_DELETED = "to_be_deleted"; - private static final String ATTRIBUTE_PAY_DATE = "pay_date"; + private static final String ATTRIBUTE_GROSS_TAXES_TREATMENT = "gross_taxes_treatment"; public TargobankPDFExtractor(Client client) { @@ -58,9 +73,8 @@ public TargobankPDFExtractor(Client client) addBankIdentifier("TARGOBANK AG"); addBuySellTransaction(); - addTaxTreatmentForBuySellTransaction(); addDividendeTransaction(); - addTaxTreatmentForDividendeTransaction(); + addTaxesTreatmentTransaction(); } @Override @@ -71,339 +85,371 @@ public String getLabel() private void addBuySellTransaction() { - DocumentType type = new DocumentType("Effektenabrechnung [\\d]{2}\\.[\\d]{2}\\.[\\d]{4}"); + final DocumentType type = new DocumentType("Effektenabrechnung [\\d]{2}\\.[\\d]{2}\\.[\\d]{4}"); this.addDocumentTyp(type); Transaction pdfTransaction = new Transaction<>(); - pdfTransaction.subject(() -> { - BuySellEntry entry = new BuySellEntry(); - entry.setType(PortfolioTransaction.Type.BUY); - return entry; - }); - Block firstRelevantLine = new Block("^Transaktionstyp (Kauf|Verkauf)$"); + Block firstRelevantLine = new Block("^Effektenabrechnung .*$"); type.addBlock(firstRelevantLine); firstRelevantLine.set(pdfTransaction); - pdfTransaction - // Is type --> "Verkauf" change from BUY to SELL - .section("type").optional() - .match("^Transaktionstyp (?(Kauf|Verkauf))$") - .assign((t, v) -> { - if ("Verkauf".equals(v.get("type"))) - t.setType(PortfolioTransaction.Type.SELL); - }) + pdfTransaction // - // @formatter:off - // Wertpapier FanCy shaRe. nAmE X0-X0 - // WKN / ISIN ABC123 / DE0000ABC123 - // Kurs 12,34 EUR - // @formatter:on - .section("name", "wkn", "isin", "currency") - .match("^Wertpapier (?.*)$") - .match("^WKN \\/ ISIN (?[A-Z0-9]{6}) \\/ (?[A-Z]{2}[A-Z0-9]{9}[0-9])$") - .match("^(Kurs|Preis vom) .* (?[\\w]{3})$") - .assign((t, v) -> t.setSecurity(getOrCreateSecurity(v))) + .subject(() -> { + BuySellEntry portfolioTransaction = new BuySellEntry(); + portfolioTransaction.setType(PortfolioTransaction.Type.BUY); + return portfolioTransaction; + }) - // @formatter:off - // Stück 987,654 - // @formatter:on - .section("shares") - .match("^St.ck (?[\\.,\\d]+)$") - .assign((t, v) -> t.setShares(asShares(v.get("shares")))) - - .oneOf( - // @formatter:off - // Schlusstag / Handelszeit 02.01.2020 / 13:01:00 - // @formatter:on - section -> section - .attributes("date", "time") - .match("^Schlusstag \\/ Handelszeit (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) \\/ (?