@fuzzle/opencode-accountant 0.12.0 → 0.12.1-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 +22 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23936,17 +23936,7 @@ function determineClosingBalance(csvFile, config2, importContext, manualClosingB
|
|
|
23936
23936
|
if (analysisBalance) {
|
|
23937
23937
|
return { closingBalance: analysisBalance, metadata, fromCSVAnalysis: true };
|
|
23938
23938
|
}
|
|
23939
|
-
|
|
23940
|
-
const exampleBalance = `${currency} <amount>`;
|
|
23941
|
-
const retryCmd = buildRetryCommand(importContext.id, exampleBalance);
|
|
23942
|
-
return {
|
|
23943
|
-
error: buildErrorResult2({
|
|
23944
|
-
csvFile: relativeCsvPath,
|
|
23945
|
-
error: "No closing balance found in CSV metadata or data",
|
|
23946
|
-
hint: `Provide closingBalance parameter manually. Example retry: ${retryCmd}`,
|
|
23947
|
-
metadata
|
|
23948
|
-
})
|
|
23949
|
-
};
|
|
23939
|
+
return { notAvailable: true, metadata };
|
|
23950
23940
|
}
|
|
23951
23941
|
function buildRetryCommand(contextId, closingBalance, account) {
|
|
23952
23942
|
const parts = ["reconcile-statement", `--contextId ${contextId}`];
|
|
@@ -24071,6 +24061,14 @@ async function reconcileStatement(directory, agent, options, configLoader = load
|
|
|
24071
24061
|
}
|
|
24072
24062
|
const { csvFile, relativePath: relativeCsvPath } = csvResult;
|
|
24073
24063
|
const balanceResult = determineClosingBalance(csvFile, config2, importContext, options.closingBalance, relativeCsvPath, rulesDir);
|
|
24064
|
+
if ("notAvailable" in balanceResult) {
|
|
24065
|
+
return JSON.stringify({
|
|
24066
|
+
success: true,
|
|
24067
|
+
skipped: true,
|
|
24068
|
+
csvFile: relativeCsvPath,
|
|
24069
|
+
note: "No closing balance available \u2014 reconciliation skipped"
|
|
24070
|
+
});
|
|
24071
|
+
}
|
|
24074
24072
|
if ("error" in balanceResult) {
|
|
24075
24073
|
return balanceResult.error;
|
|
24076
24074
|
}
|
|
@@ -25915,9 +25913,9 @@ function parseExchangeRows(csvPath) {
|
|
|
25915
25913
|
if (fields.length < 9)
|
|
25916
25914
|
continue;
|
|
25917
25915
|
const [type2, , startedDate, , description, amountStr, , currency] = fields;
|
|
25918
|
-
if (type2 !== "EXCHANGE")
|
|
25916
|
+
if (type2?.toUpperCase() !== "EXCHANGE")
|
|
25919
25917
|
continue;
|
|
25920
|
-
if (
|
|
25918
|
+
if (!/^Exchanged to [A-Z]{3}$/.test(description ?? ""))
|
|
25921
25919
|
continue;
|
|
25922
25920
|
const rawAmount = parseFloat(amountStr);
|
|
25923
25921
|
const date5 = parseRevolutDatetime(startedDate);
|
|
@@ -25939,8 +25937,8 @@ function matchExchangePairs(rowsByCsv) {
|
|
|
25939
25937
|
for (const rows of rowsByCsv.values()) {
|
|
25940
25938
|
allRows.push(...rows);
|
|
25941
25939
|
}
|
|
25942
|
-
const sources = allRows.filter((r) => r.amount
|
|
25943
|
-
const targets = allRows.filter((r) => r.amount
|
|
25940
|
+
const sources = allRows.filter((r) => r.amount < 0);
|
|
25941
|
+
const targets = allRows.filter((r) => r.amount > 0);
|
|
25944
25942
|
const matches = [];
|
|
25945
25943
|
const matchedSourceIndices = new Set;
|
|
25946
25944
|
const matchedTargetIndices = new Set;
|
|
@@ -25958,8 +25956,8 @@ function matchExchangePairs(rowsByCsv) {
|
|
|
25958
25956
|
if (!source.description.includes(targetCurrency))
|
|
25959
25957
|
continue;
|
|
25960
25958
|
matches.push({
|
|
25961
|
-
source,
|
|
25962
|
-
target
|
|
25959
|
+
source: { ...source, amount: Math.abs(source.amount) },
|
|
25960
|
+
target
|
|
25963
25961
|
});
|
|
25964
25962
|
matchedSourceIndices.add(si);
|
|
25965
25963
|
matchedTargetIndices.add(ti);
|
|
@@ -25979,11 +25977,9 @@ function formatExchangeEntry(match2) {
|
|
|
25979
25977
|
const targetCurrency = target.currency;
|
|
25980
25978
|
const sourceAmount = formatAmount3(source.amount);
|
|
25981
25979
|
const targetAmount = formatAmount3(target.amount);
|
|
25982
|
-
const rate = target.amount / source.amount;
|
|
25983
|
-
const rateStr = formatRate(rate);
|
|
25984
25980
|
return [
|
|
25985
25981
|
`${date5} ${description}`,
|
|
25986
|
-
` assets:bank:revolut:${sourceCurrency.toLowerCase()} -${sourceAmount} ${sourceCurrency}
|
|
25982
|
+
` assets:bank:revolut:${sourceCurrency.toLowerCase()} -${sourceAmount} ${sourceCurrency}`,
|
|
25987
25983
|
` equity:currency:conversion ${sourceAmount} ${sourceCurrency}`,
|
|
25988
25984
|
` equity:currency:conversion -${targetAmount} ${targetCurrency}`,
|
|
25989
25985
|
` assets:bank:revolut:${targetCurrency.toLowerCase()} ${targetAmount} ${targetCurrency}`
|
|
@@ -25993,9 +25989,6 @@ function formatExchangeEntry(match2) {
|
|
|
25993
25989
|
function formatAmount3(amount) {
|
|
25994
25990
|
return amount.toFixed(2);
|
|
25995
25991
|
}
|
|
25996
|
-
function formatRate(rate) {
|
|
25997
|
-
return rate.toFixed(4);
|
|
25998
|
-
}
|
|
25999
25992
|
function isDuplicate2(match2, journalContent) {
|
|
26000
25993
|
const date5 = match2.source.dateStr;
|
|
26001
25994
|
const description = match2.source.description;
|
|
@@ -26639,6 +26632,12 @@ async function executeReconcileStep(context, contextId, logger) {
|
|
|
26639
26632
|
account: context.options.account
|
|
26640
26633
|
}, context.configLoader, context.hledgerExecutor);
|
|
26641
26634
|
const reconcileParsed = JSON.parse(reconcileResult);
|
|
26635
|
+
if (reconcileParsed.skipped) {
|
|
26636
|
+
logger?.logStep("Reconcile", "success", "Skipped \u2014 no closing balance available");
|
|
26637
|
+
context.result.steps.reconcile = buildStepResult(true, "Reconciliation skipped \u2014 no closing balance available", { success: true, skipped: true, note: reconcileParsed.note });
|
|
26638
|
+
logger?.endSection();
|
|
26639
|
+
return;
|
|
26640
|
+
}
|
|
26642
26641
|
const message = reconcileParsed.success ? `Balance reconciled: ${reconcileParsed.actualBalance}` : `Balance mismatch: expected ${reconcileParsed.expectedBalance}, got ${reconcileParsed.actualBalance}`;
|
|
26643
26642
|
logger?.logStep("Reconcile", reconcileParsed.success ? "success" : "error", message);
|
|
26644
26643
|
if (reconcileParsed.success) {
|