Skip to content

Commit 9e35bd6

Browse files
authored
Multiple converter fixes (#303)
1 parent e5c550a commit 9e35bd6

10 files changed

Lines changed: 92 additions & 60 deletions

GitVersion.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
next-version: 0.34.0
1+
next-version: 0.34.1
22
assembly-informational-format: "{NuGetVersion}"
33
mode: ContinuousDeployment
44
branches:

package-lock.json

Lines changed: 7 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/bux-export.csv

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
Transaction Time (CET),Transaction Category,Transaction Type,Asset Id,Asset Name,Asset Currency,Transaction Currency,Currency Pair,Exchange Rate,Transaction Amount,Trade Amount,Trade Price,Trade Quantity,Cash Balance Amount,Profit And Loss Amount,Profit And Loss Currency
2-
2020-11-18 12:15:23.606000,deposits,Sepa Deposit,,,,EUR,,,500,,,,500,,
3-
2020-11-18 13:02:54.696000,deposits,Sepa Deposit,,,,EUR,,,100,,,,600.03,,
4-
2023-03-21 13:37:29.383000,trades,Buy Trade,NL0011821202,ING,EUR,EUR,EUREUR,1,-542.92,542.92,11.08,49,48.49,,
5-
2023-03-21 13:37:29.384000,fees,Trading Fee,NL0011821202,ING,,EUR,,,-1.5,,,,46.99,,
6-
2023-03-21 13:37:29.384000,trades,Buy Trade,NL0011821202,ING,EUR,EUR,EUREUR,1,-7.08,7.0800092,11.08,0.638989,39.91,,
7-
2023-05-02 11:07:12.872000,fees,Subscription Fee,,,,EUR,,,-2.99,,,,36.92,,
8-
2023-05-05 11:38:06.646000,dividends,Cash Dividend,NL0011821202,ING,EUR,EUR,EUREUR,1,16.4,,,,53.32,,
9-
2023-06-01 18:51:19.620000,fees,Subscription Fee,,,,EUR,,,-2.99,,,,50.33,,
10-
2023-07-01 12:32:03.013000,fees,Subscription Fee,,,,EUR,,,-2.99,,,,47.34,,
11-
2023-07-09 10:25:51.533000,interest,Interest Payment,,,,EUR,,,0.23,,,,47.57,,
12-
2023-08-01 16:19:45.363000,fees,Subscription Fee,,,,EUR,,,-2.99,,,,44.58,,
13-
2023-08-14 16:37:01.245000,dividends,Cash Dividend,NL0011821202,ING,EUR,EUR,EUREUR,1,14.76,,,,59.34,,
14-
2023-09-01 18:28:48.386000,fees,Subscription Fee,,,,EUR,,,-2.99,,,,56.35,,
15-
2023-10-01 16:20:38.540000,fees,Subscription Fee,,,,EUR,,,-2.99,,,,53.36,,
16-
2023-10-05 08:10:02.073000,interest,Interest Payment,,,,EUR,,,0.34,,,,53.7,,
17-
2023-11-05 07:05:37.311000,interest,Interest Payment,,,,EUR,,,0.11,,,,50.82,,
18-
2024-01-19 17:15:46.543000,deposits,Sepa Deposit,,,,EUR,,,10,,,,55.07,,
19-
2024-05-14 13:57:08.427000,withdrawals,Sepa Withdrawal,,,,EUR,,,-1200,,,,1293.6,,
20-
2023-03-21 13:37:29.384000,trades,Sell Trade,NL0011821202,ING,EUR,EUR,EUREUR,1,-7.08,7.0800092,11.08,0.638989,39.91,,
21-
2025-06-11 16:45:18.652000,trades,Buy Trade,US3755581036,Gilead Sciences,USD,EUR,EURUSD,1.14547,-10.0,11.45475312,109.96,0.104172,150.5,,
1+
Transaction Time (CET),Transaction Category,Transaction Type,Transfer Type,Transaction Amount,Transaction Currency,Cash Balance Amount,Asset Id,Asset Name,Asset Quantity,Asset Price,Asset Currency,Currency Pair,Exchange Rate,Profit And Loss Amount,Profit And Loss Currency,Dividend Currency,Dividend Gross Amount,Dividend Net Amount,Dividend Tax Amount,Transaction Description
2+
2020-11-18 12:15:23.606000,deposits,Sepa Deposit,,,500,EUR,500,,,,,,,,,,,,,
3+
2020-11-18 13:02:54.696000,deposits,Sepa Deposit,,,100,EUR,600.03,,,,,,,,,,,,,
4+
2023-03-21 13:37:29.383000,trades,Buy Trade,,-542.92,EUR,48.49,NL0011821202,ING,49,11.08,EUR,,,,,,,,,Transaction Amount: 542.92
5+
2023-03-21 13:37:29.384000,fees,Trading Fee,,-1.5,EUR,46.99,NL0011821202,ING,,,,,,,,,,,,
6+
2023-03-21 13:37:29.384000,trades,Buy Trade,,-7.08,EUR,39.91,NL0011821202,ING,0.638989,11.08,EUR,,,,,,,,,Transaction Amount: 7.0800092
7+
2023-05-02 11:07:12.872000,fees,Subscription Fee,,-2.99,EUR,36.92,,,,,,,,,,,,,,
8+
2023-05-05 11:38:06.646000,dividends,Cash Dividend,,16.4,EUR,53.32,NL0011821202,ING,,,,,,,,,,,,
9+
2023-06-01 18:51:19.620000,fees,Subscription Fee,,-2.99,EUR,50.33,,,,,,,,,,,,,,
10+
2023-07-01 12:32:03.013000,fees,Subscription Fee,,-2.99,EUR,47.34,,,,,,,,,,,,,,
11+
2023-07-09 10:25:51.533000,interest,Interest Payment,,0.23,EUR,47.57,,,,,,,,,,,,,,
12+
2023-08-01 16:19:45.363000,fees,Subscription Fee,,-2.99,EUR,44.58,,,,,,,,,,,,,,
13+
2023-08-14 16:37:01.245000,dividends,Cash Dividend,,14.76,EUR,59.34,NL0011821202,ING,,,,,,,,,,,,
14+
2023-09-01 18:28:48.386000,fees,Subscription Fee,,-2.99,EUR,56.35,,,,,,,,,,,,,,
15+
2023-10-01 16:20:38.540000,fees,Subscription Fee,,-2.99,EUR,53.36,,,,,,,,,,,,,,
16+
2023-10-05 08:10:02.073000,interest,Interest Payment,,0.34,EUR,53.7,,,,,,,,,,,,,,
17+
2023-11-05 07:05:37.311000,interest,Interest Payment,,0.11,EUR,50.82,,,,,,,,,,,,,,
18+
2024-01-19 17:15:46.543000,deposits,Sepa Deposit,,10,EUR,55.07,,,,,,,,,,,,,,
19+
2024-05-14 13:57:08.427000,withdrawals,Sepa Withdrawal,,-1200,EUR,1293.6,,,,,,,,,,,,,,
20+
2023-03-21 13:37:29.384000,trades,Sell Trade,,-7.08,EUR,39.91,NL0011821202,ING,0.638989,11.08,EUR,,,,,,,,,Transaction Amount: 7.0800092
21+
2025-06-11 16:45:18.652000,trades,Buy Trade,,-10.0,EUR,150.5,US3755581036,Gilead Sciences,0.104172,109.96,USD,EURUSD,1.14547,,,,,,,Transaction Amount: 11.45475312
22+
2020-07-06 09:21:16.051000,others,Promotional,CASH_CREDIT,4.67,EUR,354.67,,,,,,,,,,,,,,
23+
2020-07-06 12:41:38.128000,others,To User Corrections,CASH_CREDIT,1.95,EUR,351.96,,,,,,,,,,,,,,
24+
2020-08-31 11:16:47.570000,corporate_actions,General Corporate Action,ASSET_REDEEM,-1000.08,USD,,US0378331005,Apple,2.0,500.04,USD,EURUSD,1.19388,200.89,EUR,,,,,Stock split Apple
25+
2020-08-31 11:18:46.264000,corporate_actions,General Corporate Action,ASSET_DEPOSIT,1000.08,USD,,US0378331005,Apple,8.0,125.01,USD,EURUSD,1.194,,,,,,,Stock split Apple
26+
2025-12-29 16:49:52.643000,trades,Buy Trade,CASH_DEBIT,-20.0,EUR,74.83,IE00B1TXK627,iShares Global Water,0.313873,63.7199999,EUR,EUREUR,1.0,,,,,,,Order Partial Id: 59009fc3-f72c-451f-9007-28e86adfb5fd - 1

samples/schwab-export.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,5 @@ Date,Action,Symbol,Description,Quantity,Price,Fees & Comm,Amount
117117
"04/30/2021","Name Change","09070K200","BIOSOLAR INC XXXNAME CHANGE EFF: 04/30/21","-1,000","","",""
118118
"08/25/2023","Conversion","AMC","AMC ENTERTAINMENT CLASS A","34","","",""
119119
"08/25/2023","Conversion","00165C203","AMC ENTERTAINMEN 0% PFDPFD","-344","","",""
120+
"10/14/2024 as of 10/10/2024","Cash In Lieu","SCHB","SCHWAB US LARGE CAP ETF","","","","$5.49"
120121
Transactions Total,,,,,,,"-$26,582.91"

src/converters/buxConverter.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe("buxConverter", () => {
3434
// Assert
3535
expect(actualExport).toBeTruthy();
3636
expect(actualExport.activities.length).toBeGreaterThan(0);
37-
expect(actualExport.activities.length).toBe(16);
37+
expect(actualExport.activities.length).toBe(18);
3838

3939
done();
4040
}, () => { done.fail("Should not have an error!"); });
@@ -142,8 +142,10 @@ describe("buxConverter", () => {
142142
expect(consoleSpy).toHaveBeenCalledWith("[i] No result found for buy action for NL0011821202 with currency EUR! Please add this manually..\n");
143143

144144
done();
145-
}, () => done.fail("Should not have an error!"));
146-
});
145+
}, (error) => {
146+
done(error);
147+
});
148+
}, 10000);
147149

148150
it("should log error and invoke errorCallback when an error occurs in processFileContents", (done) => {
149151

src/converters/buxConverter.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class BuxConverter extends AbstractConverter {
3636
if (context.column === "transactionType") {
3737
const action = columnValue.toLocaleLowerCase();
3838

39-
if (action.indexOf("buy") > -1) {
39+
if (action.indexOf("buy") > -1 || action.indexOf("general corporate action") > -1) {
4040
return "buy";
4141
}
4242
else if (action.indexOf("sell") > -1) {
@@ -54,13 +54,16 @@ export class BuxConverter extends AbstractConverter {
5454
}
5555

5656
// Parse numbers to floats (from string).
57-
if (context.column === "exchangeRate" ||
58-
context.column === "transactionAmount" ||
59-
context.column === "tradeAmount" ||
60-
context.column === "tradePrice" ||
61-
context.column === "tradeQuantity" ||
62-
context.column === "cashBalanceAmount") {
63-
return parseFloat(columnValue);
57+
if (context.column === "transactionAmount" ||
58+
context.column === "cashBalanceAmount" ||
59+
context.column === "assetQuantity" ||
60+
context.column === "assetPrice" ||
61+
context.column === "exchangeRate" ||
62+
context.column === "profitAndLossAmount" ||
63+
context.column === "dividendGrossAmount" ||
64+
context.column === "dividendNetAmount" ||
65+
context.column === "dividendTaxAmount") {
66+
return parseFloat(columnValue || "0");
6467
}
6568

6669
return columnValue;
@@ -72,6 +75,16 @@ export class BuxConverter extends AbstractConverter {
7275
record.exchangeRate = 1;
7376
}
7477

78+
// Cash debit transactions are internally for Bux, this is not needed.
79+
if (record.transactionType === "buy" && record.transferType?.toLocaleLowerCase() === "cash_debit") {
80+
record.transactionType = "cash debit";
81+
}
82+
83+
// Fix "General Corporate Action" records that are buys but have a positive amount.
84+
if (record.transactionType === "buy" && record.transactionAmount > 0) {
85+
record.transactionType = "sell";
86+
}
87+
7588
return record;
7689
}
7790
}, async (err, records: BuxRecord[]) => {
@@ -162,8 +175,8 @@ export class BuxConverter extends AbstractConverter {
162175
quantity = 1;
163176
unitPrice = Math.abs(record.transactionAmount) / record.exchangeRate;
164177
} else {
165-
quantity = record.tradeQuantity;
166-
unitPrice = record.tradePrice / record.exchangeRate;
178+
quantity = record.assetQuantity;
179+
unitPrice = record.assetPrice / record.exchangeRate;
167180
}
168181

169182
// Add record to export.
@@ -200,7 +213,7 @@ export class BuxConverter extends AbstractConverter {
200213
* @inheritdoc
201214
*/
202215
public isIgnoredRecord(record: BuxRecord): boolean {
203-
let ignoredRecordTypes = ["deposit", "withdrawal"];
216+
let ignoredRecordTypes = ["deposit", "withdrawal", "promotional", "to user corrections", "cash debit"];
204217

205218
return ignoredRecordTypes.some(t => record.transactionType.toLocaleLowerCase().indexOf(t) > -1)
206219
}

src/converters/schwabConverter.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe("schwabConverter", () => {
3434
// Assert
3535
expect(actualExport).toBeTruthy();
3636
expect(actualExport.activities.length).toBeGreaterThan(0);
37-
expect(actualExport.activities.length).toBe(106);
37+
expect(actualExport.activities.length).toBe(107);
3838

3939
done();
4040
}, () => { done.fail("Should not have an error!"); });

src/converters/schwabConverter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ export class SchwabConverter extends AbstractConverter {
6161
else if (action.indexOf("dividend") > -1 ||
6262
action.indexOf("qual") > -1 ||
6363
action.endsWith("reinvest") ||
64-
action.indexOf("cash div") > -1) {
64+
action.indexOf("cash div") > -1 ||
65+
action.indexOf("cash in lieu") > -1) {
6566
return "dividend";
6667
}
6768
else if (action.indexOf("advisor fee") > -1 ||

src/converters/tradeRepublicConverter.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class TradeRepublicConverter extends AbstractConverter {
2626
parse(input, {
2727
delimiter: ";",
2828
fromLine: 2,
29-
columns: this.processHeaders(input),
29+
columns: this.processHeaders(input, ";"),
3030
cast: (columnValue, context) => {
3131

3232
// Custom mapping below.
@@ -160,7 +160,9 @@ export class TradeRepublicConverter extends AbstractConverter {
160160
/**
161161
* @inheritdoc
162162
*/
163-
protected processHeaders(_: string): string[] {
163+
protected processHeaders(header: string, splitChar: string): string[] {
164+
165+
const columnCount = header.split('\n')[0].split(splitChar).length;
164166

165167
// Generic header mapping from the TradeRepublic CSV export.
166168
const csvHeaders = [
@@ -171,7 +173,15 @@ export class TradeRepublicConverter extends AbstractConverter {
171173
"isin",
172174
"amount",
173175
"costs",
174-
"tax"]
176+
"tax"];
177+
178+
// Add empty headers for any extra columns.
179+
// These are not needed for processing, but Trade Republic can sometimes add extra columns.
180+
if (columnCount > csvHeaders.length) {
181+
for (let i = csvHeaders.length; i < columnCount; i++) {
182+
csvHeaders.push(`extra${i}`);
183+
}
184+
}
175185

176186
return csvHeaders;
177187
}

src/models/buxRecord.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@ export class BuxRecord {
22
transactionTimeCet: Date;
33
transactionCategory: string;
44
transactionType: string;
5+
transferType: string;
6+
transactionAmount: number;
7+
transactionCurrency: string;
8+
cashBalanceAmount: number;
59
assetId: string;
610
assetName: string;
11+
assetQuantity: number;
12+
assetPrice: number;
713
assetCurrency: string;
8-
transactionCurrency: string;
914
currencyPair: string;
1015
exchangeRate: number;
11-
transactionAmount: number;
12-
tradeAmount: number;
13-
tradePrice: number;
14-
tradeQuantity: number;
15-
cashBalanceAmount: number;
1616
profitAndLossAmount: number;
17-
profitAndLossCurrency: string;
17+
profitAndLossCurrency: string;
18+
dividendCurrency: string;
19+
dividendGrossAmount: number;
20+
dividendNetAmount: number;
21+
dividendTaxAmount: number;
22+
transactionDescription: string;
1823
}

0 commit comments

Comments
 (0)