@fuzzle/opencode-accountant 0.7.0 → 0.7.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.
Files changed (2) hide show
  1. package/dist/index.js +45 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -17272,6 +17272,11 @@ function validateDetectionRule(providerName, index, rule) {
17272
17272
  }
17273
17273
  }
17274
17274
  }
17275
+ if (ruleObj.closingBalanceField !== undefined) {
17276
+ if (typeof ruleObj.closingBalanceField !== "string" || ruleObj.closingBalanceField === "") {
17277
+ throw new Error(`Invalid config: provider '${providerName}' detect[${index}].closingBalanceField must be a non-empty string`);
17278
+ }
17279
+ }
17275
17280
  return {
17276
17281
  filenamePattern: ruleObj.filenamePattern,
17277
17282
  header: ruleObj.header,
@@ -17279,7 +17284,8 @@ function validateDetectionRule(providerName, index, rule) {
17279
17284
  skipRows: ruleObj.skipRows,
17280
17285
  delimiter: ruleObj.delimiter,
17281
17286
  renamePattern: ruleObj.renamePattern,
17282
- metadata: ruleObj.metadata
17287
+ metadata: ruleObj.metadata,
17288
+ closingBalanceField: ruleObj.closingBalanceField
17283
17289
  };
17284
17290
  }
17285
17291
  function validateProviderConfig(name, config2) {
@@ -17386,17 +17392,43 @@ function parseCSVPreview(content, skipRows = 0, delimiter = ",") {
17386
17392
  firstRow: result.data[0]
17387
17393
  };
17388
17394
  }
17395
+ function extractLastRowField(content, skipRows, delimiter, fieldName) {
17396
+ let csvContent = content;
17397
+ if (skipRows > 0) {
17398
+ const lines = content.split(`
17399
+ `);
17400
+ csvContent = lines.slice(skipRows).join(`
17401
+ `);
17402
+ }
17403
+ const result = import_papaparse.default.parse(csvContent, {
17404
+ header: true,
17405
+ skipEmptyLines: true,
17406
+ delimiter
17407
+ });
17408
+ if (result.data.length === 0)
17409
+ return;
17410
+ const lastRow = result.data[result.data.length - 1];
17411
+ const value = lastRow[fieldName];
17412
+ return value ? value.trim() : undefined;
17413
+ }
17389
17414
  function normalizeHeader(fields) {
17390
17415
  return fields.map((f) => f.trim()).join(",");
17391
17416
  }
17392
17417
  function detectProvider(filename, content, config2) {
17393
17418
  for (const [providerName, providerConfig] of Object.entries(config2.providers)) {
17394
17419
  for (const rule of providerConfig.detect) {
17420
+ let filenameMetadata = {};
17395
17421
  if (rule.filenamePattern !== undefined) {
17396
17422
  const filenameRegex = new RegExp(rule.filenamePattern);
17397
- if (!filenameRegex.test(filename)) {
17423
+ const filenameMatch = filenameRegex.exec(filename);
17424
+ if (!filenameMatch) {
17398
17425
  continue;
17399
17426
  }
17427
+ if (filenameMatch.groups) {
17428
+ for (const [key, value] of Object.entries(filenameMatch.groups)) {
17429
+ filenameMetadata[key.replace(/_/g, "-")] = value;
17430
+ }
17431
+ }
17400
17432
  }
17401
17433
  const skipRows = rule.skipRows ?? 0;
17402
17434
  const delimiter = rule.delimiter ?? ",";
@@ -17415,21 +17447,20 @@ function detectProvider(filename, content, config2) {
17415
17447
  if (!rawCurrency) {
17416
17448
  continue;
17417
17449
  }
17418
- const metadata = extractMetadata(content, skipRows, delimiter, rule.metadata);
17419
- const outputFilename = generateOutputFilename(rule.renamePattern, metadata);
17420
- const normalizedCurrency = providerConfig.currencies[rawCurrency];
17421
- if (!normalizedCurrency) {
17422
- return {
17423
- provider: providerName,
17424
- currency: rawCurrency.toLowerCase(),
17425
- rule,
17426
- outputFilename,
17427
- metadata: Object.keys(metadata).length > 0 ? metadata : undefined
17428
- };
17450
+ const headerMetadata = extractMetadata(content, skipRows, delimiter, rule.metadata);
17451
+ const metadata = { ...filenameMetadata, ...headerMetadata };
17452
+ if (rule.closingBalanceField) {
17453
+ const closingBalance = extractLastRowField(content, skipRows, delimiter, rule.closingBalanceField);
17454
+ if (closingBalance) {
17455
+ metadata["closing-balance"] = closingBalance;
17456
+ }
17429
17457
  }
17458
+ const normalizedCurrency = providerConfig.currencies[rawCurrency];
17459
+ metadata["currency"] = normalizedCurrency || rawCurrency.toLowerCase();
17460
+ const outputFilename = generateOutputFilename(rule.renamePattern, metadata);
17430
17461
  return {
17431
17462
  provider: providerName,
17432
- currency: normalizedCurrency,
17463
+ currency: normalizedCurrency || rawCurrency.toLowerCase(),
17433
17464
  rule,
17434
17465
  outputFilename,
17435
17466
  metadata: Object.keys(metadata).length > 0 ? metadata : undefined
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzzle/opencode-accountant",
3
- "version": "0.7.0",
3
+ "version": "0.7.1-next.1",
4
4
  "description": "An OpenCode accounting agent, specialized in double-entry-bookkepping with hledger",
5
5
  "author": {
6
6
  "name": "ali bengali",