[GH-ISSUE #3496] [Feature] Custom Script Editor for Rules #15681

Closed
opened 2026-04-14 18:43:20 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @DenizUgur on GitHub (Sep 24, 2024).
Original GitHub issue: https://github.com/actualbudget/actual/issues/3496

Verified feature request does not already exist?

  • I have searched and found no existing issue

💻

  • Would you like to implement this feature?

Pitch: what problem are you trying to solve?

Since the payees or notes in transactions can be limited in length, banks often shorten them. While it’s usually easy to decipher these abbreviations using regex capture groups, as proposed in PR #3305, there are instances where additional context is necessary. Sometimes, you need to access other transactions across different accounts to fully understand them.

For example, consider the following table:

Account Payee Notes Amount
Chequing Transfer foo bar 4788 3000$
Savings bar baz 4788 Transfer -3000$

Neither the payee nor the notes provide enough information about the source or destination of the funds, but they both reference a unique transaction ID.

A human can easily deduce that these two transactions are related, but to use Actual's rules, we need to add more context to each transaction.

With the proposed solution below, I would convert the table as follows and then use Actual’s rules to manage transfer logic (as explained here).

Account Payee Notes Amount
Chequing Transfer 4788 - From Savings 3000$
Savings 4788 - To Chequing Transfer -3000$

Describe your ideal solution to this problem

I would love to have a scripting feature for the rules. Users could write scripts to match specific transactions for modification and then access other transactions via exposed methods within the script to carry out these changes.

Examples

markdown-it/linkify-it

This markdown parser allows developers to create their own handlers. The following snippet is taken from their README, but I’ve shortened it to provide a brief overview. The tool uses two functions, validate and normalize, to determine where to modify the text and how to apply the changes.

linkify.add('@', {
  validate: function (text, pos, self) {
    ...
    return 0;
  },
  normalize: function (match) {
    match.url = 'https://twitter.com/' + match.url.replace(/^@/, '');
  }
});

gpac/gpac

This multimedia packaging tool allows you to write JavaScript files that the tool executes within a context where global methods are accessible to control the flow of the program.

Proposal

I propose adding a script editor to the rules window. This would allow users to write scripts like the following to solve the issue described at the beginning:

actual.match = (transaction, context) => {
    const id = transaction.notes.match("\\d+");
    return id !== null;
};

actual.modify = (transaction, context) => {
    const other = context.accounts
        .filter((a) => a.id !== transaction.account.id)
        .find((t) => t.includes(id));
    transaction.notes = `Funds from ${other.account} (${id})`;
};

Teaching and learning

TBD

Originally created by @DenizUgur on GitHub (Sep 24, 2024). Original GitHub issue: https://github.com/actualbudget/actual/issues/3496 ### Verified feature request does not already exist? - [X] I have searched and found no existing issue ### 💻 - [X] Would you like to implement this feature? ### Pitch: what problem are you trying to solve? Since the payees or notes in transactions can be limited in length, banks often shorten them. While it’s usually easy to decipher these abbreviations using regex capture groups, as proposed in PR #3305, there are instances where additional context is necessary. Sometimes, you need to access other transactions across different accounts to fully understand them. For example, consider the following table: | Account | Payee | Notes | Amount | |---------- |----------- |----------------- |-------- | | Chequing | Transfer | foo bar **4788** | 3000$ | | Savings | bar baz **4788** | Transfer | -3000$ | Neither the payee nor the notes provide enough information about the source or destination of the funds, but they both reference a unique **transaction ID**. A human can easily deduce that these two transactions are related, but to use Actual's rules, we need to add more context to each transaction. With the proposed solution below, I would convert the table as follows and then use Actual’s rules to manage transfer logic (as explained [here](https://actualbudget.org/docs/budgeting/rules/custom#q-i-use-bank-sync--how-do-i-create-transfers-and-not-make-duplicates)). | Account | Payee | Notes | Amount | |---------- |-------------------- |--------------------- |-------- | | Chequing | Transfer | 4788 - **From Savings** | 3000$ | | Savings | 4788 - **To Chequing** | Transfer | -3000$ | ### Describe your ideal solution to this problem I would love to have a scripting feature for the rules. Users could write scripts to match specific transactions for modification and then access other transactions via exposed methods within the script to carry out these changes. ## Examples ### [markdown-it/linkify-it](https://github.com/markdown-it/linkify-it) This markdown parser allows developers to create their own handlers. The following snippet is taken from their [README](https://github.com/markdown-it/linkify-it?tab=readme-ov-file#example-2-add-twitter-mentions-handler), but I’ve shortened it to provide a brief overview. The tool uses two functions, `validate` and `normalize`, to determine where to modify the text and how to apply the changes. ```js linkify.add('@', { validate: function (text, pos, self) { ... return 0; }, normalize: function (match) { match.url = 'https://twitter.com/' + match.url.replace(/^@/, ''); } }); ``` ### [gpac/gpac](https://github.com/gpac/gpac) This multimedia packaging tool allows you to write JavaScript files that the tool executes within a context where global methods are accessible to control the flow of the program. ## Proposal I propose adding a script editor to the rules window. This would allow users to write scripts like the following to solve the issue described at the beginning: ```js actual.match = (transaction, context) => { const id = transaction.notes.match("\\d+"); return id !== null; }; actual.modify = (transaction, context) => { const other = context.accounts .filter((a) => a.id !== transaction.account.id) .find((t) => t.includes(id)); transaction.notes = `Funds from ${other.account} (${id})`; }; ``` ### Teaching and learning TBD
GiteaMirror added the needs votesfeature labels 2026-04-14 18:43:20 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Sep 24, 2024):

Thanks for sharing your idea!

This repository uses lodash style issue management for enhancements. That means enhancement issues are automatically closed. This doesn’t mean we don’t accept feature requests, though! We will consider implementing ones that receive many upvotes, and we welcome contributions for any feature requests marked as needing votes (just post a comment first so we can help you make a successful contribution).

The enhancement backlog can be found here: https://github.com/actualbudget/actual/issues?q=label%3A%22needs+votes%22+sort%3Areactions-%2B1-desc+

Don’t forget to upvote the top comment with 👍!

<!-- gh-comment-id:2371918087 --> @github-actions[bot] commented on GitHub (Sep 24, 2024): :sparkles: Thanks for sharing your idea! :sparkles: This repository uses lodash style issue management for enhancements. That means enhancement issues are automatically closed. This doesn’t mean we don’t accept feature requests, though! We will consider implementing ones that receive many upvotes, and we welcome contributions for any feature requests marked as needing votes (just post a comment first so we can help you make a successful contribution). The enhancement backlog can be found here: https://github.com/actualbudget/actual/issues?q=label%3A%22needs+votes%22+sort%3Areactions-%2B1-desc+ Don’t forget to upvote the top comment with 👍! <!-- feature-auto-close-comment -->
Author
Owner

@DenizUgur commented on GitHub (Sep 25, 2024):

I examined the code related to the rules, and the implementation should be fairly straightforward. A new action type, script, needs to be implemented under the Action.exec method. The nx-js/compiler-util library seems to offer a secure way to evaluate JS code with the provided context. A relatively significant change might be required to make a list of transactions for each account available to the script. That should cover the backend work.

The frontend might be a bit more complex, as we'll likely need a code editor, syntax checker, and other related features.

9c2bb9b3de/packages/loot-core/src/server/accounts/rules.ts (L550-L554)

I'm happy to work on this, as long as I can receive feedback on the team's thoughts and possibly some guidance on how to retrieve the transactions for each account available within execActions.

<!-- gh-comment-id:2372632088 --> @DenizUgur commented on GitHub (Sep 25, 2024): I examined the code related to the rules, and the implementation should be fairly straightforward. A new action type, `script`, needs to be implemented under the `Action.exec` method. The [nx-js/compiler-util](https://github.com/nx-js/compiler-util) library seems to offer a secure way to evaluate JS code with the provided context. A relatively significant change might be required to make a list of transactions for each account available to the script. That should cover the backend work. The frontend might be a bit more complex, as we'll likely need a code editor, syntax checker, and other related features. https://github.com/actualbudget/actual/blob/9c2bb9b3dec8555d407ec936ac1baa311f04f7fd/packages/loot-core/src/server/accounts/rules.ts#L550-L554 I'm happy to work on this, as long as I can receive feedback on the team's thoughts and possibly some guidance on how to retrieve the transactions for each account available within `execActions`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#15681