@fuzzle/opencode-accountant 0.13.13-next.1 → 0.13.14-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.
Files changed (2) hide show
  1. package/dist/index.js +74 -75
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -25652,36 +25652,6 @@ function processNonMergerAction(action, inventory, entries, logger) {
25652
25652
  }
25653
25653
  }
25654
25654
  }
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
25655
  function groupMergerActions(actions) {
25686
25656
  const groupMap = new Map;
25687
25657
  for (const action of actions) {
@@ -26013,57 +25983,86 @@ async function preprocessSwissquote(csvPath, projectDir, currency, year, lotInve
26013
25983
  logger?.logStep("route", "success", `Simple: ${stats.simpleTransactions}, Trades: ${stats.trades}, Dividends: ${stats.dividends}, Corporate: ${stats.corporateActions}, Forex: ${stats.forexTransactions}, Skipped: ${stats.skipped}`);
26014
25984
  logger?.endSection();
26015
25985
  const journalEntries = [];
26016
- if (trades.length > 0) {
26017
- logger?.startSection("Trade Processing", 2);
26018
- trades.sort((a, b) => formatDate(a.date).localeCompare(formatDate(b.date)));
26019
- for (const trade of trades) {
26020
- try {
26021
- if (trade.type === "Buy") {
26022
- const tradeInfo = {
26023
- date: formatDate(trade.date),
26024
- orderNum: trade.orderNum,
26025
- symbol: trade.symbol,
26026
- isin: trade.isin,
26027
- quantity: trade.quantity,
26028
- unitPrice: trade.unitPrice,
26029
- currency: trade.currency
26030
- };
26031
- addLot(inventory, tradeInfo, logger);
26032
- const entry = generateBuyEntry(trade, logger);
26033
- journalEntries.push(entry);
26034
- logger?.logStep("trade-buy", "success", `Buy ${trade.quantity} ${trade.symbol} @ ${trade.unitPrice} ${trade.currency}`);
26035
- } else if (trade.type === "Sell") {
26036
- const consumed = consumeLotsFIFO(inventory, trade.symbol, trade.quantity, logger);
26037
- const entry = generateSellEntry(trade, consumed, logger);
25986
+ const timeline = [];
25987
+ for (const trade of trades) {
25988
+ timeline.push({ kind: "trade", sortDate: formatDate(trade.date), trade });
25989
+ }
25990
+ for (const dividend of dividends) {
25991
+ timeline.push({ kind: "dividend", sortDate: formatDate(dividend.date), dividend });
25992
+ }
25993
+ const mergerActions = [];
25994
+ const otherCorpActions = [];
25995
+ for (const action of corporateActions) {
25996
+ if (MERGER_LIKE_TYPES.has(action.type)) {
25997
+ mergerActions.push(action);
25998
+ } else {
25999
+ otherCorpActions.push(action);
26000
+ }
26001
+ }
26002
+ const mergerGroups = groupMergerActions(mergerActions);
26003
+ for (const group of mergerGroups) {
26004
+ timeline.push({ kind: "mergerGroup", sortDate: formatDate(group.date), group });
26005
+ }
26006
+ for (const action of otherCorpActions) {
26007
+ timeline.push({ kind: "corpAction", sortDate: formatDate(action.date), action });
26008
+ }
26009
+ timeline.sort((a, b) => a.sortDate.localeCompare(b.sortDate));
26010
+ if (timeline.length > 0) {
26011
+ logger?.startSection("Chronological Event Processing", 2);
26012
+ for (const event of timeline) {
26013
+ switch (event.kind) {
26014
+ case "trade": {
26015
+ const trade = event.trade;
26016
+ try {
26017
+ if (trade.type === "Buy") {
26018
+ const tradeInfo = {
26019
+ date: formatDate(trade.date),
26020
+ orderNum: trade.orderNum,
26021
+ symbol: trade.symbol,
26022
+ isin: trade.isin,
26023
+ quantity: trade.quantity,
26024
+ unitPrice: trade.unitPrice,
26025
+ currency: trade.currency
26026
+ };
26027
+ addLot(inventory, tradeInfo, logger);
26028
+ const entry = generateBuyEntry(trade, logger);
26029
+ journalEntries.push(entry);
26030
+ logger?.logStep("trade-buy", "success", `Buy ${trade.quantity} ${trade.symbol} @ ${trade.unitPrice} ${trade.currency}`);
26031
+ } else if (trade.type === "Sell") {
26032
+ const consumed = consumeLotsFIFO(inventory, trade.symbol, trade.quantity, logger);
26033
+ const entry = generateSellEntry(trade, consumed, logger);
26034
+ journalEntries.push(entry);
26035
+ const totalCost = consumed.reduce((sum, c) => sum + c.totalCost, 0);
26036
+ const gain = trade.quantity * trade.unitPrice - totalCost;
26037
+ logger?.logStep("trade-sell", "success", `Sell ${trade.quantity} ${trade.symbol} @ ${trade.unitPrice} ${trade.currency}, gain: ${gain.toFixed(2)}`);
26038
+ }
26039
+ } catch (error45) {
26040
+ const message = error45 instanceof Error ? error45.message : String(error45);
26041
+ logger?.logStep("trade", "error", `Failed to process trade: ${message}`);
26042
+ logger?.error(`Trade processing error for ${trade.symbol}`, error45 instanceof Error ? error45 : undefined);
26043
+ }
26044
+ break;
26045
+ }
26046
+ case "dividend": {
26047
+ const dividend = event.dividend;
26048
+ const entry = generateDividendEntry(dividend, logger);
26038
26049
  journalEntries.push(entry);
26039
- const totalCost = consumed.reduce((sum, c) => sum + c.totalCost, 0);
26040
- const gain = trade.quantity * trade.unitPrice - totalCost;
26041
- logger?.logStep("trade-sell", "success", `Sell ${trade.quantity} ${trade.symbol} @ ${trade.unitPrice} ${trade.currency}, gain: ${gain.toFixed(2)}`);
26050
+ logger?.logStep("dividend", "success", `Dividend ${dividend.symbol}: ${dividend.netAmount} ${dividend.currency} (tax: ${dividend.withholdingTax})`);
26051
+ break;
26052
+ }
26053
+ case "mergerGroup": {
26054
+ const groupEntries = processMultiWayMerger(event.group, inventory, lotInventoryPath, projectDir, logger);
26055
+ journalEntries.push(...groupEntries);
26056
+ break;
26057
+ }
26058
+ case "corpAction": {
26059
+ processNonMergerAction(event.action, inventory, journalEntries, logger);
26060
+ break;
26042
26061
  }
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
26062
  }
26048
26063
  }
26049
26064
  logger?.endSection();
26050
26065
  }
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
26066
  logger?.logStep("save-inventory", "start", "Saving lot inventory");
26068
26067
  saveLotInventory(projectDir, lotInventoryPath, inventory, logger);
26069
26068
  logger?.logStep("save-inventory", "success", "Lot inventory saved");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzzle/opencode-accountant",
3
- "version": "0.13.13-next.1",
3
+ "version": "0.13.14-next.1",
4
4
  "description": "An OpenCode accounting agent, specialized in double-entry-bookkepping with hledger",
5
5
  "author": {
6
6
  "name": "ali bengali",