Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Hypothekarbank Lenzburg AG PDF-Importer #3902

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,70 @@
package name.abuchen.portfolio.datatransfer.pdf.hypothekarbanklenzburgag;

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.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.security;
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 java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import name.abuchen.portfolio.datatransfer.Extractor.Item;
import name.abuchen.portfolio.datatransfer.actions.AssertImportActions;
import name.abuchen.portfolio.datatransfer.pdf.HypothekarbankLenzburgAGPDFExtractor;
import name.abuchen.portfolio.datatransfer.pdf.PDFInputFile;
import name.abuchen.portfolio.model.Client;

@SuppressWarnings("nls")
public class HypothekarbankLenzburgAGPDFExtractorTest
{
@Test
public void testWertpapierKauf01()
{
HypothekarbankLenzburgAGPDFExtractor extractor = new HypothekarbankLenzburgAGPDFExtractor(new Client());

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

List<Item> 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, "CHF");

// check security
assertThat(results, hasItem(security( //
hasIsin("IE000716YHJ7"), hasWkn("125615212"), hasTicker(null), //
hasName("Accum Shs USD Inve FTSE All"), //
hasCurrencyCode("CHF"))));

// check buy sell transaction
assertThat(results, hasItem(purchase( //
hasDate("2024-03-14T00:00"), hasShares(720), //
hasSource("Kauf01.txt"), //
hasNote("Transaktion 61327806-0002"), //
hasAmount("CHF", 3974.14), hasGrossValue("CHF", 3948.48), //
hasTaxes("CHF", 5.92), hasFees("CHF", 19.74))));
}
}
@@ -0,0 +1,31 @@
PDFBox Version: 1.8.17
Portfolio Performance Version: 0.68.2
-----------------------------------------
Hypothekarbank Lenzburg AG
Bahnhofstrasse 2 | 5600 Lenzburg 1
Telefon +41 62 885 11 11 | info@hbl.ch | www.hbl.ch
BC 8307 | HYPLCH22 | CHE-105.779.532 MWST
E-Post
Herr
Max Mustermann
Musterstrasse 1
1234 Musterdorf
Ihr Betreuerteam: Service Center / Tel. +41 43 508 03 76
Lenzburg, 14.03.2024 Seite 1 von 1
Börse / Kauf Portfolio 314.391.703
Transaktion 61327806-0002
Wir haben am 14.03.2024 an der BX Swiss für Sie gekauft
720 Accum Shs USD Inve FTSE All Depotstelle 3500
Valor: 125615212 / IE000716YHJ7
Menge 720 Kurs CHF 5.484 CHF 3'948.48
Eidg. Umsatzabgabe CHF 5.92
Eigene Kommission (NEON) CHF 19.74
Belastung 314.391.304 Valuta 18.03.2024 CHF 3'974.14
Neon Konto - neon
Die Titel buchen wir in Ihr Portfolio ein.
Dieser Auftrag erfolgte ohne Beratung durch die Bank.
Sofern für das gehandelte Finanzinstrument ein BIB vorhanden ist, wird Ihnen dieses auf unserer Internetseite unter
https://www.hbl.ch/de/private/anlegen/basisinformationsblatt/ zur Verfügung gestellt.
Freundliche Grüsse
Hypothekarbank Lenzburg AG
Anzeige ohne Unterschrift
@@ -0,0 +1,152 @@
package name.abuchen.portfolio.datatransfer.pdf;

import static name.abuchen.portfolio.util.TextUtil.trim;

import java.math.BigDecimal;

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.BuySellEntry;
import name.abuchen.portfolio.model.Client;
import name.abuchen.portfolio.model.PortfolioTransaction;
import name.abuchen.portfolio.money.Values;

/**
* @formatter:off
* @implNote Hypothekarbank Lenzburg AG
*
* @implSpec The Valorennumber number is the WKN number with 5 to 9 letters.
* @formatter:on
*/

@SuppressWarnings("nls")
public class HypothekarbankLenzburgAGPDFExtractor extends AbstractPDFExtractor
{
public HypothekarbankLenzburgAGPDFExtractor(Client client)
{
super(client);

addBankIdentifier("Hypothekarbank Lenzburg AG");

addBuySellTransaction();
}

@Override
public String getLabel()
{
return "Hypothekarbank Lenzburg AG";
}

private void addBuySellTransaction()
{
DocumentType type = new DocumentType("Wir haben am .* f.r Sie gekauft");
this.addDocumentTyp(type);

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

Block firstRelevantLine = new Block("^Transaktion .*$");
type.addBlock(firstRelevantLine);
firstRelevantLine.set(pdfTransaction);

pdfTransaction //

.subject(() -> {
BuySellEntry portfolioTransaction = new BuySellEntry();
portfolioTransaction.setType(PortfolioTransaction.Type.BUY);
return portfolioTransaction;
})

// @formatter:off
// Wir haben am 14.03.2024 an der BX Swiss für Sie gekauft
// 720 Accum Shs USD Inve FTSE All Depotstelle 3500
// Valor: 125615212 / IE000716YHJ7
// Menge 720 Kurs CHF 5.484 CHF 3'948.48
// @formatter:on
.section("name", "wkn", "isin", "currency") //
.find("Wir haben am .* f.r Sie gekauft") //)
.match("^.*[\\,'\\d]+ (?<name>.*) Depotstelle .*$") //
.match("^Valor: (?<wkn>[A-Z0-9]{5,9}) \\/ (?<isin>[A-Z]{2}[A-Z0-9]{9}[0-9])$")
.match("^Menge[\\s]{1,}[\\.'\\d]+ Kurs (?<currency>[\\w]{3})[\\s]{1,}[\\.'\\d]+[\\s]{1,}[\\w]{3}[\\s]{1,}[\\.'\\d]+$") //
.assign((t, v) -> t.setSecurity(getOrCreateSecurity(v)))

// @formatter:off
// Menge 720 Kurs CHF 5.484 CHF 3'948.48
// @formatter:on
.section("shares") //
.match("^Menge[\\s]{1,}(?<shares>[\\.'\\d]+) Kurs.*$") //
.assign((t, v) -> t.setShares(asShares(v.get("shares"))))

// @formatter:off
// Wir haben am 14.03.2024 an der BX Swiss für Sie gekauft
// @formatter:on
.section("date") //
.match("^Wir haben am (?<date>[\\d]{2}\\.[\\d]{2}\\.[\\d]{4}).*$") //
.assign((t, v) -> t.setDate(asDate(v.get("date"))))

// @formatter:off
// Belastung 314.391.304 Valuta 18.03.2024 CHF 3'974.14
// @formatter:on
.section("currency", "amount") //
.match("^Belastung .* (?<currency>[\\w]{3})[\\s]{1,}(?<amount>[\\.'\\d]+)$") //
.assign((t, v) -> {
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
t.setAmount(asAmount(v.get("amount")));
})

// @formatter:off
// Transaktion 61327806-0002
// @formatter:on
.section("note").optional() //
.match("^(?<note>Transaktion .*)$") //
.assign((t, v) -> t.setNote(trim(v.get("note"))))

.wrap(BuySellEntryItem::new);

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

private <T extends Transaction<?>> void addTaxesSectionsTransaction(T transaction, DocumentType type)
{
transaction //

// @formatter:off
// Eidg. Umsatzabgabe CHF 5.92
// @formatter:on
.section("currency", "tax").optional() //
.match("^Eidg\\. Umsatzabgabe (?<currency>[\\w]{3})[\\s]{1,}(?<tax>[\\.'\\d]+)$") //
.assign((t, v) -> processTaxEntries(t, v, type));
}

private <T extends Transaction<?>> void addFeesSectionsTransaction(T transaction, DocumentType type)
{
transaction //

// @formatter:off
// Eigene Kommission (NEON) CHF 19.74
// @formatter:on
.section("currency", "fee").optional() //
.match("^Eigene Kommission.* (?<currency>[\\w]{3})[\\s]{1,}(?<fee>[\\.'\\d]+)$") //
.assign((t, v) -> processFeeEntries(t, v, type));
}

@Override
protected long asAmount(String value)
{
return ExtractorUtils.convertToNumberLong(value, Values.Amount, "de", "CH");
}

@Override
protected long asShares(String value)
{
return ExtractorUtils.convertToNumberLong(value, Values.Share, "de", "CH");
}

@Override
protected BigDecimal asExchangeRate(String value)
{
return ExtractorUtils.convertToNumberBigDecimal(value, Values.Share, "de", "CH");
}
}
Expand Up @@ -67,6 +67,7 @@ public PDFImportAssistant(Client client, List<File> files)
extractors.add(new GladbacherBankAGPDFExtractor(client));
extractors.add(new HargreavesLansdownPlcExtractor(client));
extractors.add(new HelloBankPDFExtractor(client));
extractors.add(new HypothekarbankLenzburgAGPDFExtractor(client));
extractors.add(new INGDiBaPDFExtractor(client));
extractors.add(new JTDirektbankPDFExtractor(client));
extractors.add(new KBCGroupNVPDFExtractor(client));
Expand Down