@fuzzle/opencode-accountant 0.13.14 → 0.13.15-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 +134 -94
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25298,23 +25298,30 @@ function generateDividendEntry(dividend, logger) {
|
|
|
25298
25298
|
`;
|
|
25299
25299
|
return entry;
|
|
25300
25300
|
}
|
|
25301
|
-
function generateSplitEntry(action, oldQuantity, newQuantity, logger) {
|
|
25301
|
+
function generateSplitEntry(action, oldQuantity, newQuantity, totalCostBasis, currency, logger) {
|
|
25302
25302
|
const date5 = formatDate(action.date);
|
|
25303
25303
|
const ratio = action.ratio || newQuantity / oldQuantity;
|
|
25304
25304
|
const splitType = ratio > 1 ? "Split" : "Reverse Split";
|
|
25305
25305
|
const description = escapeDescription(`${splitType}: ${action.symbol} (${action.name})`);
|
|
25306
25306
|
logger?.debug(`Generating ${splitType} entry: ${oldQuantity} -> ${newQuantity} ${action.symbol}`);
|
|
25307
25307
|
const commodity = formatCommodity(action.symbol);
|
|
25308
|
+
const totalCost = formatAmount2(totalCostBasis, currency);
|
|
25308
25309
|
const postings = [
|
|
25309
25310
|
{
|
|
25310
25311
|
account: `assets:investments:stocks:${action.symbol}`,
|
|
25311
|
-
amount: `-${formatQuantity(oldQuantity)} ${commodity}`
|
|
25312
|
+
amount: `-${formatQuantity(oldQuantity)} ${commodity} @@ ${totalCost}`
|
|
25313
|
+
},
|
|
25314
|
+
{
|
|
25315
|
+
account: "equity:conversion",
|
|
25316
|
+
amount: `${formatQuantity(oldQuantity)} ${commodity} @@ ${totalCost}`
|
|
25317
|
+
},
|
|
25318
|
+
{
|
|
25319
|
+
account: "equity:conversion",
|
|
25320
|
+
amount: `-${formatQuantity(newQuantity)} ${commodity} @@ ${totalCost}`
|
|
25312
25321
|
},
|
|
25313
|
-
{ account: "equity:conversion", amount: `${formatQuantity(oldQuantity)} ${commodity}` },
|
|
25314
|
-
{ account: "equity:conversion", amount: `-${formatQuantity(newQuantity)} ${commodity}` },
|
|
25315
25322
|
{
|
|
25316
25323
|
account: `assets:investments:stocks:${action.symbol}`,
|
|
25317
|
-
amount: `${formatQuantity(newQuantity)} ${commodity}`
|
|
25324
|
+
amount: `${formatQuantity(newQuantity)} ${commodity} @@ ${totalCost}`
|
|
25318
25325
|
}
|
|
25319
25326
|
];
|
|
25320
25327
|
let entry = `${date5} ${description}
|
|
@@ -25355,7 +25362,7 @@ function generateWorthlessEntry(action, removedLots, logger) {
|
|
|
25355
25362
|
`;
|
|
25356
25363
|
return entry;
|
|
25357
25364
|
}
|
|
25358
|
-
function generateMultiWayMergerEntry(group, crossCurrencyOutgoingSymbols, crossCurrencyOutgoingIsins, logger) {
|
|
25365
|
+
function generateMultiWayMergerEntry(group, crossCurrencyOutgoingSymbols, crossCurrencyOutgoingIsins, costInfo, logger) {
|
|
25359
25366
|
const date5 = formatDate(group.date);
|
|
25360
25367
|
const outSymbols = crossCurrencyOutgoingSymbols ?? group.outgoing.map((a) => a.symbol);
|
|
25361
25368
|
const inSymbols = group.incoming.map((a) => a.symbol);
|
|
@@ -25365,22 +25372,29 @@ function generateMultiWayMergerEntry(group, crossCurrencyOutgoingSymbols, crossC
|
|
|
25365
25372
|
const oldIsins = (crossCurrencyOutgoingIsins ?? group.outgoing.map((a) => a.isin)).filter(Boolean);
|
|
25366
25373
|
const newIsins = group.incoming.map((a) => a.isin).filter(Boolean);
|
|
25367
25374
|
const postings = [];
|
|
25368
|
-
for (
|
|
25375
|
+
for (let i2 = 0;i2 < group.outgoing.length; i2++) {
|
|
25376
|
+
const out = group.outgoing[i2];
|
|
25369
25377
|
const qty = formatQuantity(Math.abs(out.quantity));
|
|
25370
25378
|
const commodity = formatCommodity(out.symbol);
|
|
25379
|
+
const costAnnotation = costInfo && costInfo.outgoingTotalCosts[i2] != null ? ` @@ ${formatAmount2(costInfo.outgoingTotalCosts[i2], costInfo.currency)}` : "";
|
|
25371
25380
|
postings.push({
|
|
25372
25381
|
account: `assets:investments:stocks:${out.symbol}`,
|
|
25373
|
-
amount: `-${qty} ${commodity}`
|
|
25382
|
+
amount: `-${qty} ${commodity}${costAnnotation}`
|
|
25374
25383
|
});
|
|
25375
|
-
postings.push({ account: "equity:conversion", amount: `${qty} ${commodity}` });
|
|
25384
|
+
postings.push({ account: "equity:conversion", amount: `${qty} ${commodity}${costAnnotation}` });
|
|
25376
25385
|
}
|
|
25377
|
-
for (
|
|
25386
|
+
for (let i2 = 0;i2 < group.incoming.length; i2++) {
|
|
25387
|
+
const inc = group.incoming[i2];
|
|
25378
25388
|
const qty = formatQuantity(Math.abs(inc.quantity));
|
|
25379
25389
|
const commodity = formatCommodity(inc.symbol);
|
|
25380
|
-
|
|
25390
|
+
const costAnnotation = costInfo && costInfo.incomingTotalCosts[i2] != null ? ` @@ ${formatAmount2(costInfo.incomingTotalCosts[i2], costInfo.currency)}` : "";
|
|
25391
|
+
postings.push({
|
|
25392
|
+
account: "equity:conversion",
|
|
25393
|
+
amount: `-${qty} ${commodity}${costAnnotation}`
|
|
25394
|
+
});
|
|
25381
25395
|
postings.push({
|
|
25382
25396
|
account: `assets:investments:stocks:${inc.symbol}`,
|
|
25383
|
-
amount: `${qty} ${commodity}`
|
|
25397
|
+
amount: `${qty} ${commodity}${costAnnotation}`
|
|
25384
25398
|
});
|
|
25385
25399
|
}
|
|
25386
25400
|
let entry = `${date5} ${description}
|
|
@@ -25624,9 +25638,12 @@ function processNonMergerAction(action, inventory, entries, logger) {
|
|
|
25624
25638
|
const oldQty = getHeldQuantity(inventory, action.symbol);
|
|
25625
25639
|
const newQty = Math.abs(qty);
|
|
25626
25640
|
if (oldQty > 0) {
|
|
25641
|
+
const lots = inventory[action.symbol] || [];
|
|
25642
|
+
const totalCostBasis = lots.reduce((sum, lot) => sum + lot.quantity * lot.costBasis, 0);
|
|
25643
|
+
const currency = lots[0]?.currency || "CAD";
|
|
25627
25644
|
const ratio = newQty / oldQty;
|
|
25628
25645
|
adjustLotsForSplit(inventory, action.symbol, ratio, logger);
|
|
25629
|
-
const entry = generateSplitEntry(action, oldQty, newQty, logger);
|
|
25646
|
+
const entry = generateSplitEntry(action, oldQty, newQty, totalCostBasis, currency, logger);
|
|
25630
25647
|
entries.push(entry);
|
|
25631
25648
|
} else {
|
|
25632
25649
|
logger?.warn(`Reverse split for ${action.symbol} but no lots found`);
|
|
@@ -25652,36 +25669,6 @@ function processNonMergerAction(action, inventory, entries, logger) {
|
|
|
25652
25669
|
}
|
|
25653
25670
|
}
|
|
25654
25671
|
}
|
|
25655
|
-
function processCorporateActions(actions, inventory, lotInventoryPath, projectDir, logger) {
|
|
25656
|
-
const entries = [];
|
|
25657
|
-
actions.sort((a, b) => formatDate(a.date).localeCompare(formatDate(b.date)));
|
|
25658
|
-
const mergerActions = [];
|
|
25659
|
-
const otherActions = [];
|
|
25660
|
-
for (const action of actions) {
|
|
25661
|
-
if (MERGER_LIKE_TYPES.has(action.type)) {
|
|
25662
|
-
mergerActions.push(action);
|
|
25663
|
-
} else {
|
|
25664
|
-
otherActions.push(action);
|
|
25665
|
-
}
|
|
25666
|
-
}
|
|
25667
|
-
const mergerGroups = groupMergerActions(mergerActions);
|
|
25668
|
-
mergerGroups.sort((a, b) => formatDate(a.date).localeCompare(formatDate(b.date)));
|
|
25669
|
-
let mi = 0;
|
|
25670
|
-
let oi = 0;
|
|
25671
|
-
while (mi < mergerGroups.length || oi < otherActions.length) {
|
|
25672
|
-
const mergerDate = mi < mergerGroups.length ? formatDate(mergerGroups[mi].date) : "\uFFFF";
|
|
25673
|
-
const otherDate = oi < otherActions.length ? formatDate(otherActions[oi].date) : "\uFFFF";
|
|
25674
|
-
if (mergerDate <= otherDate) {
|
|
25675
|
-
const groupEntries = processMultiWayMerger(mergerGroups[mi], inventory, lotInventoryPath, projectDir, logger);
|
|
25676
|
-
entries.push(...groupEntries);
|
|
25677
|
-
mi++;
|
|
25678
|
-
} else {
|
|
25679
|
-
processNonMergerAction(otherActions[oi], inventory, entries, logger);
|
|
25680
|
-
oi++;
|
|
25681
|
-
}
|
|
25682
|
-
}
|
|
25683
|
-
return entries;
|
|
25684
|
-
}
|
|
25685
25672
|
function groupMergerActions(actions) {
|
|
25686
25673
|
const groupMap = new Map;
|
|
25687
25674
|
for (const action of actions) {
|
|
@@ -25713,11 +25700,13 @@ function processMultiWayMerger(group, inventory, lotInventoryPath, projectDir, l
|
|
|
25713
25700
|
const pendingState = loadPendingMerger(projectDir, lotInventoryPath, group.key, logger);
|
|
25714
25701
|
if (pendingState) {
|
|
25715
25702
|
const totalIncomingQty2 = group.incoming.reduce((sum, a) => sum + Math.abs(a.quantity), 0);
|
|
25703
|
+
const incomingTotalCosts2 = [];
|
|
25716
25704
|
for (const inc of group.incoming) {
|
|
25717
25705
|
const absQty = Math.abs(inc.quantity);
|
|
25718
25706
|
const proportion = absQty / totalIncomingQty2;
|
|
25719
25707
|
const allocatedCost = pendingState.totalCostBasis * proportion;
|
|
25720
25708
|
const costBasisPerUnit = absQty > 0 ? allocatedCost / absQty : 0;
|
|
25709
|
+
incomingTotalCosts2.push(allocatedCost);
|
|
25721
25710
|
const lot = {
|
|
25722
25711
|
date: formatDate(inc.date),
|
|
25723
25712
|
quantity: absQty,
|
|
@@ -25732,7 +25721,12 @@ function processMultiWayMerger(group, inventory, lotInventoryPath, projectDir, l
|
|
|
25732
25721
|
inventory[inc.symbol].push(lot);
|
|
25733
25722
|
logger?.info(`Cross-currency merger incoming: ${absQty} ${inc.symbol} @ ${costBasisPerUnit.toFixed(2)} ${pendingState.currency}`);
|
|
25734
25723
|
}
|
|
25735
|
-
const
|
|
25724
|
+
const costInfo2 = {
|
|
25725
|
+
outgoingTotalCosts: [],
|
|
25726
|
+
incomingTotalCosts: incomingTotalCosts2,
|
|
25727
|
+
currency: pendingState.currency
|
|
25728
|
+
};
|
|
25729
|
+
const entry2 = generateMultiWayMergerEntry(group, pendingState.outgoingSymbols, pendingState.outgoingIsins, costInfo2, logger);
|
|
25736
25730
|
entries.push(entry2);
|
|
25737
25731
|
removePendingMerger(projectDir, lotInventoryPath, group.key, logger);
|
|
25738
25732
|
} else {
|
|
@@ -25743,18 +25737,23 @@ function processMultiWayMerger(group, inventory, lotInventoryPath, projectDir, l
|
|
|
25743
25737
|
let totalCostBasis = 0;
|
|
25744
25738
|
let outgoingCurrency = "";
|
|
25745
25739
|
const outgoingSymbols = [];
|
|
25740
|
+
const outgoingTotalCosts = [];
|
|
25746
25741
|
for (const out of group.outgoing) {
|
|
25747
25742
|
outgoingSymbols.push(out.symbol);
|
|
25748
25743
|
const lots = inventory[out.symbol];
|
|
25744
|
+
let symbolCost = 0;
|
|
25749
25745
|
if (lots) {
|
|
25750
25746
|
for (const lot of lots) {
|
|
25751
|
-
|
|
25747
|
+
symbolCost += lot.quantity * lot.costBasis;
|
|
25752
25748
|
if (!outgoingCurrency && lot.currency) {
|
|
25753
25749
|
outgoingCurrency = lot.currency;
|
|
25754
25750
|
}
|
|
25755
25751
|
}
|
|
25756
25752
|
}
|
|
25753
|
+
totalCostBasis += symbolCost;
|
|
25754
|
+
outgoingTotalCosts.push(symbolCost);
|
|
25757
25755
|
}
|
|
25756
|
+
const costCurrency = outgoingCurrency || "CAD";
|
|
25758
25757
|
if (group.outgoing.length > 0 && group.incoming.length === 0) {
|
|
25759
25758
|
for (const out of group.outgoing) {
|
|
25760
25759
|
removeLots(inventory, out.symbol, logger);
|
|
@@ -25766,9 +25765,14 @@ function processMultiWayMerger(group, inventory, lotInventoryPath, projectDir, l
|
|
|
25766
25765
|
outgoingIsins: group.outgoing.map((a) => a.isin),
|
|
25767
25766
|
outgoingQuantities: group.outgoing.map((a) => Math.abs(a.quantity)),
|
|
25768
25767
|
totalCostBasis,
|
|
25769
|
-
currency:
|
|
25768
|
+
currency: costCurrency
|
|
25770
25769
|
}, logger);
|
|
25771
|
-
const
|
|
25770
|
+
const costInfo2 = {
|
|
25771
|
+
outgoingTotalCosts,
|
|
25772
|
+
incomingTotalCosts: [],
|
|
25773
|
+
currency: costCurrency
|
|
25774
|
+
};
|
|
25775
|
+
const entry2 = generateMultiWayMergerEntry(group, undefined, undefined, costInfo2, logger);
|
|
25772
25776
|
entries.push(entry2);
|
|
25773
25777
|
logger?.info(`Cross-currency merger outgoing: ${outgoingSymbols.join(", ")} -> pending (cost basis: ${totalCostBasis.toFixed(2)})`);
|
|
25774
25778
|
return entries;
|
|
@@ -25779,16 +25783,18 @@ function processMultiWayMerger(group, inventory, lotInventoryPath, projectDir, l
|
|
|
25779
25783
|
logger?.debug(`Merger outgoing: removed ${absQty} ${out.symbol}`);
|
|
25780
25784
|
}
|
|
25781
25785
|
const totalIncomingQty = group.incoming.reduce((sum, a) => sum + Math.abs(a.quantity), 0);
|
|
25786
|
+
const incomingTotalCosts = [];
|
|
25782
25787
|
for (const inc of group.incoming) {
|
|
25783
25788
|
const absQty = Math.abs(inc.quantity);
|
|
25784
25789
|
const proportion = totalIncomingQty > 0 ? absQty / totalIncomingQty : 0;
|
|
25785
25790
|
const allocatedCost = totalCostBasis * proportion;
|
|
25786
25791
|
const costBasisPerUnit = absQty > 0 ? allocatedCost / absQty : 0;
|
|
25792
|
+
incomingTotalCosts.push(allocatedCost);
|
|
25787
25793
|
const lot = {
|
|
25788
25794
|
date: formatDate(inc.date),
|
|
25789
25795
|
quantity: absQty,
|
|
25790
25796
|
costBasis: costBasisPerUnit,
|
|
25791
|
-
currency:
|
|
25797
|
+
currency: costCurrency,
|
|
25792
25798
|
isin: inc.isin,
|
|
25793
25799
|
orderNum: inc.orderNum
|
|
25794
25800
|
};
|
|
@@ -25798,7 +25804,12 @@ function processMultiWayMerger(group, inventory, lotInventoryPath, projectDir, l
|
|
|
25798
25804
|
inventory[inc.symbol].push(lot);
|
|
25799
25805
|
logger?.debug(`Merger incoming: added ${absQty} ${inc.symbol} @ ${costBasisPerUnit.toFixed(2)}`);
|
|
25800
25806
|
}
|
|
25801
|
-
const
|
|
25807
|
+
const costInfo = {
|
|
25808
|
+
outgoingTotalCosts,
|
|
25809
|
+
incomingTotalCosts,
|
|
25810
|
+
currency: costCurrency
|
|
25811
|
+
};
|
|
25812
|
+
const entry = generateMultiWayMergerEntry(group, undefined, undefined, costInfo, logger);
|
|
25802
25813
|
entries.push(entry);
|
|
25803
25814
|
return entries;
|
|
25804
25815
|
}
|
|
@@ -26013,57 +26024,86 @@ async function preprocessSwissquote(csvPath, projectDir, currency, year, lotInve
|
|
|
26013
26024
|
logger?.logStep("route", "success", `Simple: ${stats.simpleTransactions}, Trades: ${stats.trades}, Dividends: ${stats.dividends}, Corporate: ${stats.corporateActions}, Forex: ${stats.forexTransactions}, Skipped: ${stats.skipped}`);
|
|
26014
26025
|
logger?.endSection();
|
|
26015
26026
|
const journalEntries = [];
|
|
26016
|
-
|
|
26017
|
-
|
|
26018
|
-
|
|
26019
|
-
|
|
26020
|
-
|
|
26021
|
-
|
|
26022
|
-
|
|
26023
|
-
|
|
26024
|
-
|
|
26025
|
-
|
|
26026
|
-
|
|
26027
|
-
|
|
26028
|
-
|
|
26029
|
-
|
|
26030
|
-
|
|
26031
|
-
|
|
26032
|
-
|
|
26033
|
-
|
|
26034
|
-
|
|
26035
|
-
|
|
26036
|
-
|
|
26037
|
-
|
|
26027
|
+
const timeline = [];
|
|
26028
|
+
for (const trade of trades) {
|
|
26029
|
+
timeline.push({ kind: "trade", sortDate: formatDate(trade.date), trade });
|
|
26030
|
+
}
|
|
26031
|
+
for (const dividend of dividends) {
|
|
26032
|
+
timeline.push({ kind: "dividend", sortDate: formatDate(dividend.date), dividend });
|
|
26033
|
+
}
|
|
26034
|
+
const mergerActions = [];
|
|
26035
|
+
const otherCorpActions = [];
|
|
26036
|
+
for (const action of corporateActions) {
|
|
26037
|
+
if (MERGER_LIKE_TYPES.has(action.type)) {
|
|
26038
|
+
mergerActions.push(action);
|
|
26039
|
+
} else {
|
|
26040
|
+
otherCorpActions.push(action);
|
|
26041
|
+
}
|
|
26042
|
+
}
|
|
26043
|
+
const mergerGroups = groupMergerActions(mergerActions);
|
|
26044
|
+
for (const group of mergerGroups) {
|
|
26045
|
+
timeline.push({ kind: "mergerGroup", sortDate: formatDate(group.date), group });
|
|
26046
|
+
}
|
|
26047
|
+
for (const action of otherCorpActions) {
|
|
26048
|
+
timeline.push({ kind: "corpAction", sortDate: formatDate(action.date), action });
|
|
26049
|
+
}
|
|
26050
|
+
timeline.sort((a, b) => a.sortDate.localeCompare(b.sortDate));
|
|
26051
|
+
if (timeline.length > 0) {
|
|
26052
|
+
logger?.startSection("Chronological Event Processing", 2);
|
|
26053
|
+
for (const event of timeline) {
|
|
26054
|
+
switch (event.kind) {
|
|
26055
|
+
case "trade": {
|
|
26056
|
+
const trade = event.trade;
|
|
26057
|
+
try {
|
|
26058
|
+
if (trade.type === "Buy") {
|
|
26059
|
+
const tradeInfo = {
|
|
26060
|
+
date: formatDate(trade.date),
|
|
26061
|
+
orderNum: trade.orderNum,
|
|
26062
|
+
symbol: trade.symbol,
|
|
26063
|
+
isin: trade.isin,
|
|
26064
|
+
quantity: trade.quantity,
|
|
26065
|
+
unitPrice: trade.unitPrice,
|
|
26066
|
+
currency: trade.currency
|
|
26067
|
+
};
|
|
26068
|
+
addLot(inventory, tradeInfo, logger);
|
|
26069
|
+
const entry = generateBuyEntry(trade, logger);
|
|
26070
|
+
journalEntries.push(entry);
|
|
26071
|
+
logger?.logStep("trade-buy", "success", `Buy ${trade.quantity} ${trade.symbol} @ ${trade.unitPrice} ${trade.currency}`);
|
|
26072
|
+
} else if (trade.type === "Sell") {
|
|
26073
|
+
const consumed = consumeLotsFIFO(inventory, trade.symbol, trade.quantity, logger);
|
|
26074
|
+
const entry = generateSellEntry(trade, consumed, logger);
|
|
26075
|
+
journalEntries.push(entry);
|
|
26076
|
+
const totalCost = consumed.reduce((sum, c) => sum + c.totalCost, 0);
|
|
26077
|
+
const gain = trade.quantity * trade.unitPrice - totalCost;
|
|
26078
|
+
logger?.logStep("trade-sell", "success", `Sell ${trade.quantity} ${trade.symbol} @ ${trade.unitPrice} ${trade.currency}, gain: ${gain.toFixed(2)}`);
|
|
26079
|
+
}
|
|
26080
|
+
} catch (error45) {
|
|
26081
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
26082
|
+
logger?.logStep("trade", "error", `Failed to process trade: ${message}`);
|
|
26083
|
+
logger?.error(`Trade processing error for ${trade.symbol}`, error45 instanceof Error ? error45 : undefined);
|
|
26084
|
+
}
|
|
26085
|
+
break;
|
|
26086
|
+
}
|
|
26087
|
+
case "dividend": {
|
|
26088
|
+
const dividend = event.dividend;
|
|
26089
|
+
const entry = generateDividendEntry(dividend, logger);
|
|
26038
26090
|
journalEntries.push(entry);
|
|
26039
|
-
|
|
26040
|
-
|
|
26041
|
-
|
|
26091
|
+
logger?.logStep("dividend", "success", `Dividend ${dividend.symbol}: ${dividend.netAmount} ${dividend.currency} (tax: ${dividend.withholdingTax})`);
|
|
26092
|
+
break;
|
|
26093
|
+
}
|
|
26094
|
+
case "mergerGroup": {
|
|
26095
|
+
const groupEntries = processMultiWayMerger(event.group, inventory, lotInventoryPath, projectDir, logger);
|
|
26096
|
+
journalEntries.push(...groupEntries);
|
|
26097
|
+
break;
|
|
26098
|
+
}
|
|
26099
|
+
case "corpAction": {
|
|
26100
|
+
processNonMergerAction(event.action, inventory, journalEntries, logger);
|
|
26101
|
+
break;
|
|
26042
26102
|
}
|
|
26043
|
-
} catch (error45) {
|
|
26044
|
-
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
26045
|
-
logger?.logStep("trade", "error", `Failed to process trade: ${message}`);
|
|
26046
|
-
logger?.error(`Trade processing error for ${trade.symbol}`, error45 instanceof Error ? error45 : undefined);
|
|
26047
26103
|
}
|
|
26048
26104
|
}
|
|
26049
26105
|
logger?.endSection();
|
|
26050
26106
|
}
|
|
26051
|
-
if (dividends.length > 0) {
|
|
26052
|
-
logger?.startSection("Dividend Processing", 2);
|
|
26053
|
-
for (const dividend of dividends) {
|
|
26054
|
-
const entry = generateDividendEntry(dividend, logger);
|
|
26055
|
-
journalEntries.push(entry);
|
|
26056
|
-
logger?.logStep("dividend", "success", `Dividend ${dividend.symbol}: ${dividend.netAmount} ${dividend.currency} (tax: ${dividend.withholdingTax})`);
|
|
26057
|
-
}
|
|
26058
|
-
logger?.endSection();
|
|
26059
|
-
}
|
|
26060
|
-
if (corporateActions.length > 0) {
|
|
26061
|
-
logger?.startSection("Corporate Actions Processing", 2);
|
|
26062
|
-
const corpEntries = processCorporateActions(corporateActions, inventory, lotInventoryPath, projectDir, logger);
|
|
26063
|
-
journalEntries.push(...corpEntries);
|
|
26064
|
-
logger?.logStep("corporate", "success", `Processed ${corporateActions.length} corporate actions`);
|
|
26065
|
-
logger?.endSection();
|
|
26066
|
-
}
|
|
26067
26107
|
logger?.logStep("save-inventory", "start", "Saving lot inventory");
|
|
26068
26108
|
saveLotInventory(projectDir, lotInventoryPath, inventory, logger);
|
|
26069
26109
|
logger?.logStep("save-inventory", "success", "Lot inventory saved");
|
package/package.json
CHANGED