Closed flywire closed 3 years ago
@Nirus2000 is there a guide how to make these Importers?
Hallo @flywire Wenn du die PDF-Importer meinst, gibt keinen direkte Anleitung für Importer. Jedoch versuchen wir einen Standard zu implementieren. Am besten schaust du dir hier die PDF-Importer an und hier die testcase zu den jeweiligen Importern.
Als Orientierung für einen einfachen Importer könntest du den Deutsche Bank anschauen mit den passenden TestCases. Für komplexere Importer den FinTech mit diesen TestCases. Die PDF-Importer und TestCases sollte, so den Standard entsprechen.
Grüße Alex
This is a start.
Detail for later: GGT is tax, a refund for business but not personal investors.
package name.abuchen.portfolio.datatransfer.pdf;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;
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.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 SelfWealthPDFExtractor extends AbstractPDFExtractor
{
public SelfWealthPDFExtractor(Client client)
{
super(client);
addBankIdentifier("SelfWealth"); //$NON-NLS-1$
addBankIdentifier("SelfWealth Limited ABN: 52 154 324 428 AFSL 421789 W: www.selfwealth.com.au E: support@selfwealth.com.au"); //$NON-NLS-1$
addBuySellTransaction();
}
@Override
public String getPDFAuthor()
{
return ""; //$NON-NLS-1$
}
@Override
public String getLabel()
{
return "SelfWealth Limited ABN: 52 154 324 428 AFSL 421789 W: www.selfwealth.com.au E: support@selfwealth.com.au"; //$NON-NLS-1$
}
private void addBuySellTransaction()
{
DocumentType type = new DocumentType("(Buy|Sell) Confirmation");
this.addDocumentTyp(type);
Transaction<BuySellEntry> pdfTransaction = new Transaction<>();
pdfTransaction.subject(() -> {
BuySellEntry entry = new BuySellEntry();
entry.setType(PortfolioTransaction.Type.BUY);
return entry;
});
Block firstRelevantLine = new Block("^(Buy|Sell) Confirmation$");
type.addBlock(firstRelevantLine);
firstRelevantLine.set(pdfTransaction);
pdfTransaction
// Is type --> "Sell" change from BUY to SELL
.section("type").optional()
.match("^(?<type>Sell) Confirmation$")
.assign((t, v) -> {
if (v.get("type").equals("Sell"))
{
t.setType(PortfolioTransaction.Type.SELL);
}
})
// JOHN DOE A/C Reference No: T20210701123456-1
.section("note")
.match(" Reference No: (?<note>.*)$")
.assign((t, v) -> {
t.setNote(asNote(v.get("note")));
})
// 1 LONG ROAD Trade Date: 1 Jul 2021
.section("date")
.match(" Settlement Date: (?<date>\\d+ \\D{3} \\d{4})$")
.assign((t, v) -> {
if (v.get("time") != null)
t.setDate(asDate(v.get("date"), v.get("time")));
else
t.setDate(asDate(v.get("date")));
})
// 25 UMAX BETA S&P500 YIELDMAX 12.40 $312.50 AUD
.section("shares", "symbol", "name", "quote", "amount", "currency")
.match("^(?<shares>[.,\\d]+) (?<symbol>[\\D]+)") "name", "quote" \\$(?<amount>[.,\\d]+) (?<currency>[\\w]{3})$")
.assign((t, v) -> {
t.setShares(asShares(v.get("shares")));
t.setSecurity(getOrCreateSecurity(v));
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
})
// Brokerage* $9.50 AUD
.section("brokerage_fee")
.match("^Brokerage Fee//* //$(?<brokerage_fee>.*) [\\w]{3}$")
// Adviser Fee* $0.00 AUD
.section("adviser_fee")
.match("^Adviser Fee//* //$(?<adviser_fee>.*)$")
fees = brokerage_fee + adviser_fee
.assign((t, v) -> {
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
// Net Value $322.00 AUD
.section("amount")
.match("^GST included in this invoice is //$(?<amount>.*) [\\w]{3}$")
.assign((t, v) -> {
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
// GST included in this invoice is $0.86
.section("gst")
.match("^GST included in this invoice is //$(?<gst>.*)$")
.assign((t, v) -> {
t.setAmount(asAmount(v.get("amount")));
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
.wrap(BuySellEntryItem::new);
addTaxesSectionsTransaction(pdfTransaction, type);
addFeesSectionsTransaction(pdfTransaction, type);
}
private <T extends Transaction<?>> void addTaxesSectionsTransaction(T transaction, DocumentType type)
{
transaction
// Kapitalertragsteuer (KESt) - 9,88 USD - 8,71 EUR
.section("tax", "currency").optional()
.match("^Kapitalertragsteuer \\(KESt\\) ([\\s]+)?- [.,\\d]+ [\\w]{3} - (?<tax>[.,\\d]+) (?<currency>[\\w]{3})$")
.assign((t, v) -> processTaxEntries(t, v, type))
}
private <T extends Transaction<?>> void addFeesSectionsTransaction(T transaction, DocumentType type)
{
transaction
// Provision EUR 7,90
// Provision EUR -7,90
.section("currency", "fee").optional()
.match("^Provision (?<currency>[\\w]{3}) ([-])?(?<fee>[.,\\d]+)$")
.assign((t, v) -> processFeeEntries(t, v, type))
}
private void processTaxEntries(Object t, Map<String, String> v, DocumentType type)
{
if (t instanceof name.abuchen.portfolio.model.Transaction)
{
Money tax = Money.of(asCurrencyCode(v.get("currency")), asAmount(v.get("tax")));
PDFExtractorUtils.checkAndSetTax(tax, (name.abuchen.portfolio.model.Transaction) t, type);
}
else
{
Money tax = Money.of(asCurrencyCode(v.get("currency")), asAmount(v.get("tax")));
PDFExtractorUtils.checkAndSetTax(tax, ((name.abuchen.portfolio.model.BuySellEntry) t).getPortfolioTransaction(), type);
}
}
private void processFeeEntries(Object t, Map<String, String> v, DocumentType type)
{
if (t instanceof name.abuchen.portfolio.model.Transaction)
{
Money fee = Money.of(asCurrencyCode(v.get("currency")), asAmount(v.get("fee")));
PDFExtractorUtils.checkAndSetFee(fee,
(name.abuchen.portfolio.model.Transaction) t, type);
}
else
{
Money fee = Money.of(asCurrencyCode(v.get("currency")), asAmount(v.get("fee")));
PDFExtractorUtils.checkAndSetFee(fee,
((name.abuchen.portfolio.model.BuySellEntry) t).getPortfolioTransaction(), type);
}
}
}
Hello @flywire sorry that I have answered you in german. For us it is better if you start a draft-request. Then we look at it together and show you where there are still changes should be made.
Is SelfWealth a bank or securities account? delete the second identifier
addBankIdentifier("SelfWealth"); //$NON-NLS-1$
addBankIdentifier("SelfWealth Limited ABN: 52 154 324 428 AFSL 421789 W: www.selfwealth.com.au E: support@selfwealth.com.au"); //$NON-NLS-1$
Change getLabel() to this...
public String getLabel()
{
return "SelfWealth"; //$NON-NLS-1$
}
For the structur in addBuySellTransaction or other transactions....
There is many other small thinks... so start in draft-request.
C ya Alex
Hello and welcome, Therefore, log in to the forum at https://forum.portfolio-performance.info/ and create a thread with the name "PDF-Importer SelfWealth"
For a PDF-Importer we need examples of buy, sell, dividend and so on.... post it there. You can see how this works in the video tutorial.
Video tutorial: Extract PDF documents for debugging
I don't think the words translate exactly so I'm misunderstanding something:
Neuen Github Issue Create with the text or post it here in the forum.
I assume translates to: create a new Github Issue or Post it in the forum.
https://github.com/buchen/portfolio/issues/2329#issuecomment-881902163
so start in draft-request
I assume means: new GitHub Pull Request
https://github.com/buchen/portfolio/pull/2340 has draft code, test files and tests.
While no PDF-Importer users can enter manually or follow https://forum.portfolio-performance.info/t/import-csv-file/17123
One transaction per file. What more can I say?
Line 4: Buy Line 6: JOHN DOE A/C Line 7: Trade Date: 1 Jul 2021 Line 11-12: Fields are space delineated except spaces in Security Description Quantity: 25 Security Code: UMAX Security Description: BETA S&P500 YIELDMAX Price +1: 12.40 Consideration: $312.50 Currency: AUD