@fuzzle/opencode-accountant 0.16.5 → 0.16.6-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +73 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17850,7 +17850,7 @@ function extractMetadata2(detection) {
|
|
|
17850
17850
|
fromDate: metadata["from-date"],
|
|
17851
17851
|
untilDate: metadata["until-date"],
|
|
17852
17852
|
openingBalance: metadata["opening-balance"],
|
|
17853
|
-
closingBalance: metadata["closing-balance"]
|
|
17853
|
+
closingBalance: metadata["closing-balance"] ? parseFloat(metadata["closing-balance"]).toFixed(2) : undefined
|
|
17854
17854
|
};
|
|
17855
17855
|
}
|
|
17856
17856
|
function executeMoves(plannedMoves, config2, unrecognizedDir, directory) {
|
|
@@ -26903,6 +26903,16 @@ function generateIbkrBuyEntry(trade, logger) {
|
|
|
26903
26903
|
account: `assets:broker:ibkr:${trade.currency.toLowerCase()}`,
|
|
26904
26904
|
amount: formatAmount(-cashOut, trade.currency)
|
|
26905
26905
|
});
|
|
26906
|
+
const computedNetCents = Math.round(totalCost * 100) + Math.round(fees * 100);
|
|
26907
|
+
const brokerNetCents = Math.round(cashOut * 100);
|
|
26908
|
+
const roundingCents = brokerNetCents - computedNetCents;
|
|
26909
|
+
if (roundingCents !== 0) {
|
|
26910
|
+
postings.push({
|
|
26911
|
+
account: "equity:rounding",
|
|
26912
|
+
amount: formatAmount(roundingCents / 100, trade.currency)
|
|
26913
|
+
});
|
|
26914
|
+
logger?.debug(`Rounding adjustment: ${roundingCents / 100} ${trade.currency}`);
|
|
26915
|
+
}
|
|
26906
26916
|
let entry = `${trade.date} ${description}
|
|
26907
26917
|
`;
|
|
26908
26918
|
entry += ` ; ibkr:account:${trade.account}
|
|
@@ -26952,6 +26962,16 @@ function generateIbkrSellEntry(trade, consumed, logger) {
|
|
|
26952
26962
|
amount: formatAmount(-capitalGain, trade.currency)
|
|
26953
26963
|
});
|
|
26954
26964
|
}
|
|
26965
|
+
const computedNetCents = Math.round(saleProceeds * 100) - Math.round(fees * 100);
|
|
26966
|
+
const brokerNetCents = Math.round(Math.abs(cashIn) * 100);
|
|
26967
|
+
const roundingCents = computedNetCents - brokerNetCents;
|
|
26968
|
+
if (roundingCents !== 0) {
|
|
26969
|
+
postings.push({
|
|
26970
|
+
account: "equity:rounding",
|
|
26971
|
+
amount: formatAmount(roundingCents / 100, trade.currency)
|
|
26972
|
+
});
|
|
26973
|
+
logger?.debug(`Rounding adjustment: ${roundingCents / 100} ${trade.currency}`);
|
|
26974
|
+
}
|
|
26955
26975
|
let entry = `${trade.date} ${description}
|
|
26956
26976
|
`;
|
|
26957
26977
|
entry += ` ; ibkr:account:${trade.account}
|
|
@@ -26981,6 +27001,16 @@ function generateIbkrDividendEntry(dividend, logger) {
|
|
|
26981
27001
|
account: `income:dividends:${dividend.symbol}`,
|
|
26982
27002
|
amount: formatAmount(-dividend.grossAmount, dividend.currency)
|
|
26983
27003
|
});
|
|
27004
|
+
const computedNetCents = Math.round(dividend.grossAmount * 100) - Math.round(dividend.withholdingTax * 100);
|
|
27005
|
+
const brokerNetCents = Math.round(dividend.netAmount * 100);
|
|
27006
|
+
const roundingCents = brokerNetCents - computedNetCents;
|
|
27007
|
+
if (roundingCents !== 0) {
|
|
27008
|
+
postings.push({
|
|
27009
|
+
account: "equity:rounding",
|
|
27010
|
+
amount: formatAmount(roundingCents / 100, dividend.currency)
|
|
27011
|
+
});
|
|
27012
|
+
logger?.debug(`Rounding adjustment: ${roundingCents / 100} ${dividend.currency}`);
|
|
27013
|
+
}
|
|
26984
27014
|
let entry = `${dividend.date} ${description}
|
|
26985
27015
|
`;
|
|
26986
27016
|
entry += ` ; ibkr:account:${dividend.account}
|
|
@@ -26997,6 +27027,7 @@ var TAX_TYPE = "Foreign Tax Withholding";
|
|
|
26997
27027
|
var ADJUSTMENT_TYPE = "Adjustment";
|
|
26998
27028
|
var FOREX_TYPE = "Forex Trade Component";
|
|
26999
27029
|
var DEPOSIT_TYPE = "Deposit";
|
|
27030
|
+
var round2 = (n) => Math.round(n * 100) / 100;
|
|
27000
27031
|
function parseIbkrCsv(content) {
|
|
27001
27032
|
const transactions = [];
|
|
27002
27033
|
const result = import_papaparse3.default.parse(content, {
|
|
@@ -27102,6 +27133,8 @@ async function preprocessIbkr(csvPath, directory, currency, year, lotInventoryPa
|
|
|
27102
27133
|
const content = fs22.readFileSync(csvPath, "utf-8");
|
|
27103
27134
|
const transactions = parseIbkrCsv(content);
|
|
27104
27135
|
logger?.info(`Parsed ${transactions.length} IBKR transactions from ${path17.basename(csvPath)}`);
|
|
27136
|
+
let rawSum = 0;
|
|
27137
|
+
let roundedSum = 0;
|
|
27105
27138
|
const deposits = [];
|
|
27106
27139
|
const trades = [];
|
|
27107
27140
|
const dividendTxns = [];
|
|
@@ -27224,6 +27257,7 @@ async function preprocessIbkr(csvPath, directory, currency, year, lotInventoryPa
|
|
|
27224
27257
|
const commodityJournalPath = path17.join(directory, "ledger", "investments", "commodities.journal");
|
|
27225
27258
|
ensureCommodityDeclarations(commodityJournalPath, tradedSymbols, logger);
|
|
27226
27259
|
}
|
|
27260
|
+
usedAccounts.add("equity:rounding");
|
|
27227
27261
|
if (usedAccounts.size > 0) {
|
|
27228
27262
|
const accountJournalPath = path17.join(directory, "ledger", "investments", "accounts.journal");
|
|
27229
27263
|
ensureInvestmentAccountDeclarations(accountJournalPath, usedAccounts, logger);
|
|
@@ -27232,29 +27266,52 @@ async function preprocessIbkr(csvPath, directory, currency, year, lotInventoryPa
|
|
|
27232
27266
|
logger?.info(`Generated IBKR journal: ${journalPath} with ${journalEntries.length} entries`);
|
|
27233
27267
|
}
|
|
27234
27268
|
const simpleTransactions = [...deposits, ...adjustments, ...forexTxns];
|
|
27269
|
+
for (const d of simpleTransactions) {
|
|
27270
|
+
rawSum += d.netAmount;
|
|
27271
|
+
roundedSum += round2(d.netAmount);
|
|
27272
|
+
}
|
|
27273
|
+
const csvRows = simpleTransactions.map((d) => [
|
|
27274
|
+
d.date,
|
|
27275
|
+
d.account,
|
|
27276
|
+
`"${d.description.replace(/"/g, '""')}"`,
|
|
27277
|
+
d.transactionType,
|
|
27278
|
+
d.symbol,
|
|
27279
|
+
d.quantity || "",
|
|
27280
|
+
d.price || "",
|
|
27281
|
+
d.priceCurrency,
|
|
27282
|
+
d.grossAmount ? round2(d.grossAmount) : "",
|
|
27283
|
+
d.commission ? round2(d.commission) : "",
|
|
27284
|
+
round2(d.netAmount)
|
|
27285
|
+
].join(","));
|
|
27286
|
+
const roundingAdj = round2(round2(rawSum) - roundedSum);
|
|
27287
|
+
if (roundingAdj !== 0 && Math.abs(roundingAdj) <= 0.05) {
|
|
27288
|
+
const lastDate = transactions[transactions.length - 1]?.date ?? "";
|
|
27289
|
+
const account = transactions[0]?.account ?? "";
|
|
27290
|
+
csvRows.push([
|
|
27291
|
+
lastDate,
|
|
27292
|
+
account,
|
|
27293
|
+
'"Rounding adjustment"',
|
|
27294
|
+
"Rounding",
|
|
27295
|
+
"",
|
|
27296
|
+
"",
|
|
27297
|
+
"",
|
|
27298
|
+
"",
|
|
27299
|
+
"",
|
|
27300
|
+
"",
|
|
27301
|
+
roundingAdj
|
|
27302
|
+
].join(","));
|
|
27303
|
+
logger?.info(`Added rounding adjustment: ${roundingAdj} CHF`);
|
|
27304
|
+
}
|
|
27235
27305
|
let simpleTransactionsCsvPath = null;
|
|
27236
|
-
if (
|
|
27306
|
+
if (csvRows.length > 0) {
|
|
27237
27307
|
const filteredCsvPath = path17.join(csvDir, `${csvBasename}-filtered.csv`);
|
|
27238
27308
|
const csvHeader = "Date,Account,Description,Transaction Type,Symbol,Quantity,Price,Price Currency,Gross Amount,Commission,Net Amount";
|
|
27239
|
-
const csvRows = simpleTransactions.map((d) => [
|
|
27240
|
-
d.date,
|
|
27241
|
-
d.account,
|
|
27242
|
-
`"${d.description.replace(/"/g, '""')}"`,
|
|
27243
|
-
d.transactionType,
|
|
27244
|
-
d.symbol,
|
|
27245
|
-
d.quantity || "",
|
|
27246
|
-
d.price || "",
|
|
27247
|
-
d.priceCurrency,
|
|
27248
|
-
d.grossAmount ? Math.round(d.grossAmount * 100) / 100 : "",
|
|
27249
|
-
d.commission ? Math.round(d.commission * 100) / 100 : "",
|
|
27250
|
-
Math.round(d.netAmount * 100) / 100
|
|
27251
|
-
].join(","));
|
|
27252
27309
|
fs22.writeFileSync(filteredCsvPath, csvHeader + `
|
|
27253
27310
|
` + csvRows.join(`
|
|
27254
27311
|
`) + `
|
|
27255
27312
|
`);
|
|
27256
27313
|
simpleTransactionsCsvPath = filteredCsvPath;
|
|
27257
|
-
logger?.info(`Generated filtered CSV: ${filteredCsvPath} (${
|
|
27314
|
+
logger?.info(`Generated filtered CSV: ${filteredCsvPath} (${csvRows.length} rows)`);
|
|
27258
27315
|
}
|
|
27259
27316
|
const dividendCount = dividendGroups.length;
|
|
27260
27317
|
return {
|