Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feedback] Rule action templating #3606

Open
matt-fidd opened this issue Oct 8, 2024 · 43 comments
Open

[Feedback] Rule action templating #3606

matt-fidd opened this issue Oct 8, 2024 · 43 comments
Labels
experimental feature Related to an experimental feature feedback Single feedback thread for bug reports on a new feature rules Related to rules

Comments

@matt-fidd
Copy link
Contributor

matt-fidd commented Oct 8, 2024

Rule action templating allows rules to dynamically set fields based on transaction data.

To enable the feature - head over to experimental features and toggle the rule action templating feature flag. Next, go to the "rules" page and set up a new rule.

To use it, click the icon on the right hand side of the input box to toggle from "text" to "template" mode:
Text mode:
image
Template mode:
image

Then enter your template. For example, the below will replace the notes field with the VAT paid (standard VAT is 20% in the uk)
image

At the moment, templating is supported for setting:

  • notes
  • date
  • amount
  • cleared (although no boolean helper functions are currently supported)

Full list of available helper functions:

  • regex value regex replacement
  • add num1 num2 ...
  • sub num1 num2 ...
  • div num1 num2 ...
  • mul num1 num2 ...
  • mod num1 num2 ...
  • floor num
  • ceil num
  • round num
  • abs num
  • min num1 num2 ...
  • max num1 num2 ...
  • fixed num1 num2
  • day date
  • month date
  • year date
  • format date format
  • debug value (logs to console)
  • replace value pattern replacement mimics js replace. When pattern is not as /regex/flags it just uses raw value as opposed to {{regex ...
  • replaceAll value pattern replacement mimics js replaceAll
  • addDays date days add x days to the day
  • subDays date days
  • addWeeks date weeks
  • subWeeks date weeks
  • addMonths date months
  • subMonths date months
  • addYears date years
  • subYears date years
  • setDay date day Overflows are handled, 0 will set to last day of month before
  • concat args.. joins all arguments together

Full list of available variables that can be used

  • today (date)
  • account (id)
  • amount (number)
    • remember this is stored without the decimal place. ie. £152 will be 15200. {{div amount 100}} can be used to convert back
  • cleared (boolean)
  • date (date)
  • error (?)
  • imported_id (id)
  • imported_payee (string)
  • is_child (boolean)
  • is_parent (boolean)
  • notes (string)
  • parent_id (id)
  • payee (id)
  • reconciled (boolean)
  • schedule (id)
  • sort_order (number)
  • starting_balance_flag (boolean)
  • tombstone (boolean)
  • transfer_id (id)

Feel free to share your ideas, bug reports and feedback below.

@matt-fidd matt-fidd added rules Related to rules experimental feature Related to an experimental feature feedback Single feedback thread for bug reports on a new feature labels Oct 8, 2024
@youngcw
Copy link
Member

youngcw commented Oct 8, 2024

Some additional variables I would appreciate being added are:

  1. Current Balance of Account (extra bonus points for average monthly balance). This would be nice for automatically determining interest amounts that are included in a mortgage payment for example.

  2. Account balance on day. Useful for determining what a paid in full credit card payment will be dynamically based on current balance of the CC account within a window. (EX. Balance_today- Balance_one_month_prior = payment amount)

@UnderKoen
Copy link
Member

Some additional variables I would appreciate being added are:

  1. Current Balance of Account (extra bonus points for average monthly balance). This would be nice for automatically determining interest amounts that are included in a mortgage payment for example.
  2. Account balance on day. Useful for determining what a paid in full credit card payment will be dynamically based on current balance of the CC account within a window. (EX. Balance_today- Balance_one_month_prior = payment amount)

I think these could best be added as helper functions. Especially the second one.
We could use https://github.com/gastonrobledo/handlebars-async-helpers/ to make an helper that fetches on execution

@mullermn
Copy link

This looks incredibly powerful, I will turn this on and start playing with it.

My condolences to whoever eventually takes on the task of building a UI for this! 😃

@UnderKoen
Copy link
Member

I don't thing there will ever be an UI for this, (at most an helper to show which fields are available). As that it would most likely limit the usage of this function.

@UnderKoen
Copy link
Member

Maybe fun to share, my current rules with templating
image

@IsThisThingStillOn
Copy link

IsThisThingStillOn commented Oct 28, 2024

I'd love to see some examples of using the date functions. As of now I have only successfully got a result with {{today}}. {{day today}} for example doesn't bring up any result. {{date}} doesn't work.

What surprisingly worked was {{regex today "-[0-9]{2}-[0-9]{2}" "-11-01"}} to set the date.

But right now making date calculations doesn't seem to be supported at all, is that assumption correct? I'd love to see that as a feature. Along with other date functions (first of month, end of month etc.)

/E:
After fix #3749 day, month and year work as intended.

To everyone interested, the following rule template will move the transaction to the first of the next month (including changing the year):

{{add (year date) (floor (div (add (month date) 1) 13))}}-{{add (mod (month date) 12) 1}}-1

@londondev77
Copy link

Not sure if I'm using this wrong but I'm trying to do a currency conversion by using the following rule to set the amount:
{{ div amount 119.76 }}

I thought maybe it was down to decimal places so I also tried:
{{ fixed (div amount 119.76) 2 }}

Both result in the following error:
There was an internal error. Please get in touch https://actualbudget.org/contact for support.

If I look at the console, it shows:
Internal error: Error: Can’t convert to integer: -62.83

If I use the same rule but to set the note rather than the amount, then it works fine.

@UnderKoen
Copy link
Member

@londondev77 the amount should be in cents (*100). Decimals are not allowed,

@londondev77
Copy link

Thanks. I misread the note about decimal places in the instructions at the top.

Unfortunately I can't test for the rest of the day as I've used up my GoCardless rate today.

@IsThisThingStillOn
Copy link

@londondev77 You don't need to import transactions to test this. In the edit window of each rule you see a list of matching transactions. Just click the checkbox in the leftmost column and then click "Apply actions" in the top right above said list.

@youngcw
Copy link
Member

youngcw commented Nov 4, 2024

Another useful value for the templating would be the balance of a budget category.

For example in a split rule have a split line of amount = balance of and a second split line of amount = remainder.

@TWilhoWI
Copy link

TWilhoWI commented Nov 7, 2024

Could someone help me with following: I got a monthly payment for savings. This is categorised as payment, but I want to categorise it a deposit. So from - to +. How can I do this? Amount does change every month.

@UnderKoen
Copy link
Member

UnderKoen commented Nov 7, 2024

@TWilhoWI
image
{{mul amount -1}}

@TWilhoWI
Copy link

TWilhoWI commented Nov 7, 2024

Thank you very much!

@nmathey
Copy link
Contributor

nmathey commented Nov 7, 2024

Wow this looks powerful!
would it be possible to extend templating to "conditions match" criterias?
Basically I would like to action a rule if the amount is a decimal number.

@IsThisThingStillOn
Copy link

@nmathey
You can already so that with the regular filters

For payments:
amount is less than -0.00
amount is greater than -1.00

For deposits:
amount is greater than -0,00
amount is less than +1,00

@nmathey
Copy link
Contributor

nmathey commented Nov 12, 2024

Mmmm rule doesn't match any

image

image

@youngcw
Copy link
Member

youngcw commented Nov 12, 2024

Mmmm rule doesn't match any

image

image

There isn't any templating in that rule. Also it looks like that transaction is out of range.

@nmathey
Copy link
Contributor

nmathey commented Nov 12, 2024

Yeah I just tried to apply whats @IsThisThingStillOn were referring too even if it looked weird for me as is.
I want to basically match any decimal number not only a range and do not match if integer: that was my point to extend templating rule in "conditions match" in order to extend filter possibility.
If it is still valid for my use case, I'll switch to discord to avoid polluting this thread.

@UnderKoen
Copy link
Member

Basically I would like to action a rule if the amount is a decimal number.

We could achieve this by adding regex matching to the amount field. I will look if I can get this working.

@gael-vanderlee
Copy link

My imported payees always start with "CARDXXXX" or "CARDXXXX DD/MM", would this new feature allow me to remove those automatically ?

@youngcw
Copy link
Member

youngcw commented Nov 15, 2024

My imported payees always start with "CARDXXXX" or "CARDXXXX DD/MM", would this new feature allow me to remove those automatically ?

It could, but you probably should be able to use a regular "imported_payee"-"contains" rule and not need to use a template rule.

@gael-vanderlee
Copy link

gael-vanderlee commented Nov 15, 2024

@youngcw Ah nice !
How would I set that up in the payee section ? I'd like a rule that goes for any transaction of the form CARD XXXX DD/MM YYYYY:

  • If imported payee matches (regex expression)
  • Set payee to YYYY

I'm struggling to know how to extract the YYYY information from the imported payee to set it in the payee field. Hope that makes sense

@youngcw
Copy link
Member

youngcw commented Nov 15, 2024

@youngcw Ah nice ! How would I set that up in the payee section ? I'd like a rule that goes for any transaction of the form CARD XXXX DD/MM YYYYY:

  • If imported payee matches (regex expression)
  • Set payee to YYYY

I'm struggling to know how to extract the YYYY information from the imported payee to set it in the payee field. Hope that makes sense

I don't think you need to extract anything. Use if imported payee contains "Grocery Store", set payee "Grocery Store"

@gael-vanderlee
Copy link

gael-vanderlee commented Nov 15, 2024

@youngcw Ah yes I already do that, but a universal rule on import would help a lot with readability when sorting through the transactions. Hopefully that's possible with rule action templating.

Since the proposed solution includes regex replacement and imported payee, it's looking promising !

@matt-fidd
Copy link
Contributor Author

matt-fidd commented Nov 15, 2024

@youngcw Ah yes I already do that, but a universal rule on import would help a lot with readability when sorting through the transactions. Hopefully that's possible with rule action templating.

I think you should be able to do something like the below... it might need a bit of tweaking though

if: imported payee contains "CARD" (regex is not availble for rule criteria) AND account = the account you're seeing this on
set payee = {{regex imported_payee "^CARD\s.*\s\d{2}\\\d{2}\s(.*)$" "$1"}}

@gael-vanderlee
Copy link

gael-vanderlee commented Nov 15, 2024

Had to make a few tweaks (mine is in french so "Carte XXXXX" and the date field is optional). For those interested, the final formula is {{regex imported_payee "^Carte X\d{4}(\s+\d{2}/\d{2})?\s+(.*)$" "$2"}}
Thank you very much for the help ! Came to github to make a feature request and left with a working solution :)

@fossum
Copy link

fossum commented Nov 29, 2024

My only issue right now is, I can't choose the order. I'd like it to be above some of my set payee rules, but it's right in the middle for some reason.

@Chuckame
Copy link

Chuckame commented Dec 11, 2024

The UI is quite difficult, even as a software engineer who loves regex 😄

There is no feedback on the regex execution: is the regex valid ? what is going on if I apply the regex (a dry-run is missing) ?

I'm doing exactly the same as many of you: extract payee and date from the imported_payee.

Here is my solution for the pattern Cb <payee> Fact DDMMYY <card number>:

  • when imported_payee matches ^Cb .+ Fact \d{6} .*$
  • set payee (name) to template {{regex imported_payee "^Cb (.+) Fact (\d{2})(\d{2})(\d{2}) .*$" "$1"}}
  • set date to template {{regex imported_payee "^Cb (.+) Fact (\d{2})(\d{2})(\d{2}) .*$" "20$4-$3-$2"}}

Note

The date is not following the display format but the ISO8601 format like YYYY-MM-DD, the reason why I prepend 20 to the year group 4

Btw, it could be awesome to use the condition catched groups to to repeat the regex like:

  • when imported_payee matches ^Cb (.+) Fact (\d{2})(\d{2})(\d{2}) .*$
  • set payee (name) to template {{regex_replacement "$1"}}
  • set date to template {{regex_replacement "20$4-$3-$2"}}

And even better using group names to better understand the catched groups:

  • when imported_payee matches ^Cb (?<payee>.+) Fact (?<day>\d{2})(?<month>\d{2})(?<year>\d{2}) .*$
  • set payee (name) to template {{regex_replacement "${payee}"}}
  • set date to template {{regex_replacement "20${year}-${month}-${day}"}}

Quick proposal: change the date template placeholder from nothing to YYYY-MM-DD (ISO8601 date)

@tcpr1
Copy link

tcpr1 commented Jan 8, 2025

I would like to multiply the amount of a transaction by the total number os installments.

Example, in the notes I have: installment 01/03.
Is it possible to get the number after "/" an use it to multiple the amount, like a variable?

Something like: Set amount {{mul amount N}} where in this case N = 03.

@UnderKoen
Copy link
Member

UnderKoen commented Jan 9, 2025

@tcpr1 You can do the following
{{mul amount (regex notes "/^.*\d+/(\d+).*$/" "$1")}}

@tcpr1
Copy link

tcpr1 commented Jan 10, 2025

@tcpr1 You can do the following {{mul amount (regex notes "/^.*\d+/(\d+).*$/" "$1")}}

Perfect, thank you! Very cool feature.

@psybers
Copy link
Contributor

psybers commented Jan 12, 2025

I think if you enter in a bad/invalid template you just get a generic error. Might be nice to give better feedback to the user that the problem is their template is bad. As an example, try entering in mul 0.5 {{amount}}.

@tostasmistas
Copy link

tostasmistas commented Jan 22, 2025

Nice feature!

Do you know if it's possible to combine the format helper function with other functions? I wanted to set the notes field to the first of the next month, but with the date formatted as "MMMM yyyy". So maybe something like:

{{format (add (year date) (floor (div (add (month date) 1) 13))}}-{{add (mod (month date) 12) 1}}-1) "MMMM yyyy"}}

Although the above comes up as Invalid handlebars template.

@snqyz
Copy link

snqyz commented Jan 25, 2025

Thanks for this feature!

I am experiencing a bug where the regex substitution works only on first match.

Example

My rule: {{regex notes "\s+" " "}}
Input: "foo bar test"
Output: "foo bar test"

@UnderKoen
Copy link
Member

@snqyz this is intented. It uses the normal replace behaviour.

You should use {{regex notes "/\s+/g" " "}}

The global flag let i match more than once

@UnderKoen
Copy link
Member

Do you know if it's possible to combine the format helper function with other functions? I wanted to set the notes field to the first of the next month, but with the date formatted as "MMMM yyyy".

@tostasmistas unfortunatly currently not. I will be adding an function to changing dates by an amount. And a method for concatenation

@mr-ister
Copy link

I'm trying to set the transaction date based on the imported_payee field, but for some reason I keep getting an error message (Something internally went wrong. You may want to restart the app if anything looks wrong. Please report this as a new issue on Github.).

My template looks like this:

  • If imported payee is not nothing
  • Then set date to {{regex imported_payee "(\d{2})\.(\d{2})\.\s\d{2}:\d{2}" "2025-$2-$1"}}

My strings look like this:

  • Pos 5,06 at K20 28.01. 09:59 O
  • Store 3114 2360 K20 28.01. 14:34

Any ideas where I went wrong? Thanks!

@matt-fidd
Copy link
Contributor Author

@mr-ister I've not tested this but I think the replacement will only work on the matched substring.

Try changing the regex to match the entire string.

- {{regex imported_payee "(\d{2})\.(\d{2})\.\s\d{2}:\d{2}" "2025-$2-$1"}}
+ {{regex imported_payee "^.*(\d{2})\.(\d{2})\.\s\d{2}:\d{2}.*$" "2025-$2-$1"}}

@mr-ister
Copy link

That's perfect, it's working, thank you!

@IsThisThingStillOn
Copy link

Can someone share working examples for date functions like addDays, subDays etc. and how to set a new date with them?

I can't get them to work.

@UnderKoen
Copy link
Member

@IsThisThingStillOn

Can someone share working examples for date functions like addDays, subDays etc. and how to set a new date with them?

I can't get them to work.

This will be fixed with #4356

matt-fidd added a commit to actualbudget/docs that referenced this issue Feb 13, 2025
Closes #480

Feedback issue for the reference
actualbudget/actual#3606

This is a starting point for a more fleshed out version, adding examples
in the future would be good
@b-neufeld
Copy link

This is awesome. I was looking for something like this... and found it!

Some ideas & suggestions:

  1. The text mode/template mode icons are not immediately intuitive and there's no mouseover label for what they do. Suggest adding a mouseover to help users understand which is which ("am I switching TO this mode, or am I in this mode now?") Or maybe instead of <> the symbol should be { }?
  2. Suggest the error-checking logic that generates the "Invalid handlebars template" message is triggered/updated when the "Apply actions" button is clicked, or even after clicking out of the action field. I was trying to "preview" the logic on one transaction and getting no feedback, and only got the error on Save. Conversely, if I fixed my logic and clicked "Apply actions" after that, I'd be successfully updating transactions but still seeing an error message.
  3. Would it be possible to enable this with the "append/prepend to" function for the notes field? In my use case below, I lose the small piece of information that the .qfx import originally drops into the Notes field, since there is no such field as imported_notes to play with.

My simple use case for this is as follows. I import all transactions as .QFX files from my bank. Interac e-Transfers (Canadians will know) can be a mess, with payee names getting cut off and/or generating a huge number of Actual payees.

Before I had completely replaced the Imported Payee (which might be something like "INTERAC e-Transfer From: Maria" with the payee "Interac e-Transfer" (I usually don't care about individual names as these are mostly one-off Marketplace transactions). However, the downside is that that little bit of name that might have helped me categorize the transaction was gone.

Solution: A simple Find and Replace on the imported_payee and drop that in the notes field.

Image

Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
experimental feature Related to an experimental feature feedback Single feedback thread for bug reports on a new feature rules Related to rules
Projects
None yet
Development

No branches or pull requests