[GH-ISSUE #1827] [Bug]: API import transactions overrides some fields, not others, hard to make sense #49811

Open
opened 2026-04-30 11:32:50 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @cpainchaud on GitHub (Oct 26, 2023).
Original GitHub issue: https://github.com/actualbudget/actual/issues/1827

Verified issue does not already exist?

  • I have searched and found no existing issue

What happened?

when using API to import transactions, if they already exist (same imported_id) then an odd behavior happens:

  • if the 'updated' transaction has changed amount, it will not take it in account and keep the old one
  • if the 'updated' transaction has changed the 'cleared' status, it will use that new status. ommiting the status will force it to True

I do believe it should be the contrary:

  • there are good reason to update an amount and it should not be ignored by the import call
  • 'Cleared' should not be touched, it's what people use to check operations was reviewed.

selfhosted fresh v23.10.0 servers and client. API version 6.2.1

What error did you receive?

no error in particular

Where are you hosting Actual?

Docker

What browsers are you seeing the problem on?

Chrome, Other

Operating System

Windows 10

Originally created by @cpainchaud on GitHub (Oct 26, 2023). Original GitHub issue: https://github.com/actualbudget/actual/issues/1827 ### Verified issue does not already exist? - [X] I have searched and found no existing issue ### What happened? when using API to import transactions, if they already exist (**same imported_id**) then an odd behavior happens: - if the 'updated' transaction has changed amount, it will not take it in account and keep the old one - if the 'updated' transaction has changed the 'cleared' status, it will use that new status. ommiting the status will force it to True I do believe it should be the contrary: - there are good reason to update an amount and it should not be ignored by the import call - 'Cleared' should not be touched, it's what people use to check operations was reviewed. selfhosted fresh v23.10.0 servers and client. API version 6.2.1 ### What error did you receive? no error in particular ### Where are you hosting Actual? Docker ### What browsers are you seeing the problem on? Chrome, Other ### Operating System Windows 10
GiteaMirror added the APIbug labels 2026-04-30 11:32:50 -05:00
Author
Owner

@tavlima commented on GitHub (Dec 17, 2023):

Here is another perspective: depending on what your import source is, it may actually be the source of truth, including whether the transaction is cleared or not.

But I agree with you that the current behavior is non-intuitive. Here is what I think would make some sense, from what I could see:

  1. an additional boolean argument to the import API that overwrites the existing data with whatever new data is provided (if true and if there is a matching imported_id, of course)
  2. now that a "reconciled" flag was introduced, ensure that no import call touches any transaction field (unless using the flag I suggested above)

My goal with (1) is being able to rewrite my importers to fine-tune some inferred notes/payees/categories and not have to manually delete the previously importer transactions for that.

(2) is about an issue I just found, where I had to manually fix some transaction dates for imported transactions, only to have them overwritten again by the next import, even though they were already reconciled.

<!-- gh-comment-id:1859275142 --> @tavlima commented on GitHub (Dec 17, 2023): Here is another perspective: depending on what your import source is, it may actually be the source of truth, including whether the transaction is cleared or not. But I agree with you that the current behavior is non-intuitive. Here is what I think would make some sense, from what I could see: 1. an additional boolean argument to the import API that overwrites the existing data with whatever new data is provided (if `true` and if there is a matching `imported_id`, of course) 2. now that a "reconciled" flag was introduced, ensure that no import call touches any transaction field (unless using the flag I suggested above) My goal with (1) is being able to rewrite my importers to fine-tune some inferred notes/payees/categories and not have to manually delete the previously importer transactions for that. (2) is about an issue I just found, where I had to manually fix some transaction dates for imported transactions, only to have them overwritten again by the next import, even though they were already reconciled.
Author
Owner

@andyg0808 commented on GitHub (Mar 22, 2025):

I think I've seen a similar behavior: using bank sync from SimpleFin, I see a transaction which is listed as a deposit, even though it's supposed to be a payment. The debugging output seemed to show that the transaction is being provided as a payment from SimpleFin. My assumption is that somehow it changed from positive to negative. I'm thinking it might make sense to sync amounts if the new amount is exactly the inverse of the old amount.

That is, maybe the code should also check existing.amount == -trans.amount ? trans.amount : existing.amount right here, and add it to the fields to update:

b2287cded3/packages/loot-core/src/server/accounts/sync.ts (L526-L535)

I'd be happy to open a PR for this, if the maintainers think it's reasonable.

<!-- gh-comment-id:2745900091 --> @andyg0808 commented on GitHub (Mar 22, 2025): I think I've seen a similar behavior: using bank sync from SimpleFin, I see a transaction which is listed as a deposit, even though it's supposed to be a payment. The debugging output seemed to show that the transaction is being provided as a payment from SimpleFin. My assumption is that somehow it changed from positive to negative. I'm thinking it might make sense to sync amounts if the new amount is exactly the inverse of the old amount. That is, maybe the code should also check `existing.amount == -trans.amount ? trans.amount : existing.amount` right here, and add it to the fields to update: https://github.com/actualbudget/actual/blob/b2287cded3460e1a98e2cefa986c2702ee1b5442/packages/loot-core/src/server/accounts/sync.ts#L526-L535 I'd be happy to open a PR for this, if the maintainers think it's reasonable.
Author
Owner

@t4cmyk commented on GitHub (Jun 6, 2025):

I'm writing a script to sync my bank account which doesn't have an official api and I encountered pretty much the same problem.

api.importTransactions would be the perfect match for my purpos except it doesn't update the amount values. Right now I'm just using a workaround but a general change to the api would be better I think.

  await api.importTransactions(accountId, txs);

  // workaround to update amount
  for (let tx of txs) {
    const { data }: { data: [{ id: string; amount: number }] } =
      (await runQuery(
        q("transactions")
          .filter({ imported_id: tx.imported_id })
          .select(["id", "amount"])
      )) as any;
    
    const match = data && data.length ? data[0] : undefined;
    if (match && match.amount !== tx.amount)
      await api.updateTransaction(match.id, {
        amount: tx.amount,
      });
  }
<!-- gh-comment-id:2948309946 --> @t4cmyk commented on GitHub (Jun 6, 2025): I'm writing a script to sync my bank account which doesn't have an official api and I encountered pretty much the same problem. `api.importTransactions` would be the perfect match for my purpos except it doesn't update the amount values. Right now I'm just using a workaround but a general change to the api would be better I think. ```typescript await api.importTransactions(accountId, txs); // workaround to update amount for (let tx of txs) { const { data }: { data: [{ id: string; amount: number }] } = (await runQuery( q("transactions") .filter({ imported_id: tx.imported_id }) .select(["id", "amount"]) )) as any; const match = data && data.length ? data[0] : undefined; if (match && match.amount !== tx.amount) await api.updateTransaction(match.id, { amount: tx.amount, }); } ```
Author
Owner

@matt-fidd commented on GitHub (Mar 23, 2026):

Should be fixed in packages/loot-core/src/server/accounts/app.ts by using addTransactions

<!-- gh-comment-id:4111841288 --> @matt-fidd commented on GitHub (Mar 23, 2026): Should be fixed in packages/loot-core/src/server/accounts/app.ts by using addTransactions
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#49811