Skip to content

Commit

Permalink
Modify WIR Bank PDF-Importer to support VIAC Invest transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
gh-nw-pp committed Feb 4, 2025
1 parent 5b9b2a1 commit 6e0add7
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
PDFBox Version: 3.0.3
Portfolio Performance Version: 0.74.1.qualifier
System: win32 | x86_64 | 21.0.5+11-LTS | Eclipse Adoptium
-----------------------------------------
VIAC Invest AG
Strasse 1
1111 Stadt
E-Mail info@viac.ch
Telefon 0000 00 00 00
www.viac.ch
Vertrag 1.111.111.111
Portfolio 1.111.111.111.11
Herr
Vorname Nachname
Strasse 1
1111 Stadt
Stadt, 09.01.2025
Börsenabrechnung - Zeichnung VIAC Equity North America Sustainable
Wir haben für Sie folgenden Auftrag ausgeführt:
Order: Zeichnung
16.839 Anteile VIAC Equity North America Sustainable
ISIN: CH1336969030
Kurs: CHF 101.53
Betrag CHF 1'709.70
Verrechneter Betrag: Valuta 09.01.2025 CHF 1'709.70
S. E. & O.
Freundliche Grüsse
VIAC Invest AG
Anzeige ohne Unterschrift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
PDFBox Version: 3.0.3
Portfolio Performance Version: 0.74.1.qualifier
System: win32 | x86_64 | 21.0.5+11-LTS | Eclipse Adoptium
-----------------------------------------
VIAC Invest AG
Strasse 1
1111 Stadt
E-Mail info@viac.ch
Telefon 0000 00 00 00
www.viac.ch
Vertrag 1.111.111.111
Portfolio 1.111.111.111.11
Herr
Vorname Nachname
Strasse 1
1111 Stadt
Stadt, 16.01.2025
Börsenabrechnung - Rücknahme VIAC Equity North America Sustainable
Wir haben für Sie folgenden Auftrag ausgeführt:
Order: Rücknahme
0.181 Anteile VIAC Equity North America Sustainable
ISIN: CH1336969030
Kurs: CHF 99.82
Betrag CHF 18.10
Verrechneter Betrag: Valuta 16.01.2025 CHF 18.10
S. E. & O.
Freundliche Grüsse
VIAC Invest AG
Anzeige ohne Unterschrift
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,52 @@ public void testWertpapierKauf11WithSecurityInCHF()
}))));
}

@Test
public void testWertpapierKauf12()
{
Client client = new Client();

WirBankPDFExtractor extractor = new WirBankPDFExtractor(client);

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

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Kauf12_ViacInvest.txt"), errors);

assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, "CHF");

// check security
Security security = results.stream().filter(SecurityItem.class::isInstance).findFirst()
.orElseThrow(IllegalArgumentException::new).getSecurity();
assertThat(security.getIsin(), is("CH1336969030"));
assertNull(security.getWkn());
assertNull(security.getTickerSymbol());
assertThat(security.getName(), is("VIAC Equity North America Sustainable"));
assertThat(security.getCurrencyCode(), is("CHF"));

// 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.BUY));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY));

assertThat(entry.getPortfolioTransaction().getDateTime(), is(LocalDateTime.parse("2025-01-09T00:00")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(16.839)));
assertThat(entry.getSource(), is("Kauf12_ViacInvest.txt"));
assertNull(entry.getNote());

assertThat(entry.getPortfolioTransaction().getMonetaryAmount(),
is(Money.of("CHF", Values.Amount.factorize(1709.70))));
assertThat(entry.getPortfolioTransaction().getGrossValue(),
is(Money.of("CHF", Values.Amount.factorize(1709.70))));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX),
is(Money.of("CHF", Values.Amount.factorize(0.00))));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE),
is(Money.of("CHF", Values.Amount.factorize(0.00))));
}

@Test
public void testInterest01()
{
Expand Down Expand Up @@ -1983,6 +2029,36 @@ public void testWertpapierVerkauf04()
hasTaxes("CHF", 0.00), hasFees("CHF", 0.00))));
}

@Test
public void testWertpapierVerkauf05()
{
WirBankPDFExtractor extractor = new WirBankPDFExtractor(new Client());

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

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "Verkauf05_ViacInvest.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("CH1336969030"), hasWkn(null), hasTicker(null), //
hasName("VIAC Equity North America Sustainable"), //
hasCurrencyCode("CHF"))));

// check buy sell transaction
assertThat(results, hasItem(sale( //
hasDate("2025-01-16T00:00"), hasShares(0.181), //
hasSource("Verkauf05_ViacInvest.txt"), hasNote(null), //
hasAmount("CHF", 18.10), hasGrossValue("CHF", 18.10), //
hasTaxes("CHF", 0.00), hasFees("CHF", 0.00))));
}

@Test
public void testWertpapierVerkauf04WithSecurityInCHF()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public WirBankPDFExtractor(Client client)

addBankIdentifier("WIR Bank");
addBankIdentifier("Banque WIR");
addBankIdentifier("VIAC Invest AG");

addDepositTransaction();
addBuySellTransaction();
Expand Down Expand Up @@ -86,13 +87,13 @@ private void addDepositTransaction()
private void addBuySellTransaction()
{
DocumentType type = new DocumentType("(B.rsenabrechnung|Exchange Settlement|Op.ration de bourse) " //
+ "\\- (Kauf|Verkauf|Buy|Sell|Achat|Vente)");
+ "\\- (Kauf|Zeichnung|Verkauf|R.cknahme|Buy|Sell|Achat|Vente)");
this.addDocumentTyp(type);

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

Block firstRelevantLine = new Block("^(B.rsenabrechnung|Exchange Settlement|Op.ration de bourse) " //
+ "\\- (Kauf|Verkauf|Buy|Sell|Achat|Vente).*$");
+ "\\- (Kauf|Zeichnung|Verkauf|R.cknahme|Buy|Sell|Achat|Vente).*$");
type.addBlock(firstRelevantLine);
firstRelevantLine.set(pdfTransaction);

Expand All @@ -107,9 +108,10 @@ private void addBuySellTransaction()
// Is type --> "Verkauf" change from BUY to SELL
.section("type").optional() //
.match("^(B.rsenabrechnung|Exchange Settlement|Op.ration de bourse) " //
+ "\\- (?<type>(Kauf|Verkauf|Buy|Sell|Achat|Vente)).*$") //
+ "\\- (?<type>(Kauf|Zeichnung|Verkauf|R.cknahme|Buy|Sell|Achat|Vente)).*$") //
.assign((t, v) -> {
if ("Verkauf".equals(v.get("type")) //
|| "Rücknahme".equals(v.get("type")) //
|| "Sell".equals(v.get("type")) //
|| "Vente".equals(v.get("type")))
t.setType(PortfolioTransaction.Type.SELL);
Expand All @@ -122,7 +124,7 @@ private void addBuySellTransaction()
// Kurs: USD 262.51
// @formatter:on
.section("isin", "name", "currency") //
.find("(Order|Ordre): (Kauf|Verkauf|Buy|Sell|Achat|Vente)") //
.find("(Order|Ordre): (Kauf|Zeichnung|Verkauf|R.cknahme|Buy|Sell|Achat|Vente)") //
.match("^[\\.,\\d]+ (Anteile|Qty|Ant|units|Qt.|Quantit.|parts|actions)?(?<name>.*)$") //
.match("^ISIN: (?<isin>[A-Z]{2}[A-Z0-9]{9}[0-9])$") //
.match("^(Kurs|Price|Cours): (?<currency>[\\w]{3}) .*$") //
Expand All @@ -133,7 +135,7 @@ private void addBuySellTransaction()
// 0.027 units Swisscanto Pacific ex Japan
// @formatter:on
.section("shares") //
.find("(Order|Ordre): (Kauf|Verkauf|Buy|Sell|Achat|Vente)") //
.find("(Order|Ordre): (Kauf|Zeichnung|Verkauf|R.cknahme|Buy|Sell|Achat|Vente)") //
.match("^(?<shares>[\\.,\\d]+) (Anteile|Qty|Ant|units|Qt.|Quantit.|parts|actions)?(?<name>.*)$") //
.assign((t, v) -> t.setShares(asShares(v.get("shares"))))

Expand All @@ -148,7 +150,7 @@ private void addBuySellTransaction()
// Verrechneter Betrag: Valuta 05.07.2018 CHF 360.43
// @formatter:on
.section("amount", "currency") //
.match("^(Verrechneter Betrag: Valuta|Charged amount: Value date|Montant comptabilis.: Valeur) .* (?<currency>[\\w]{3}) (?<amount>[\\.,'\\d]+)$") //
.match("^(Verrechneter Betrag: Valuta|Charged amount: Value date|Montant comptabilis.: Valeur) .* (?<currency>[\\w]{3}) (?<amount>[\\.,'\\d]+).*$") //
.assign((t, v) -> {
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
Expand Down

0 comments on commit 6e0add7

Please sign in to comment.