-
Notifications
You must be signed in to change notification settings - Fork 616
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Scalable Capital importer (#4410)
Apparently, Scalable Capital is not using the Baader Bank anymore. From now on, there are two importers for Scalable: the Baader Bank one for older document, and the Scalable Capital one for newer documents.
- Loading branch information
Showing
4 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
...en.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/scalablecapital/Kauf01.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
PDFBox Version: 1.8.17 | ||
Portfolio Performance Version: 0.72.2 | ||
----------------------------------------- | ||
Scalable Capital GmbH • Seitzstraße 8e • 80538 München • Deutschland | ||
gMbdE BSBVSo | ||
PIUWUpOPvMUGNZ OXxLwz 66 | ||
80481 YHbanuVrhilpy Datum 12.12.2024 | ||
Deutschland Seite 1 / 1 | ||
Wertpapierabrechnung | ||
für Kundenauftrag | ||
Typ LIMIT Order SCALsin78vS5CYz | ||
Ausführung 12.12.2024 13:12:51 Geschäft 36581526 | ||
Ausführungsplatz EIX Lagerland Luxemburg | ||
Depot 1970027444 Verwahrart Wertpapierrechnung | ||
Wertpapierabrechnung | ||
Typ Wertpapier Anzahl Kurs Betrag | ||
Kauf Vngrd Fds-ESG Dv.As-Pc Al ETF 3,00 Stk. 6,168 EUR 18,50 EUR | ||
IE0008T6IUX0 | ||
Ordergebühren +0,99 EUR | ||
Total 19,49 EUR | ||
Der Betrag wird mit dem Verrechnungskonto DE168836967200035482353 (Valuta: 16.12.2024) verrechnet. | ||
Bitte überprüfen Sie die Informationen auf Richtigkeit und melden Sie etwaige Einwände unverzüglich bei uns. | ||
Verwenden Sie dafür den Menüpunkt Support im Kundenbereich. | ||
Scalable Capital GmbH HRB 217778 Geschäftsführer: Aufsichtsrat: Seite | ||
Seitzstraße 8e Amtsgericht München Erik Podzuweit, Florian Prucker Patrick Olson (Vorsitzender) | ||
80538 München USt.-Id. Nr.: DE300434774 Martin Krebs, Dirk Franzmeyer, Dirk | ||
Urmoneit 1 / 1 |
70 changes: 70 additions & 0 deletions
70
...e/abuchen/portfolio/datatransfer/pdf/scalablecapital/ScalableCapitalPDFExtractorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package name.abuchen.portfolio.datatransfer.pdf.scalablecapital; | ||
|
||
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.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.PDFInputFile; | ||
import name.abuchen.portfolio.datatransfer.pdf.ScalableCapitalPDFExtractor; | ||
import name.abuchen.portfolio.model.Client; | ||
import name.abuchen.portfolio.money.CurrencyUnit; | ||
|
||
@SuppressWarnings("nls") | ||
public class ScalableCapitalPDFExtractorTest | ||
{ | ||
@Test | ||
public void testKauf01() | ||
{ | ||
ScalableCapitalPDFExtractor extractor = new ScalableCapitalPDFExtractor(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, CurrencyUnit.EUR); | ||
|
||
// check security | ||
assertThat(results, hasItem(security( // | ||
hasIsin("IE0008T6IUX0"), // | ||
hasName("Vngrd Fds-ESG Dv.As-Pc Al ETF"), // | ||
hasCurrencyCode("EUR")))); | ||
|
||
// check dividends transaction | ||
assertThat(results, hasItem(purchase( // | ||
hasDate("2024-12-12T13:12:51"), hasShares(3), // | ||
hasSource("Kauf01.txt"), // | ||
hasNote(null), // | ||
hasAmount("EUR", 19.49), hasGrossValue("EUR", 18.50), // | ||
hasTaxes("EUR", 0.00), hasFees("EUR", 0.99)))); | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
...en.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/ScalableCapitalPDFExtractor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package name.abuchen.portfolio.datatransfer.pdf; | ||
|
||
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.model.Transaction.Unit; | ||
import name.abuchen.portfolio.money.Money; | ||
|
||
@SuppressWarnings("nls") | ||
public class ScalableCapitalPDFExtractor extends AbstractPDFExtractor | ||
{ | ||
public ScalableCapitalPDFExtractor(Client client) | ||
{ | ||
super(client); | ||
|
||
addBankIdentifier("Scalable Capital GmbH"); | ||
|
||
addPurchaseTransaction(); | ||
} | ||
|
||
@Override | ||
public String getLabel() | ||
{ | ||
return "Scalable Capital"; | ||
} | ||
|
||
private void addPurchaseTransaction() | ||
{ | ||
final DocumentType type = new DocumentType("Wertpapierabrechnung"); | ||
|
||
this.addDocumentTyp(type); | ||
|
||
Block purchase = new Block(".* Kundenauftrag.*"); | ||
type.addBlock(purchase); | ||
purchase.set(new Transaction<BuySellEntry>() | ||
|
||
.subject(() -> { | ||
BuySellEntry portfolioTransaction = new BuySellEntry(); | ||
portfolioTransaction.setType(PortfolioTransaction.Type.BUY); | ||
return portfolioTransaction; | ||
}) | ||
|
||
.section("name", "currency", "isin") // | ||
.find("Typ Wertpapier Anzahl Kurs Betrag") // | ||
.match("^Kauf (?<name>.*) " // | ||
+ "[.,\\d]+ Stk. " // | ||
+ "[.,\\d]+ [A-Z]{3} " // | ||
+ "[.,\\d]+ (?<currency>[A-Z]{3})") | ||
.match("^(?<isin>[A-Z]{2}[A-Z0-9]{9}[0-9])$") // | ||
.assign((t, v) -> t.setSecurity(getOrCreateSecurity(v))) | ||
|
||
.section("shares", "amount", "currency") // | ||
.find("Typ Wertpapier Anzahl Kurs Betrag") // | ||
.match("^Kauf .* " // | ||
+ "(?<shares>[.,\\d]+) Stk. " // | ||
+ "[.,\\d]+ [A-Z]{3} " // | ||
+ "(?<amount>[.,\\d]+) (?<currency>[A-Z]{3})") | ||
.assign((t, v) -> { | ||
t.setCurrencyCode(asCurrencyCode(v.get("currency"))); | ||
t.setAmount(asAmount(v.get("amount"))); | ||
t.setShares(asShares(v.get("shares"))); | ||
}) | ||
|
||
.section("date", "time") // | ||
.match("^Ausführung (?<date>[\\d]{2}\\.[\\w]{2}\\.[\\d]{4}) " // | ||
+ "(?<time>[\\d]{2}:[\\d]{2}:[\\d]{2}) .*$") | ||
.assign((t, v) -> t.setDate(asDate(v.get("date"), v.get("time")))) | ||
|
||
.section("fee", "currency") // | ||
.optional() // | ||
.match("^Ordergebühren \\+(?<fee>[.,\\d]+) (?<currency>[A-Z]{3})$").assign((t, v) -> { | ||
var currency = asCurrencyCode(v.get("currency")); | ||
var fee = asAmount(v.get("fee")); | ||
var tx = t.getPortfolioTransaction(); | ||
|
||
tx.addUnit(new Unit(Unit.Type.FEE, Money.of(currency, fee))); | ||
t.setAmount(tx.getAmount() + fee); | ||
}) | ||
|
||
.wrap(e -> e.getPortfolioTransaction().getSecurity() == null ? null : new BuySellEntryItem(e))); | ||
} | ||
|
||
} |