Skip to content
Closed
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
Expand Up @@ -776,6 +776,49 @@ public void testWertpapierVerkauf03()
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(11.94 + 3.50 + 5.40))));
}

@Test
public void testWertpapierVerkauf04()
{
DeutscheBankPDFExtractor extractor = new DeutscheBankPDFExtractor(new Client());

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

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Verkauf04.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("DE0007448508"));
assertThat(security.getWkn(), is("744850"));
assertThat(security.getName(), is("IVU TRAFFIC TECHNOLOGIES AG INH.AKT. O.N."));
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("2022-07-07T09:05")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(1870)));
assertThat(entry.getSource(), is("Verkauf04.txt"));
assertNull(entry.getNote());

assertThat(entry.getPortfolioTransaction().getMonetaryAmount(),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(27613.77))));
assertThat(entry.getPortfolioTransaction().getGrossValue(),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(27676.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(58.90 + 2.00 + 1.33))));
}

@Test
public void testGiroKontoauszug01()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
PDFBox Version: 1.8.16
-----------------------------------------
Deutsche Bank AG
Melissa Otto
Telefon 040 309516-42
Martin Mustermann
24/7-Kundenservice (069) 910-10000
Musterstraße 22
12345 Ort
7. Juli 2022
Abrechnung: Verkauf von Wertpapieren / Zusammenfassung von Teilausführungen
Depotinhaber: Martin Mustermann
Filialnummer Depotnummer Wertpapierbezeichnung Seite
789 1145651 02 IVU TRAFFIC TECHNOLOGIES AG INH.AKT. O.N. 1/2
WKN 744850 Nominal 1.870
ISIN DE0007448508 Mischkurs (EUR) 14,80
Börse Frankfurt a.M. - Deutsche Börse - Frankfurter Wertpapierbörse (FWB) - Xetra
Geschäft Kommissionsgeschäft im Auftragsart Limitauftrag
XETRA-Handel
Schlusstag 07.07.2022 Ordernummer 684978
Verwahrart Girosammeldepot
Diese Order wurde elektronisch übermittelt.
Abrechnung Währung Betrag
Kurswert EUR 27.676,00
Provision EUR -58,90
Weitere Provision der Bank bei der börslichen Orderausführung EUR -2,00
XETRA-Kosten EUR -1,33
Gesamtbetrag
EUR 27.613,77
Summe der in der Abrechnung erhaltenen Provisionen und Auslagen EUR 62,23
TR00000004 TRSA 20220707 6947_000
Abrechnung: Verkauf von Wertpapieren / Zusammenfassung von Teilausführungen
Depotinhaber: Martin Mustermann
Filialnummer Depotnummer Wertpapierbezeichnung Seite
789 1145651 02 IVU TRAFFIC TECHNOLOGIES AG INH.AKT. O.N. 2/2
Detaillierte Auflistung der Teilausführungen
Die Verbuchung erfolgt pro Teilausführung auf Kontonummer 789114565102 mit Wertstellung 11.07.2022
Handelszeit Beleg Nr. Nominal / Stück Kurs (EUR) Kurswert Ausmachender
Betrag (EUR)
09:05 MEZ 1447743358 618 14,80 9.146,40 9.120,93
09:05 MEZ 1447743359 448 14,80 6.630,40 6.613,67
09:05 MEZ 1447743360 533 14,80 7.888,40 7.868,56
09:05 MEZ 1447743361 271 14,80 4.010,80 4.010,61
Summe 1.870 14,80 27.676,00 27.613,77
Informationen zum Steuerabzug Währung Betrag
- keine Steuerbescheinigung -
Veräußerungsverlust EUR -5.131,70
Angerechneter Verlusttopf 'Aktien' EUR 5.131,70
DieWertpapiere haben wir entsprechend der Abrechnung gebucht. Unser Geschäftsverkehr mit Ihnen wird durch unsere Allgemeinen Geschäftsbedingungen
und die Sonderbedingungen für Wertpapiergeschäfte geregelt. Bitte überprüfen Sie diese Abrechnung schnellstmöglich und richten Sie etwaige Einwendungen
in den Geschäftsräumen der Bank oder schriftlich an Deutsche Bank AG, QM - Support, 04082 Leipzig. Andernfalls gilt diese Abrechnung als genehmigt. Die
unter § 4 Nr. 8 UStG im Inland fallenden Bank- und Finanzdienstleistungen sind von der Umsatzsteuer befreit, sofern Umsatzsteuer nicht gesondert ausgewiesen
ist. Soweit der Leistungsempfänger umsatzsteuerlicher Unternehmer ist und seinen Sitz in einem anderen EU-Mitgliedstaat hat und die Bank und
Finanzdienstleistungen nach dortigemRecht umsatzsteuerpflichtig sind, gilt die Steuerschuldnerschaft des Leistungsempfängers. Umsatzsteuer ID Nr.: Deutsche
Bank AG, 60262 Frankfurt DE114103379
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public DeutscheBankPDFExtractor(Client client)
addBankIdentifier("DB Privat- und Firmenkundenbank AG"); //$NON-NLS-1$

addBuySellTransaction();
addBuySellPartialExecutionsTransaction();
addDividendeTransaction();
addAccountStatementTransaction();
}
Expand Down Expand Up @@ -57,7 +58,7 @@ private void addBuySellTransaction()
pdfTransaction
// Is type --> "Verkauf" change from BUY to SELL
.section("type").optional()
.match("^Abrechnung: (?<type>Verkauf) von Wertpapieren$")
.match("^Abrechnung: (?<type>(Kauf|Verkauf)) von Wertpapieren$")
.assign((t, v) -> {
if (v.get("type").equals("Verkauf"))
t.setType(PortfolioTransaction.Type.SELL);
Expand Down Expand Up @@ -91,9 +92,8 @@ private void addBuySellTransaction()
.assign((t, v) -> t.setDate(asDate(v.get("date"), v.get("time"))))
)


// Buchung auf Kontonummer 1234567 40 mit Wertstellung 08.04.2015 EUR 675,50
.section("amount", "currency").optional()
.section("amount", "currency")
.match("^Buchung auf Kontonummer [\\s\\d]+ mit Wertstellung [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} (?<currency>[\\w]{3}) (?<amount>[\\.,\\d]+)$")
.assign((t, v) -> {
t.setAmount(asAmount(v.get("amount")));
Expand All @@ -113,6 +113,83 @@ private void addBuySellTransaction()
addFeesSectionsTransaction(pdfTransaction, type);
}

private void addBuySellPartialExecutionsTransaction()
{
DocumentType type = new DocumentType("Abrechnung: (Kauf|Verkauf) von Wertpapieren \\/ Zusammenfassung von Teilausf.hrungen");
this.addDocumentTyp(type);

Transaction<BuySellEntry> pdfTransaction = new Transaction<>();
pdfTransaction.subject(() -> {
BuySellEntry entry = new BuySellEntry();
entry.setType(PortfolioTransaction.Type.BUY);
return entry;
});

Block firstRelevantLine = new Block("^[\\d]{1,2}\\. .* [\\d]{4}$");
type.addBlock(firstRelevantLine);
firstRelevantLine.set(pdfTransaction);

pdfTransaction
// Is type --> "Verkauf" change from BUY to SELL
.section("type").optional()
.match("^Abrechnung: (?<type>(Kauf|Verkauf)) von Wertpapieren \\/ Zusammenfassung von Teilausf.hrungen$")
.assign((t, v) -> {
if (v.get("type").equals("Verkauf"))
t.setType(PortfolioTransaction.Type.SELL);
})

// 444 1234567 02 IVU TRAFFIC TECHNOLOGIES AG INH.AKT. O.N. 1/2
// WKN 744850 Nominal 120
// ISIN DE0007448508 Mischkurs (EUR) 14,80
.section("name", "wkn", "isin", "currency")
.match("^[\\d]{3} [\\d]+ [\\d]{2} (?<name>.*) 1\\/[\\d]{1,2}$")
.match("^WKN (?<wkn>.*) Nominal [\\.,\\d]+$")
.match("^ISIN (?<isin>[\\w]{12}) Mischkurs \\((?<currency>[\\w]{3})\\) .*$")
.assign((t, v) -> t.setSecurity(getOrCreateSecurity(v)))

// WKN 744850 Nominal 120
.section("shares")
.match("^.* Nominal (?<shares>[\\.,\\d]+)$")
.assign((t, v) -> t.setShares(asShares(v.get("shares"))))

// 09:05 MEZ 1447743358 618 14,80 9.146,40 9.120,93
.section("time").optional()
.match("^(?<time>[\\d]{2}:[\\d]{2}) MEZ [\\d]+ [\\d]{3} [\\.,\\d]+ [\\.,\\d]+ [\\.,\\d]+$")
.assign((t, v) -> type.getCurrentContext().put("time", v.get("time")))

// Schlusstag 07.07.2022 Ordernummer 123545
.section("date")
.match("^Schlusstag (?<date>[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) .*$")
.assign((t, v) -> {
if (type.getCurrentContext().get("time") != null)
t.setDate(asDate(v.get("date"), type.getCurrentContext().get("time")));
else
t.setDate(asDate(v.get("date")));
})

// Gesamtbetrag
// EUR 9.613,77
.section("amount", "currency")
.find("Gesamtbetrag")
.match("^(?<currency>[\\w]{3}) (?<amount>[\\.,\\d]+)$")
.assign((t, v) -> {
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
})

.wrap(t -> {
// If we have multiple entries in the document, with
// fee and fee refunds, then the "noProvision" flag
// must be removed.
type.getCurrentContext().remove("noProvision");

return new BuySellEntryItem(t);
});

addTaxesSectionsTransaction(pdfTransaction, type);
addFeesSectionsTransaction(pdfTransaction, type);
}

private void addDividendeTransaction()
{
DocumentType type = new DocumentType("Dividendengutschrift|Ertragsgutschrift");
Expand Down Expand Up @@ -142,10 +219,14 @@ private void addDividendeTransaction()
.assign((t, v) -> t.setShares(asShares(v.get("shares"))))

// Gutschrift mit Wert 15.12.2014 64,88 EUR
.section("date", "amount", "currency")
.section("date")
.match("^Gutschrift mit Wert (?<date>[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) .*$")
.assign((t, v) -> t.setDateTime(asDate(v.get("date"))))

// Gutschrift mit Wert 15.12.2014 64,88 EUR
.section("amount", "currency")
.match("^Gutschrift mit Wert (?<date>[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) (?<amount>[\\.,\\d]+) (?<currency>[\\w]{3})$")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not need the (?<date>....) named group here anymore, do we?

.assign((t, v) -> {
t.setDateTime(asDate(v.get("date")));
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
})
Expand All @@ -160,7 +241,7 @@ private void addDividendeTransaction()

Money gross = Money.of(asCurrencyCode(v.get("currency")), asAmount(v.get("gross")));
Money fxGross = Money.of(asCurrencyCode(v.get("fxCurrency")), asAmount(v.get("fxGross")));

checkAndSetGrossUnit(gross, fxGross, t, type);
})

Expand Down