Skip to content

Commit

Permalink
Modify DADAT PDF-Importer to support new transaction (#4377)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nirus2000 authored Dec 1, 2024
1 parent edf190d commit b9083e5
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void testWertpapierKauf01()
assertThat(entry.getPortfolioTransaction().getDateTime(), is(LocalDateTime.parse("2021-02-17T20:49:54")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(3)));
assertThat(entry.getSource(), is("Kauf01.txt"));
assertThat(entry.getNote(), is("Auftrags-Nr.: 45247499-17.2.2021"));
assertThat(entry.getNote(), is("Auftrags-Nr.: 45247499"));

assertThat(entry.getPortfolioTransaction().getMonetaryAmount(),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(1800.00))));
Expand Down Expand Up @@ -2145,7 +2145,7 @@ public void testDividende01()
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2021-03-23T00:00")));
assertThat(transaction.getShares(), is(Values.Share.factorize(3)));
assertThat(transaction.getSource(), is("Dividende01.txt"));
assertNull(transaction.getNote());
assertThat(transaction.getNote(), is("R.-Nr.: 45970540"));

assertThat(transaction.getMonetaryAmount(),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(7.51))));
Expand Down Expand Up @@ -2188,7 +2188,7 @@ public void testDividende01WithSecurityInEUR()
assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2021-03-23T00:00")));
assertThat(transaction.getShares(), is(Values.Share.factorize(3)));
assertThat(transaction.getSource(), is("Dividende01.txt"));
assertNull(transaction.getNote());
assertThat(transaction.getNote(), is("R.-Nr.: 45970540"));

assertThat(transaction.getMonetaryAmount(),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(7.51))));
Expand Down Expand Up @@ -2230,9 +2230,9 @@ public void testDividende02()

// check dividends transaction
assertThat(results, hasItem(dividend( //
hasDate("2023-12-27T00:00"), hasShares(100), //
hasDate("2023-12-27T00:00"), hasShares(100.00), //
hasSource("Dividende02.txt"), //
hasNote(null), //
hasNote("R.-Nr.: 84052423"), //
hasAmount("EUR", 17.99), hasGrossValue("EUR", 24.82), //
hasForexGrossValue("USD", 27.51), //
hasTaxes("EUR", (4.13 + 3.44) / 1.1082), hasFees("EUR", 0.00))));
Expand Down Expand Up @@ -2262,9 +2262,9 @@ public void testDividende02WithSecurityInEUR()

// check dividends transaction
assertThat(results, hasItem(dividend( //
hasDate("2023-12-27T00:00"), hasShares(100), //
hasDate("2023-12-27T00:00"), hasShares(100.00), //
hasSource("Dividende02.txt"), //
hasNote(null), //
hasNote("R.-Nr.: 84052423"), //
hasAmount("EUR", 17.99), hasGrossValue("EUR", 24.82), //
hasTaxes("EUR", (4.13 + 3.44) / 1.1082), hasFees("EUR", 0.00), //
check(tx -> {
Expand Down Expand Up @@ -2300,7 +2300,7 @@ public void testDividende03()

// check dividends transaction
assertThat(results, hasItem(dividend( //
hasDate("2024-04-30T00:00"), hasShares(50), //
hasDate("2024-04-30T00:00"), hasShares(50.00), //
hasSource("Dividende03.txt"), //
hasNote(null), //
hasAmount("EUR", 32.99), hasGrossValue("EUR", 45.50), //
Expand Down Expand Up @@ -2332,7 +2332,7 @@ public void testDividende03WithSecurityInEUR()

// check dividends transaction
assertThat(results, hasItem(dividend( //
hasDate("2024-04-30T00:00"), hasShares(50), //
hasDate("2024-04-30T00:00"), hasShares(50.00), //
hasSource("Dividende03.txt"), //
hasNote(null), //
hasAmount("EUR", 32.99), hasGrossValue("EUR", 45.50), //
Expand All @@ -2345,4 +2345,74 @@ public void testDividende03WithSecurityInEUR()
assertThat(s, is(Status.OK_STATUS));
}))));
}

@Test
public void testDividende04()
{
DADATBankenhausPDFExtractor extractor = new DADATBankenhausPDFExtractor(new Client());

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

List<Item> 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
assertThat(results, hasItem(security( //
hasIsin("NO0003054108"), hasWkn(null), hasTicker(null), //
hasName("M o w i A S A Navne-Aksjer NK 7,50"), //
hasCurrencyCode("NOK"))));

// check dividends transaction
assertThat(results, hasItem(dividend( //
hasDate("2024-11-25T00:00"), hasShares(400.00), //
hasSource("Dividende04.txt"), //
hasNote("R.-Nr.: 92276651"), //
hasAmount("EUR", 32.34), hasGrossValue("EUR", 51.74), //
hasForexGrossValue("NOK", 600.05), //
hasTaxes("EUR", (150.00 + 75.04) / 11.5975), hasFees("EUR", 0.00))));
}

@Test
public void testDividende04WithSecurityInEUR()
{
Security security = new Security("M o w i A S A Navne-Aksjer NK 7,50", CurrencyUnit.EUR);
security.setIsin("NO0003054108");

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

DADATBankenhausPDFExtractor extractor = new DADATBankenhausPDFExtractor(client);

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

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Dividende04.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
assertThat(results, hasItem(dividend( //
hasDate("2024-11-25T00:00"), hasShares(400.00), //
hasSource("Dividende04.txt"), //
hasNote("R.-Nr.: 92276651"), //
hasAmount("EUR", 32.34), hasGrossValue("EUR", 51.74), //
hasTaxes("EUR", (150.00 + 75.04) / 11.5975), 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));
}))));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
PDFBox Version: 1.8.17
Portfolio Performance Version: 0.71.2
-----------------------------------------
Abrechnung Ereignis
92276651-25.11.2024
Depot-Nr.: Depotnummer
Name
01/5020
DADAT-Bank
Herrn
Name
Straße
PLZ Ort
Wir haben für Sie am 25.11.2024 unten angeführtes Geschäft abgerechnet:
Geschäftsart: Ertrag
400 Stk
Titel: NO0003054108 M o w i A S A
Navne-Aksjer NK 7,50
Dividende: 1,5 NOK
Verwahrart: WR
Positionsdaten: Loco: München
Zinsen/Dividenden: 600,-- NOK
Quellensteuer: -150,-- NOK
Auslands-KESt: -75,04 NOK
374,96 NOK
Devisenkurs: 11,5975 (22.11.2024) 32,34 EUR
Zu Gunsten IBAN IBAN 32,34 EUR
Valuta 25.11.2024
Extag: 15.11.2024
Record-Tag: 18.11.2024
QUSt pro Stück 25,00 %
Es wurde Auslands-KESt in der Höhe von +12,5% berücksichtigt.
Die KESt wird an das Finanzamt Wien 1/23 abgeführt.
Devisenkurs: 11,5975 (22.11.2024)
KESt-Neubestand mit Anschaffungskosten nach dem gleitenden
Durchschnittsverfahren § 27a Abs. 4 Zi 3 EStG 400 Stk
Ertrag: 51,74 EUR
25.11.2024 Seite 1
DVR 0060011 ,HG WIEN ,FN58248i, Irrtum vorbehalten! Dieser Beleg wird von der Bank
nicht unterschrieben!
01015 Doknr.: BSG0-045-0000000950
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

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;
Expand Down Expand Up @@ -147,7 +148,7 @@ private void addBuySellTransaction()
// Auftrags-Nr.: 45247499-17.2.2021
// @formatter:on
.section("note").optional() //
.match("^(?<note>Auftrags\\-Nr\\.: .*)$") //
.match("^(?<note>Auftrags\\-Nr\\.: [\\d]+)\\-[\\d]{1,2}\\.[\\d]{1,2}.\\d{4}$") //
.assign((t, v) -> t.setNote(trim(v.get("note"))))

.wrap(BuySellEntryItem::new);
Expand All @@ -158,12 +159,12 @@ private void addBuySellTransaction()

private void addDividendeTransaction()
{
DocumentType type = new DocumentType("Abrechnung Ereignis");
DocumentType type = new DocumentType("Gesch.ftsart: Ertrag");
this.addDocumentTyp(type);

Transaction<AccountTransaction> pdfTransaction = new Transaction<>();

Block firstRelevantLine = new Block("^Gesch.ftsart: Ertrag$");
Block firstRelevantLine = new Block("^Abrechnung Ereignis$");
type.addBlock(firstRelevantLine);
firstRelevantLine.set(pdfTransaction);

Expand Down Expand Up @@ -216,7 +217,7 @@ private void addDividendeTransaction()
})

// @formatter:off
// Devisenkurs: 1,077 (30.4.2024) 32,99 EUR
// Devisenkurs: 1,077 (30.4.2024) 32,99 EUR
// Ertrag: 45,50 EUR
// @formatter:on
.section("termCurrency", "exchangeRate", "baseCurrency", "gross").optional() //
Expand All @@ -233,6 +234,15 @@ private void addDividendeTransaction()
checkAndSetGrossUnit(gross, fxGross, t, type.getCurrentContext());
})

// @formatter:off
// 92276651-25.11.2024
// @formatter:on
.section("note").optional() //
.match("^(?<note>[\\d]+)\\-[\\d]{1,2}\\.[\\d]{1,2}.\\d{4}$") //
.assign((t, v) -> t.setNote("R.-Nr.: " + trim(v.get("note"))))

.conclude(ExtractorUtils.fixGrossValueA())

.wrap(TransactionItem::new);

addTaxesSectionsTransaction(pdfTransaction, type);
Expand Down Expand Up @@ -903,37 +913,38 @@ private <T extends Transaction<?>> void addTaxesSectionsTransaction(T transactio
// @formatter:off
// QUELLENSTEUER: -1,86 USD
// Quellensteuer: -4,13 USD
// Quellensteuer: -150,-- NOK
// @formatter:on
.section("withHoldingTax", "currency").optional() //
.match("^(?i).*QUELLENSTEUER:[\\s]{1,}\\-(?<withHoldingTax>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^(?i).*QUELLENSTEUER:[\\s]{1,}\\-(?<withHoldingTax>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processWithHoldingTaxEntries(t, v, "withHoldingTax", type))

// @formatter:off
// QUELLENSTEUER -15,60 USD Auslands-KESt -13,00 USD
// @formatter:on
.section("withHoldingTax", "currency").optional() //
.match("^(?i).*QUELLENSTEUER[\\s]{1,}\\-(?<withHoldingTax>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^(?i).*QUELLENSTEUER[\\s]{1,}\\-(?<withHoldingTax>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processWithHoldingTaxEntries(t, v, "withHoldingTax", type))

// @formatter:off
// Auslands-KESt: -1,54 USD
// @formatter:on
.section("tax", "currency").optional() //
.match("^(?i).*Auslands\\-KESt:[\\s]{1,}\\-(?<tax>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^(?i).*Auslands\\-KESt:[\\s]{1,}\\-(?<tax>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processTaxEntries(t, v, type))

// @formatter:off
// QUELLENSTEUER -3,77 USD Auslands-KESt -3,13 USD
// @formatter:on
.section("tax", "currency").optional() //
.match("^(?i).*Auslands\\-KESt[\\s]{1,}\\-(?<tax>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^(?i).*Auslands\\-KESt[\\s]{1,}\\-(?<tax>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processTaxEntries(t, v, type))

// @formatter:off
// KEST -140,27 USD Handelsspesen -5,07 USD
// @formatter:on
.section("tax", "currency").optional() //
.match("^(?i)KEST[\\s]{1,}\\-(?<tax>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^(?i)KEST[\\s]{1,}\\-(?<tax>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processTaxEntries(t, v, type));
}

Expand All @@ -952,35 +963,35 @@ private <T extends Transaction<?>> void addFeesSectionsTransaction(T transaction
// DADAT Handelsspesen -1,67 EUR
// @formatter:on
.section("fee", "currency").optional() //
.match("^DADAT Handelsspesen ([\\s]+)?\\-(?<fee>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^DADAT Handelsspesen ([\\s]+)?\\-(?<fee>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processFeeEntries(t, v, type))

// @formatter:off
// KEST -140,27 USD Handelsspesen -5,07 USD
// @formatter:on
.section("fee", "currency").optional() //
.match("^.* Handelsspesen ([\\s]+)?\\-(?<fee>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^.* Handelsspesen ([\\s]+)?\\-(?<fee>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processFeeEntries(t, v, type))

// @formatter:off
// Handelsspesen -3,66 EUR DADAT Handelsspesen -6,36 EUR
// @formatter:on
.section("fee", "currency").optional() //
.match("^Handelsspesen ([\\s]+)?\\-(?<fee>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^Handelsspesen ([\\s]+)?\\-(?<fee>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processFeeEntries(t, v, type))

// @formatter:off
// Clearing Gebühr -1,00 EUR
// @formatter:on
.section("fee", "currency").optional() //
.match("^Clearing Geb.hr ([\\s]+)?\\-(?<fee>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^Clearing Geb.hr ([\\s]+)?\\-(?<fee>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processFeeEntries(t, v, type))

// @formatter:off
// DADAT Handelsspesen -7,12 EUR Clearing Gebühr -1,00 EUR
// @formatter:on
.section("fee", "currency").optional() //
.match("^.* Clearing Geb.hr ([\\s]+)?\\-(?<fee>[\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.match("^.* Clearing Geb.hr ([\\s]+)?\\-(?<fee>[\\-\\.,\\d]+) (?<currency>[\\w]{3}).*$") //
.assign((t, v) -> processFeeEntries(t, v, type));
}
}

0 comments on commit b9083e5

Please sign in to comment.