Skip to content

Commit

Permalink
Modify Fidelity International PDF-Importer to support new transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
Nirus2000 authored and buchen committed Dec 30, 2023
1 parent 0de5dfc commit 5ca873f
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 31 deletions.
Expand Up @@ -38,6 +38,37 @@
@SuppressWarnings("nls")
public class FidelityInternationalPDFExtractorTest
{
@Test
public void testSecurityBuy01()
{
FidelityInternationalPDFExtractor extractor = new FidelityInternationalPDFExtractor(new Client());

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

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SecurityBuy01.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, "USD");

// check security
assertThat(results, hasItem(security( //
hasIsin(null), hasWkn("31620M106"), hasTicker("FIS"), //
hasName("FIDELITY NATL"), //
hasCurrencyCode("USD"))));

// check buy sell transaction
assertThat(results, hasItem(purchase( //
hasDate("2023-12-08T00:00"), hasShares(7.5146), //
hasSource("SecurityBuy01.txt"), //
hasNote("Ref. No. 23342-0D6SVL"), //
hasAmount("USD", 442.83), hasGrossValue("USD", 442.83), //
hasTaxes("USD", 0.00), hasFees("USD", 0.00))));
}

@Test
public void testSecuritySale01()
{
Expand Down Expand Up @@ -69,6 +100,37 @@ public void testSecuritySale01()
hasTaxes("USD", 0.00), hasFees("USD", 0.13))));
}

@Test
public void testSecuritySale02()
{
FidelityInternationalPDFExtractor extractor = new FidelityInternationalPDFExtractor(new Client());

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

List<Item> results = extractor.extract(PDFInputFile.loadTestCase(getClass(), "SecuritySale02.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, "USD");

// check security
assertThat(results, hasItem(security( //
hasIsin(null), hasWkn("31620M106"), hasTicker("FIS"), //
hasName("FIDELITY NATL"), //
hasCurrencyCode("USD"))));

// check buy sell transaction
assertThat(results, hasItem(sale( //
hasDate("2022-07-19T00:00"), hasShares(30), //
hasSource("SecuritySale02.txt"), //
hasNote("Ref. No. 33107-zz91lf"), //
hasAmount("USD", 2887.43), hasGrossValue("USD", 2887.50), //
hasTaxes("USD", 0.00), hasFees("USD", 0.07))));
}

@Test
public void testTradeConfirmation01()
{
Expand Down
@@ -0,0 +1,38 @@
PDFBox Version: 1.8.17
Portfolio Performance Version: 0.66.2
-----------------------------------------
FIDELITY NATIONAL INFORMATION
SERVICES
PARTICIPANT NO.
U98299884
90035485
NIK HEMMERYCKX
XjlaqpRajgteel 88 FIDELITY STOCK PLAN SERVICES, LLC
ANTWERPEN P.O. BOX 770001
BELGIUM 2000 CINCINNATI, OH 45277-0003
TELEPHONE NUMBER:(800) 544-0275
REF # 23342-0D6SVL
CUSTOMER NO. PARTICIPANT ID. TYPE REG.REP. TRADE DATE SETTLEMENT DATE TRANS NO. CUSIP NO. ORIG.
U98299884 1 000 12-08-23 12-12-23 0D6SVL 31620M106
Confirmation of purchase made through your
FIS ESPP on DEC/08/2023. PURCHASE INFORMATION
Offering period: JAN/01/2023 - DEC/31/2023 Market Value at Purchase¹ $442.83
Accumulated Contributions* $442.83
YOU PURCHASED 7.5146 AT $58.9290 PURCHASE PRICE Gain² $0.00
SECURITY DESCRIPTION SYMBOL: FIS EXPLANATION OF PROCEEDS
FIDELITY NATL
The shares you have acquired are subject to a "Restriction Period" in accordance with Total Gain $0.00
your company's stock plan rules. Please see your plan documents for more
information. Provided below are the dates for when the restriction on these shares will
be removed. Share Proceeds** 7.5146
Sale Availability: 06/05/2024
Transfer Availability: 06/05/2024
PLEASE RETAIN THIS STATEMENT FOR YOUR RECORDS
* Accumulated Contributions are the amount of money contributed to your Plan that is
used toward the purchase of company stock.
** Shares will be held by Fidelity Stock Plan Services on your behalf in the SPS
Participant Trust.
¹ Market Value is determined under your Plan rules.
² Please consult your tax advisor regarding tax treatment in your jurisdiction.
PAGE 1 OF 1 Recordkeeping and administrative services for your company's equity compensation plans are
provided by your company and its service providers.
@@ -0,0 +1,29 @@
PDFBox Version: 1.8.17
Portfolio Performance Version: 0.66.2
-----------------------------------------
PARTICIPANT NO.
U98299884
90017770
NIK HEMMERYCKX
flBJHBJAntgwOx 84
ANTWERPEN
BELGIUM 2000 FIDELITY STOCK PLAN SERVICES, LLC
P.O. BOX 770001
CINCINNATI, OH 45277-0003
TELEPHONE NUMBER:(800) 544-0275
REF # 33107-zz91lf
CUSTOMER NO. PARTICIPANT ID. TYPE REG.REP. TRADE DATE SETTLEMENT DATE TRANS NO. CUSIP NO. ORIG.
U98299884 1 WI# 07-19-22 07-21-22 KS51HX 31620M106
YOU SOLD 30 AT 96.2500
EXPLANATION OF PROCEEDS
SECURITY DESCRIPTION SYMBOL: FIS Sale Proceeds $2,887.50
FIDELITY NATL
DETAILS: Total Fees $0.07
Sale Date: JUL/19/2022
Proceeds Available: JUL/21/2022
Plan Type: COMPANY STOCK PLAN
Net Cash Proceeds¹ -$2,887.43
PLEASE RETAIN THIS STATEMENT FOR YOUR RECORDS
¹ Your proceeds will be held by Fidelity in your trust. Please contact Fidelity Stock Plan Services to request a distribution.
PAGE 1 OF 1 Recordkeeping and administrative services for your company's equity compensation plans are
provided by your company and its service providers.
Expand Up @@ -43,7 +43,7 @@ public String getLabel()

private void addBuySellTransaction()
{
DocumentType type = new DocumentType("YOU SOLD");
DocumentType type = new DocumentType("YOU (PURCHASED|SOLD)");
this.addDocumentTyp(type);

Transaction<BuySellEntry> pdfTransaction = new Transaction<>();
Expand All @@ -62,52 +62,91 @@ private void addBuySellTransaction()

// Is type --> "SOLD" change from BUY to SELL
.section("type").optional() //
.match("^YOU (?<type>SOLD) [\\.,\\d]+.*$") //
.match("^YOU (?<type>(PURCHASED|SOLD)) [\\.,\\d]+.*$") //
.assign((t, v) -> {
if ("SOLD".equals(v.get("type")))
t.setType(PortfolioTransaction.Type.SELL);
})

// @formatter:off
// I00123456 1 WI# 12-12-23 12-14-23 K9T1Q9 11135F101
// SECURITY DESCRIPTION SYMBOL: AAPL Sale Proceeds $2,423.54
// APPLE INC
// @formatter:off
.section("wkn", "tickerSymbol", "currency", "name") //
.match("^.* [\\d]{2}\\-[\\d]{2}\\-[\\d]{2} [\\d]{2}\\-[\\d]{2}\\-[\\d]{2} [\\w]+ (?<wkn>[A-Z0-9]+)$") //
.match("^SECURITY DESCRIPTION SYMBOL: (?<tickerSymbol>[A-Z]{2,}) .* (?<currency>\\p{Sc})[\\.,\\d]+$") //
.match("^(?<name>.*)$") //
.assign((t, v) -> t.setSecurity(getOrCreateSecurity(v)))
.oneOf( //
// @formatter:off
// U98299884 1 000 12-08-23 12-12-23 0D6SVL 31620M106
// YOU PURCHASED 7.5146 AT $58.9290 PURCHASE PRICE Gain² $0.00
// SECURITY DESCRIPTION SYMBOL: FIS EXPLANATION OF PROCEEDS
// FIDELITY NATL
// @formatter:on
section -> section //
.attributes("wkn", "tickerSymbol", "currency", "name") //
.match("^.* [\\d]{2}\\-[\\d]{2}\\-[\\d]{2} [\\d]{2}\\-[\\d]{2}\\-[\\d]{2} [\\w]+ (?<wkn>[A-Z0-9]+)$") //
.match("^YOU PURCHASED [\\.,\\d]+ AT (?<currency>\\p{Sc})[\\.,\\d]+.*$") //
.match("^SECURITY DESCRIPTION SYMBOL: (?<tickerSymbol>[A-Z]{2,}) .*$") //
.match("^(?<name>.*)$") //
.assign((t, v) -> t.setSecurity(getOrCreateSecurity(v))),
// @formatter:off
// I00123456 1 WI# 12-12-23 12-14-23 K9T1Q9 11135F101
// YOU SOLD 14 AT 173.1100
// SECURITY DESCRIPTION SYMBOL: AAPL Sale Proceeds $2,423.54
// APPLE INC
// @formatter:on
section -> section //
.attributes("wkn", "tickerSymbol", "currency", "name") //
.match("^.* [\\d]{2}\\-[\\d]{2}\\-[\\d]{2} [\\d]{2}\\-[\\d]{2}\\-[\\d]{2} [\\w]+ (?<wkn>[A-Z0-9]+)$") //
.match("^YOU SOLD [\\.,\\d]+.*$") //
.match("^SECURITY DESCRIPTION SYMBOL: (?<tickerSymbol>[A-Z]{2,}) .* (?<currency>\\p{Sc})[\\.,\\d]+$") //
.match("^(?<name>.*)$") //
.assign((t, v) -> t.setSecurity(getOrCreateSecurity(v))))

// @formatter:off
// Sale Date: DEC/12/2023
// @formatter:on
.section("date") //
.match("^Sale Date: (?<date>[\\w]{3}\\/[\\d]{2}\\/[\\d]{4})$") //
.assign((t, v) -> t.setDate(asDate(v.get("date"))))
.oneOf( //
// @formatter:off
// Sale Date: DEC/12/2023
// @formatter:on
section -> section //
.attributes("date") //
.match("^Sale Date: (?<date>[\\w]{3}\\/[\\d]{2}\\/[\\d]{4})$") //
.assign((t, v) -> t.setDate(asDate(v.get("date")))),
// @formatter:off
// FIS ESPP on DEC/08/2023. PURCHASE INFORMATION
// @formatter:on
section -> section //
.attributes("date") //
.match("^.* (?<date>[\\w]{3}\\/[\\d]{2}\\/[\\d]{4})\\. PURCHASE INFORMATION$") //
.assign((t, v) -> t.setDate(asDate(v.get("date")))))

// @formatter:off
// YOU SOLD 14 AT 173.1100
// YOU PURCHASED 7.5146 AT $58.9290 PURCHASE PRICE Gain² $0.00
// @formatter:on
.section("shares") //
.match("^YOU SOLD (?<shares>[\\.,\\d]+).*$") //
.match("^YOU (PURCHASED|SOLD) (?<shares>[\\.,\\d]+).*$") //
.assign((t, v) -> t.setShares(asShares(v.get("shares"))))

// @formatter:off
// Net Cash Proceeds¹ -$2,423.41
// @formatter:on
.section("currency", "amount") //
.match("^Net Cash Proceeds.* \\-(?<currency>\\p{Sc})(?<amount>[\\.,\\d]+)$") //
.assign((t, v) -> {
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
t.setAmount(asAmount(v.get("amount")));
})
.oneOf( //
// @formatter:off
// Net Cash Proceeds¹ -$2,423.41
// @formatter:on
section -> section //
.attributes("currency", "amount") //
.match("^Net Cash Proceeds.* \\-(?<currency>\\p{Sc})(?<amount>[\\.,\\d]+)$") //
.assign((t, v) -> {
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
t.setAmount(asAmount(v.get("amount")));
}),
// @formatter:off
// Accumulated Contributions* $442.83
// @formatter:on
section -> section //
.attributes("currency", "amount") //
.match("^Accumulated Contributions.* (?<currency>\\p{Sc})(?<amount>[\\.,\\d]+)$") //
.assign((t, v) -> {
t.setCurrencyCode(asCurrencyCode(v.get("currency")));
t.setAmount(asAmount(v.get("amount")));
}))

// @formatter:off
// REF # 23346-K9T1Q9
// @formatter:on
.section("note").optional() //
.match("^REF # (?<note>[A-Z0-9]+\\-[A-Z0-9]+)$") //
.match("^REF # (?<note>[\\w]+\\-[\\w]+)$") //
.assign((t, v) -> t.setNote("Ref. No. " + v.get("note")))

.wrap(BuySellEntryItem::new);
Expand Down Expand Up @@ -227,14 +266,14 @@ private void addSummaryStatementBuySellTransaction()
// 20123-1XXXXX 1* WK# 01-04-21 01-06-21 46428Q109 20123-XXXXX
// @formatter:on
.section("note").optional() //
.match("^(?<note>[A-Z0-9]+\\-[A-Z0-9]+) .*$") //
.match("^(?<note>[\\w]+\\-[\\w]+) .*$") //
.assign((t, v) -> t.setNote("Ref. No. " + v.get("note")))

// @formatter:off
// 20123-1XXXXX 1* WK# 01-04-21 01-06-21 46428Q109 20123-XXXXX
// @formatter:on
.section("note").optional() //
.match("^[A-Z0-9]+\\-[A-Z0-9]+ .* (?<note>[A-Z0-9]+\\-[A-Z0-9]+)$") //
.match("^[\\w]+\\-[\\w]+ .* (?<note>[\\w]+\\-[\\w]+)$") //
.assign((t, v) -> t.setNote(concatenate(t.getNote(), v.get("note"), " | Ord. No. ")))

.wrap(BuySellEntryItem::new);
Expand Down

0 comments on commit 5ca873f

Please sign in to comment.