Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package name.abuchen.portfolio.datatransfer.pdf.consorsbank;

import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.check;
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.deposit;
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.dividend;
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasAmount;
Expand Down Expand Up @@ -4016,14 +4015,7 @@ public void testDividende19WithSecurityInEUR()
hasSource("Dividende19.txt"), //
hasNote(null), //
hasAmount("EUR", 44.78), hasGrossValue("EUR", 60.15), //
hasTaxes("EUR", 9.02 + 6.02 + 0.33), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 9.02 + 6.02 + 0.33), hasFees("EUR", 0.00))));
}

@Test
Expand Down Expand Up @@ -4157,14 +4149,7 @@ public void testDividende22WithSecurityInEUR()
hasSource("Dividende22.txt"), //
hasNote(null), //
hasAmount("EUR", 56.33), hasGrossValue("EUR", 56.33), //
hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))));
}

@Test
Expand Down Expand Up @@ -4232,14 +4217,7 @@ public void testDividende23WithSecurityInEUR()
hasSource("Dividende23.txt"), //
hasNote(null), //
hasAmount("EUR", 1.44), hasGrossValue("EUR", 1.94), //
hasTaxes("EUR", 0.29 + 0.19 + 0.01 + 0.01), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 0.29 + 0.19 + 0.01 + 0.01), hasFees("EUR", 0.00))));
}

@Test
Expand Down Expand Up @@ -4307,14 +4285,7 @@ public void testDividende24WithSecurityInEUR()
hasSource("Dividende24.txt"), //
hasNote(null), //
hasAmount("EUR", 10.38), hasGrossValue("EUR", 12.22), //
hasTaxes("EUR", 1.84), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 1.84), hasFees("EUR", 0.00))));
}

@Test
Expand Down Expand Up @@ -4382,14 +4353,7 @@ public void testDividende25WithSecurityInEUR()
hasSource("Dividende25.txt"), //
hasNote(null), //
hasAmount("EUR", 41.99), hasGrossValue("EUR", 41.99), //
hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))));
}

@Test
Expand Down Expand Up @@ -4457,14 +4421,7 @@ public void testDividende26WithSecurityInEUR()
hasSource("Dividende26.txt"), //
hasNote(null), //
hasAmount("EUR", 70.84), hasGrossValue("EUR", 96.21), //
hasTaxes("EUR", 24.05 + 1.32), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 24.05 + 1.32), hasFees("EUR", 0.00))));
}

@Test
Expand Down Expand Up @@ -4532,14 +4489,7 @@ public void testDividende27WithSecurityInEUR()
hasSource("Dividende27.txt"), //
hasNote(null), //
hasAmount("EUR", 69.68), hasGrossValue("EUR", 69.68), //
hasTaxes("EUR", 0.00), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 0.00), hasFees("EUR", 0.00))));
}

@Test
Expand Down Expand Up @@ -4607,14 +4557,7 @@ public void testDividende28WithSecurityInEUR()
hasSource("Dividende28.txt"), //
hasNote(null), //
hasAmount("EUR", 9.75), hasGrossValue("EUR", 11.47), //
hasTaxes("EUR", 1.72), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 1.72), hasFees("EUR", 0.00))));
}

@Test
Expand Down Expand Up @@ -4682,14 +4625,75 @@ public void testDividende29WithSecurityInEUR()
hasSource("Dividende29.txt"), //
hasNote(null), //
hasAmount("EUR", 1.81), hasGrossValue("EUR", 2.13), //
hasTaxes("EUR", 0.32), hasFees("EUR", 0.00), //
check(tx -> {
var c = new CheckCurrenciesAction();
var account = new Account();
account.setCurrencyCode("EUR");
var s = c.process((AccountTransaction) tx, account);
assertThat(s, is(Status.OK_STATUS));
}))));
hasTaxes("EUR", 0.32), hasFees("EUR", 0.00))));
}

@Test
public void testDividende30()
{
var extractor = new ConsorsbankPDFExtractor(new Client());

List<Exception> errors = new ArrayList<>();

var results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende30.txt"), errors);

assertThat(errors, empty());
assertThat(countSecurities(results), is(1L));
assertThat(countBuySell(results), is(0L));
assertThat(countAccountTransactions(results), is(1L));
assertThat(countAccountTransfers(results), is(0L));
assertThat(countItemsWithFailureMessage(results), is(0L));
assertThat(results.size(), is(2));
new AssertImportActions().check(results, "USD");

// check security
assertThat(results, hasItem(security( //
hasIsin("US7427181091"), hasWkn("852062"), hasTicker(null), //
hasName("PROCTER & GAMBLE CO., THE Registered Shares o.N."), //
hasCurrencyCode("USD"))));

// check dividends transaction
assertThat(results, hasItem(dividend( //
hasDate("2025-11-17T00:00"), hasShares(100.00), //
hasSource("Dividende30.txt"), //
hasNote(null), //
hasAmount("USD", 78.68), hasGrossValue("USD", 105.68), //
hasTaxes("USD", 27.00), hasFees("USD", 0.00))));
}

@Test
public void testDividende30WithSecurityInEUR()
{
var security = new Security("PROCTER & GAMBLE CO., THE Registered Shares o.N.", "EUR");
security.setIsin("US7427181091");
security.setWkn("852062");

var client = new Client();
client.addSecurity(security);

var extractor = new ConsorsbankPDFExtractor(client);

List<Exception> errors = new ArrayList<>();

var results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende30.txt"), errors);

assertThat(errors, empty());
assertThat(countSecurities(results), is(0L));
assertThat(countBuySell(results), is(0L));
assertThat(countAccountTransactions(results), is(1L));
assertThat(countAccountTransfers(results), is(0L));
assertThat(countItemsWithFailureMessage(results), is(0L));
assertThat(results.size(), is(1));
new AssertImportActions().check(results, "USD");

// check dividends transaction
assertThat(results, hasItem(dividend( //
hasDate("2025-11-17T00:00"), hasShares(100.00), //
hasSource("Dividende30.txt"), //
hasNote(null), //
hasAmount("USD", 78.68), hasGrossValue("USD", 105.68), //
hasForexGrossValue("EUR", 90.99), //
hasTaxes("USD", 27.00), hasFees("USD", 0.00))));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
PDFBox Version: 3.0.5
Portfolio Performance Version: 0.80.4
System: macosx | x86_64 | 21.0.5+11-LTS | Azul Systems, Inc.
-----------------------------------------
Consorsbank • 90318 Nürnberg
Depotnummer: 4696448174
1500561976/00
Vermerk der Bank: 1000
2
nhDv-LeWUjfS BfPwB
Datum: 18.11.2025
KsY-mhJiRIfL-RiBZZ 55
Seite: 1 von 2
13300 iFXohyJfhLHK
Dividendengutschrift
Wertpapierbezeichnung WKN ISIN
PROCTER & GAMBLE CO., THE Registered Shares o.N. 852062 US7427181091
Bestand
100 Stück
Dividende pro Stück 1,0568 USD Schlusstag 23.10.2025
Brutto in USD 105,68 USD
abzgl. Quellensteuer 15,00 % von 105,68 USD 15,85 USD
89,83 USD
Zwischensumme in USD
Devisenkurs 1,161500 USD / EUR
90,99 EUR
Brutto in EUR
13,65 EUR
Quellensteuer in EUR
Zwischensumme in EUR 77,34 EUR
abzgl. Kapitalertragsteuer 25,00 % von 36,39 EUR 9,10 EUR
abzgl. Solidaritätszuschlag 5,50 % von 9,10 EUR 0,50 EUR
67,74 EUR
Netto in EUR
78,68 USD
Netto in USD zugunsten IBAN qx55 4648 3025 8585 7395 06
Valuta 17.11.2025 BIC DABBDEMMXXX
Anrechenbare Quellensteuer EUR
15,00 % von 105,68 USD 13,65
Bitte beachten Sie die weiteren Informationen auf Seite 2.
Consorsbank ist eine eingetragene Marke der BNP Paribas S.A. Niederlassung Deutschland (AG nach franz. Recht).
Standort Nürnberg: Bahnhofstraße 55, 90402 Nürnberg, HRB Nürnberg 31129, USt-IdNr. DE191528929
Fon +49 (0) 911 / 369-30 00, Fax +49 (0) 911 / 369-10 00, [email protected], www.consorsbank.de
Sitz der BNP Paribas S.A.: 16, boulevard des Italiens, 75009 Paris, Frankreich, Registergericht: R.C.S. Paris 662 042 449
Président du Conseil d‘Administration (Präsident des Verwaltungsrates): Jean Lemierre, Directeur Général (Generaldirektor): Jean-Laurent Bonnafé
C123A1EC-13A0-5133-19D2-6F17D5970C23
Depotnummer: 0408762232
1500561976/00
Vermerk der Bank: 1000
2
Datum: 18.11.2025
Seite: 2 von 2
Details zur Abrechnung
Steuerpflichtiger Gesamtertrag 90,99 EUR
Mit Verrechnungstopf "Allgemein" verrechnet 0,00 EUR
Mit Sparerpauschbetrag verrechnet 0,00 EUR
Mit Quellensteuer verrechnet -54,60 EUR
somit verrechnete Quellensteuer -13,65 EUR
Bemessungsgrundlage für Kapitalertragsteuer gesamt 36,39 EUR
Details zu den Verrechnungstöpfen
Verrechnungstopf "Allgemein" vor der Abrechnung 0,00 EUR
Mit Verrechnungstopf "Allgemein" verrechnet 0,00 EUR
Verrechnungstopf "Allgemein" nach der Abrechnung 0,00 EUR
Sparerpauschbetrag vor der Abrechnung 0,00 EUR
Mit Sparerpauschbetrag verrechnet 0,00 EUR
Sparerpauschbetrag nach der Abrechnung 0,00 EUR
Verrechnungstopf "Quellensteuer" vor der Abrechnung 0,00 EUR
Änderung Verrechnungstopf "Quellensteuer" 0,00 EUR
Verrechnungstopf "Quellensteuer" nach der Abrechnung 0,00 EUR
Original file line number Diff line number Diff line change
Expand Up @@ -490,11 +490,35 @@ private void addDividendeTransaction()
}),
// @formatter:off
// Netto zugunsten IBAN DE00 0000 0000 0000 0000 00 9,34 EUR
// @formatter:on
section -> section //
.attributes("amount", "currency") //
.match("^Netto (zugunsten|zulasten) .* (?<amount>[\\.,\\d]+) (?<currency>[A-Z]{3})$") //
.assign((t, v) -> {
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
t.setAmount(asAmount(v.get("amount")));
}),
// @formatter:off
// Netto in USD zugunsten IBAN DE12 3456 3456 3456 3456 78 6,46 USD
// @formatter:on
section -> section //
.attributes("amount", "currency") //
.match("^Netto( in [A-Z]{3})? (zugunsten|zulasten) .* (?<amount>[\\.,\\d]+) (?<currency>[A-Z]{3})$") //
.match("^Netto in [A-Z]{3} (zugunsten|zulasten) .* (?<amount>[\\.,\\d]+) (?<currency>[A-Z]{3})$") //
.assign((t, v) -> {
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
t.setAmount(asAmount(v.get("amount")));
}),
// @formatter:off
// 67,74 EUR
// Netto in EUR
// 78,68 USD
// Netto in USD zugunsten IBAN qx55 4648 3025 8585 7395 06
// @formatter:on
section -> section //
.attributes("amount", "currency") //
.find("Netto in [A-Z]{3}") //
.match("^(?<amount>[\\.,\\d]+) (?<currency>[A-Z]{3})$")
.match("^Netto in [A-Z]{3} (zugunsten|zulasten) .*$") //
.assign((t, v) -> {
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
t.setAmount(asAmount(v.get("amount")));
Expand Down Expand Up @@ -598,6 +622,23 @@ private void addDividendeTransaction()
checkAndSetGrossUnit(gross, fxGross, t, type.getCurrentContext());
}),
// @formatter:off
// Brutto in USD 105,68 USD
// Devisenkurs 1,161500 USD / EUR
// @formatter:on
section -> section //
.attributes("gross", "exchangeRate", "termCurrency", "baseCurrency") //
.match("^Brutto in [A-Z]{3} (?<gross>[\\.,\\d]+) [A-Z]{3}$") //
.match("^Devisenkurs (?<exchangeRate>[\\.,\\d]+) (?<termCurrency>[A-Z]{3}) \\/ (?<baseCurrency>[A-Z]{3})$") //
.assign((t, v) -> {
var rate = asExchangeRate(v);
type.getCurrentContext().putType(rate);

var gross = Money.of(rate.getTermCurrency(), asAmount(v.get("gross")));
var fxGross = rate.convert(rate.getBaseCurrency(), gross);

checkAndSetGrossUnit(gross, fxGross, t, type.getCurrentContext());
}),
// @formatter:off
// Brutto in USD 10,00 USD
// Devisenkurs 1,12000 USD / EUR
// Brutto in EUR 8,93 EUR
Expand Down