Skip to content

Commit

Permalink
Improve Audi Bank PDF-Importer (#4561)
Browse files Browse the repository at this point in the history
Previously, taxes were posted separately for interest transactions on account statements.
These are now offset together and imported as one transaction.
  • Loading branch information
Nirus2000 authored Mar 2, 2025
1 parent 36ff673 commit 7137f59
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.deposit;
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasAmount;
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasDate;
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasFees;
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasGrossValue;
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.interest;
import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.removal;
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;
Expand All @@ -22,7 +24,6 @@

import org.junit.Test;

import name.abuchen.portfolio.Messages;
import name.abuchen.portfolio.datatransfer.Extractor.Item;
import name.abuchen.portfolio.datatransfer.actions.AssertImportActions;
import name.abuchen.portfolio.datatransfer.pdf.AudiBankPDFExtractor;
Expand All @@ -45,25 +46,17 @@ public void testKontoauszug01()
assertThat(errors, empty());
assertThat(countSecurities(results), is(0L));
assertThat(countBuySell(results), is(0L));
assertThat(countAccountTransactions(results), is(4L));
assertThat(results.size(), is(4));
assertThat(countAccountTransactions(results), is(1L));
assertThat(results.size(), is(1));
new AssertImportActions().check(results, CurrencyUnit.EUR);

// assert transaction
assertThat(results, hasItem(interest(hasDate("2021-12-25"), hasAmount("EUR", 0.83), //
hasSource("Kontoauszug01.txt"), hasNote(null))));

// assert transaction
assertThat(results, hasItem(taxes(hasDate("2021-12-25"), hasAmount("EUR", 0.01), //
hasSource("Kontoauszug01.txt"), hasNote("Solidaritätszuschlag"))));

// assert transaction
assertThat(results, hasItem(taxes(hasDate("2021-12-25"), hasAmount("EUR", 0.01), //
hasSource("Kontoauszug01.txt"), hasNote("Kirchensteuer"))));

// assert transaction
assertThat(results, hasItem(taxes(hasDate("2021-12-25"), hasAmount("EUR", 0.20), //
hasSource("Kontoauszug01.txt"), hasNote("Abgeltungsteuer"))));
assertThat(results, hasItem(interest( //
hasDate("2021-12-25"), hasShares(0), //
hasSource("Kontoauszug01.txt"), //
hasNote(null), //
hasAmount("EUR", 0.61), hasGrossValue("EUR", 0.83), //
hasTaxes("EUR", (0.20 + 0.01 + 0.01)), hasFees("EUR", 0.00))));
}

@Test
Expand All @@ -78,8 +71,8 @@ public void testKontoauszug02()
assertThat(errors, empty());
assertThat(countSecurities(results), is(0L));
assertThat(countBuySell(results), is(0L));
assertThat(countAccountTransactions(results), is(7L));
assertThat(results.size(), is(7));
assertThat(countAccountTransactions(results), is(4L));
assertThat(results.size(), is(4));
new AssertImportActions().check(results, CurrencyUnit.EUR);

// assert transaction
Expand All @@ -95,24 +88,12 @@ public void testKontoauszug02()
hasSource("Kontoauszug02.txt"), hasNote(null))));

// assert transaction
assertThat(results, hasItem(interest(hasDate("2023-08-25"), hasAmount("EUR", 1.00), //
hasSource("Kontoauszug02.txt"), hasNote(null))));

// assert transaction
assertThat(results, hasItem(taxes(hasDate("2023-08-25"), hasAmount("EUR", 0.01), //
hasSource("Kontoauszug02.txt"), hasNote("Solidaritätszuschlag"))));

// check cancellation transaction
assertThat(results, hasItem(withFailureMessage( //
Messages.MsgErrorTransactionTypeNotSupported, //
taxes( //
hasDate("2023-08-25"), hasAmount("EUR", 0.00), //
hasSource("Kontoauszug02.txt"), hasNote("Kirchensteuer")))));

// assert transaction
assertThat(results, hasItem(taxes(hasDate("2023-08-25"), hasAmount("EUR", 0.25), //
hasSource("Kontoauszug02.txt"), hasNote("Abgeltungsteuer"))));

assertThat(results, hasItem(interest( //
hasDate("2023-08-25"), hasShares(0), //
hasSource("Kontoauszug02.txt"), //
hasNote(null), //
hasAmount("EUR", 0.74), hasGrossValue("EUR", 1.00), //
hasTaxes("EUR", (0.25 + 0.00 + 0.01)), hasFees("EUR", 0.00))));
}

@Test
Expand All @@ -127,8 +108,8 @@ public void testKontoauszug03()
assertThat(errors, empty());
assertThat(countSecurities(results), is(0L));
assertThat(countBuySell(results), is(0L));
assertThat(countAccountTransactions(results), is(6L));
assertThat(results.size(), is(6));
assertThat(countAccountTransactions(results), is(3L));
assertThat(results.size(), is(3));
new AssertImportActions().check(results, CurrencyUnit.EUR);

// assert transaction
Expand All @@ -140,20 +121,11 @@ public void testKontoauszug03()
hasSource("Kontoauszug03.txt"), hasNote(null))));

// assert transaction
assertThat(results, hasItem(interest(hasDate("2022-03-25"), hasAmount("EUR", 1.13), //
hasSource("Kontoauszug03.txt"), hasNote(null))));

// assert transaction
assertThat(results, hasItem(taxes(hasDate("2022-03-25"), hasAmount("EUR", 0.01), //
hasSource("Kontoauszug03.txt"), hasNote("Solidaritätszuschlag"))));

// check cancellation transaction
assertThat(results, hasItem(taxes(hasDate("2022-03-25"), hasAmount("EUR", 0.02), //
hasSource("Kontoauszug03.txt"), hasNote("Kirchensteuer"))));

// assert transaction
assertThat(results, hasItem(taxes(hasDate("2022-03-25"), hasAmount("EUR", 0.27), //
hasSource("Kontoauszug03.txt"), hasNote("Abgeltungsteuer"))));

assertThat(results, hasItem(interest( //
hasDate("2022-03-25"), hasShares(0), //
hasSource("Kontoauszug03.txt"), //
hasNote(null), //
hasAmount("EUR", 0.83), hasGrossValue("EUR", 1.13), //
hasTaxes("EUR", (0.27 + 0.01 + 0.02)), hasFees("EUR", 0.00))));
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package name.abuchen.portfolio.datatransfer.pdf;

import name.abuchen.portfolio.Messages;
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.Client;
import name.abuchen.portfolio.model.Transaction.Unit;
import name.abuchen.portfolio.money.Money;

@SuppressWarnings("nls")
public class AudiBankPDFExtractor extends AbstractPDFExtractor
Expand Down Expand Up @@ -90,6 +91,9 @@ private void addAccountStatementTransaction()

// @formatter:off
// 1 23.12.2021 Habenzinsen 25.12.2021 0,83
// 2 23.12.2021 Solidaritätszuschlag 25.12.2021 -0,01
// 3 23.12.2021 Kirchensteuer 25.12.2021 -0,01
// 4 23.12.2021 Abgeltungsteuer 25.12.2021 -0,20
// @formatter:on
Block interestBlock = new Block("^[\\d]+ [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} Habenzinsen [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} [\\.,\\d]+$");
type.addBlock(interestBlock);
Expand All @@ -110,40 +114,36 @@ private void addAccountStatementTransaction()
t.setCurrencyCode(v.get("currency"));
})

.wrap(TransactionItem::new));

// @formatter:off
// 2 23.12.2021 Solidaritätszuschlag 25.12.2021 -0,01
// 3 23.12.2021 Kirchensteuer 25.12.2021 -0,01
// 4 23.12.2021 Abgeltungsteuer 25.12.2021 -0,20
// @formatter:on
Block taxesBlock = new Block("^[\\d]+ [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} (Solidarit.tszuschlag|Kirchensteuer|Abgeltungsteuer) [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} \\-[\\.,\\d]+$");
type.addBlock(taxesBlock);
taxesBlock.set(new Transaction<AccountTransaction>()
.section("tax").optional() //
.documentContext("currency") //
.match("^[\\d]+ [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} Abgeltungsteuer [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} \\-(?<tax>[\\.,\\d]+)$") //
.assign((t, v) -> {
Money tax = Money.of(asCurrencyCode(v.get("currency")), asAmount(v.get("tax")));
t.addUnit(new Unit(Unit.Type.TAX, tax));

.subject(() -> {
AccountTransaction accountTransaction = new AccountTransaction();
accountTransaction.setType(AccountTransaction.Type.TAXES);
return accountTransaction;
t.setMonetaryAmount(t.getMonetaryAmount().subtract(tax));
})

.section("note", "date", "amount") //
.section("tax").optional() //
.documentContext("currency") //
.match("^[\\d]+ [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} (?<note>(Solidarit.tszuschlag|Kirchensteuer|Abgeltungsteuer)) (?<date>[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}) \\-(?<amount>[\\.,\\d]+)$") //
.match("^[\\d]+ [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} Solidarit.tszuschlag [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} \\-(?<tax>[\\.,\\d]+)$") //
.assign((t, v) -> {
t.setDateTime(asDate(v.get("date")));
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(v.get("currency"));
t.setNote(v.get("note"));
Money tax = Money.of(asCurrencyCode(v.get("currency")), asAmount(v.get("tax")));
t.addUnit(new Unit(Unit.Type.TAX, tax));

t.setMonetaryAmount(t.getMonetaryAmount().subtract(tax));
})

.wrap((t, ctx) -> {
TransactionItem item = new TransactionItem(t);
.section("tax").optional() //
.documentContext("currency") //
.match("^[\\d]+ [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} Kirchensteuer [\\d]{2}\\.[\\d]{2}\\.[\\d]{4} \\-(?<tax>[\\.,\\d]+)$") //
.assign((t, v) -> {
Money tax = Money.of(asCurrencyCode(v.get("currency")), asAmount(v.get("tax")));
t.addUnit(new Unit(Unit.Type.TAX, tax));

if (t.getCurrencyCode() != null && t.getAmount() == 0)
item.setFailureMessage(Messages.MsgErrorTransactionTypeNotSupported);
t.setMonetaryAmount(t.getMonetaryAmount().subtract(tax));
})

return item;
}));
.wrap(TransactionItem::new));
}
}

0 comments on commit 7137f59

Please sign in to comment.