Skip to content

Preserve manual edits

Sometimes you need to tweak an imported transaction without changing your import rules. For example, you might correct a narration, add a hashtag, or fix a posting account. You can edit the transaction directly in your Beancount file. However, because the transaction still has the same import-id, the next time you run beanhub import, the engine will overwrite your changes with the transaction generated from the rules.

To keep your manual edits while still allowing the import engine to update other parts of the transaction, use the import-override metadata.

The problem

Suppose you have an imported transaction like this:

2024-04-15 * "Circleci"
  import-id: "bAPgjNEZj6FaEdqGQP4lsx33gAbQw9umpQAmk"
  Assets:Bank:US:MyBank                                10.00 USD
  Expenses:Engineering:ServiceSubscription            -10.00 USD

You discover this particular charge was actually a refund due to a billing error. You update the narration to make that clear:

2024-04-15 * "CircleCI refund due to billing error"
  import-id: "bAPgjNEZj6FaEdqGQP4lsx33gAbQw9umpQAmk"
  Assets:Bank:US:MyBank                                10.00 USD
  Expenses:Engineering:ServiceSubscription            -10.00 USD

But when you run beanhub import, the engine overwrites your change and restores the original narration from the rules. That happens because the engine matches on import-id and replaces the entire transaction with the rule-generated one.

The solution: import-override

Add the import-override metadata to the transaction to control which fields the import engine is allowed to override. This lets you preserve your manual edits while still allowing updates to other parts of the transaction when the source data changes.

Modes

  • none — Do not override anything. Keep the transaction exactly as you edited it. The import engine will not modify this transaction.
  • all — Override the entire transaction with the one generated from the rules. This is the default behavior when import-override is not set.

Fine-grained control

Instead of none or all, you can specify exactly which fields may be overridden by listing them as a comma-separated string. Only the listed fields will be updated; everything else stays as you edited it.

Available values:

Value Description
date Date of the transaction (e.g., 2024-09-01)
flag Transaction flag (e.g., * or !)
narration Narration text (e.g., "Purchase lunch.")
payee Payee (e.g., "AT&T")
hashtags Hashtags (e.g., "#Rent")
links Links (e.g., "^Travel-to-eu-2023")
postings Postings (accounts and amounts)
amount Amounts in postings (can be used with postings)

You can combine any of these. For example, to allow only date and flag to be overridden:

import-override: "date,flag"

Example: preserve narration only

For the CircleCI refund example, you want to keep your custom narration but still allow the import engine to update the date, amounts, and postings if the source data changes. Add import-override with the fields you do want to allow overriding:

2024-04-15 * "CircleCI refund due to billing error"
  import-id: "bAPgjNEZj6FaEdqGQP4lsx33gAbQw9umpQAmk"
  import-override: "date,postings,flag"
  Assets:Bank:US:MyBank                              10.00 USD
  Expenses:Engineering:ServiceSubscription          -10.00 USD

By omitting narration and payee from the list, your manual edits to those fields are preserved. If the source import file changes (e.g., the date or amount is corrected), the engine will still update those fields.

Example: lock a transaction completely

If you want the import engine to never touch a transaction again, set:

import-override: "none"

The transaction will remain exactly as you wrote it, even when you run beanhub import.