mirror of
https://github.com/actualbudget/actual.git
synced 2026-07-16 07:04:23 -05:00
Open
opened 2026-05-19 02:32:06 -05:00 by GiteaMirror
·
16 comments
No Branch/Tag Specified
master
dependabot/npm_and_yarn/npm_and_yarn-cd62b4b37a
api-browser-custom-data-dir
tabedzki/feat/replacing-month-picker-with-day-picker
delay-initial-sync-until-loaded
jfdoming/mobile-app-build
cross-version-sync-compat
jfdoming/api-tokens-part-1
jfdoming/api-tokens-part-2
jfdoming/api-tokens-part-3
jfdoming/mobile-app-updates
claude/budget-version-migration-compat-151jlr
claude/worker-error-serialization-9iqtl7
claude/react-table-library-research-afx83z
claude/issue-8401-regression-test-9nw9l3
jfdoming/mobile-app-foundation-part-1
jfdoming/mobile-app-scaffold
release
ai-fix-cleanup-def-8290
claude/relaxed-shannon-jusywa
claude/fervent-keller-s6f2fq
claude/determined-feynman-st1y9z
claude/wizardly-einstein-vi2wce
claude/sweet-albattani-7nseio
feat/bank-sync-per-budget-file
claude/affectionate-cannon-y0kc82
claude/dependabot-findings-m9pgmb
claude/mac-app-ios-publish-zjs1lz
claude/vigilant-tesla-aiiyos
depot-migrate-secrets-1781296330308
claude/quirky-cerf-v5qck7
claude/animation-removal-alternative-2etfh1
claude/netlify-preview-comments-consolidate-9XPYa
osc/7391-error-boundaries-reports
claude/pensive-dijkstra-7DYui
claude/server-app-version-mismatch-HTCGv
claude/pr-8027-review-feedback-mELuO
claude/zealous-wozniak-e5pO0
claude/intelligent-heisenberg-BSHJq
claude/translation-download-refactor-jFRsO
claude/mobile-performance-ideas-G9PAO
claude/github-issue-7988-5A5ly
blacksmith-migration-ff70d2d
claude/great-mayer-KRvOk
claude/react-native-ios-compilation-fcJh5
claude/serene-goldberg-58xv0
claude/kind-euler-LVG3K
release-automation/edge-nightly
7710-bundle-migrations
claude/fix-docker-build-error-WMfed
claude/llm-compatible-release-notes-t20Nr
7710-tests-tdd
cursor/transaction-table-rewrite-f077
claude/plan-ci-secure-context-OtEe1
claude/fix-issue-7667-DPXi3
cursor/resolve-pr-7449-ee11
claude/fix-typescript-build-error-JPtZ5
copilot/add-repository-configs-to-packages
worktree-compressed-drifting-ritchie
claude/api-consumer-verification-kfz1K
pr-7454
claude/fix-issue-7410-LLLQ4
revert-7281-generate-icons
react-query-useSchedules
copilot/sub-pr-6140
package-upgrades
v26.7.0
v26.6.0
v26.5.2
v26.5.1
v26.5.0
v26.4.0
v26.3.0
v26.2.1
v26.2.0
v26.1.0
v25.12.0
v25.11.0
v25.10.0
v25.9.0
v25.8.0
v25.7.1
v25.7.0
v25.6.1
v25.6.0
v25.5.0
v25.4.0
v25.3.1
v25.3.0
v25.2.1
v25.2.0
v25.1.0
v24.12.0
v24.11.0
v24.10.1
v24.10.0
v24.9.0
v24.8.0
v24.7.0
v24.6.0
v24.5.0
v24.4.0
v24.3.0
v24.2.0
v24.1.0
v23.12.0
v23.11.0
v23.10.0
v23.9.0
v23.8.1
v23.8.0
v23.7.2
v23.7.1
v23.7.0
v23.6.0
v23.5.0
v23.4.2
v23.4.1
v23.4.0
v23.3.2
v23.3.0
v23.2.9
v23.2.5
v23.1.12
v22.12.9
Labels
Clear labels
AI generated
API
bank sync
budgeting
bug
can’t replicate
dependencies
docker
documentation
electron
experimental feature
feature
feedback
goal templates
good first issue
help wanted
importers
maintenance
needs info
needs testing
needs triage
needs votes
openid
payees
pull-request
regression
reports
responsive
rules
schedules
server
✨ merged
split transactions
tech debt
tech-support
theme
transaction import
transaction reconciliation
transactions
translations
upstream
user interface
✅ approved
wontfix
Mirrored from GitHub Pull Request
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: github-starred/actual#79564
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @alecbakholdin on GitHub (May 16, 2025).
Original GitHub issue: https://github.com/actualbudget/actual/issues/5000
Verified issue does not already exist?
What happened?
Bug described here by another user @cesjn
I have been an Actual user for several months now and was really excited for the new Merge feature that came out in the latest release. In theory it should address this problem, but the current implementation seems to fall short. I have a similar situation where a transfer is made between two accounts but the transaction is duplicated in the receiving account. So I end up with the following three transactions:
Account A, $20 Payment, categorized as Transfer, matched to SimpleLink Import and marked as cleared
Account B, $20 Credit, categorized as Transfer, unmatched and not cleared (appears to result from a rule that Actual automatically created for me)
Account B, $20 Credit, Not Categorized, matched to import and marked as cleared
Before the merge function was introduced I would change the category of transaction https://github.com/actualbudget/actual/pull/1 to something else, delete transaction https://github.com/actualbudget/actual/pull/2 and then use the "make transfer" function to link https://github.com/actualbudget/actual/pull/1 and https://github.com/actualbudget/actual/pull/3 together, thus categorizing them both as a transfer (Actual then wants me to make a rule for this, which I try to always decline in order to avoid the same situation the next month when these transactions occur again).
With the merge function I had the expectation that I should simply be able to "Merge" transactions https://github.com/actualbudget/actual/pull/2 and https://github.com/actualbudget/actual/pull/3 and we should be good to go. Unfortunately, when I do so, the resulting transaction is NOT categorized as a transfer, but https://github.com/actualbudget/actual/pull/1 stays as a transfer. This results in me being unable to link https://github.com/actualbudget/actual/pull/1 and the https://github.com/actualbudget/actual/pull/2/3 merge.
So, I would propose that there is a Bug here, specifically in the new merge feature. I.e. that if you merge a "transfer" transaction with another transaction, that the resulting merged transaction should maintain the "transfer" category. The alternative would be to unlink the transaction linked to the transfer transaction (set it back to uncategorized) so that you can re-link the resulting transaction, but that seems far more complicated.
How can we reproduce the issue?
create a transfer, create a transaction. Attempt to merge the two transactions. It fails.
Where are you hosting Actual?
None
What browsers are you seeing the problem on?
No response
Operating System
None
@alecbakholdin commented on GitHub (May 16, 2025):
Created as a result of discussion in #4899
@karanj commented on GitHub (Sep 22, 2025):
Encountered this today, was very confused as to why it would always seem to pick the non-transfer as the merged entry.
If merge is broken when transfers are included in the merge set, is there a way to disable or caution the user trying to perform the action until a fix is developed?
@oddmaniv commented on GitHub (Feb 17, 2026):
Really struggling with this issue - has there been any progress / alternative methods?
@nicepopo86-lang commented on GitHub (Feb 17, 2026):
I’d like to work on this bounty issue. I’ll reproduce the transfer-merge bug, implement a focused fix, and open a PR with regression steps.
@nicepopo86-lang commented on GitHub (Feb 17, 2026):
I opened a draft PR with a focused fix and regression test for this merge path:\n\n- PR: https://github.com/actualbudget/actual/pull/7000\n\nIt preserves/relinks when a merge keeps the imported transaction, so transfer pairing stays valid instead of pointing to a deleted transaction id.
@lmee commented on GitHub (Feb 17, 2026):
I reviewed "Can't merge transfers with new merge functionality" and read all comments before proposing a patch path.
Problem I see: - [x] I have searched and found no existing issue.
Root-cause hypothesis: inconsistent filter/query state between two rendering paths.
First patch plan: reproduce the issue against acceptance criteria, isolate the root cause in the relevant module, and submit a focused fix with regression tests.
If this aligns with maintainer expectations, I will post repro evidence first and then open the scoped patch.
@cesjn commented on GitHub (Apr 23, 2026):
@oddmaniv, @karanj I am attempting to address this issue (with some help from Claude) and I have an interesting question for you (and any other user who has an opinion). If you have two sets of transfer transactions (accountATransaction1 <-> accountBTransaction2, accountATransaction3 <-> accountBTransaction4) and you merge transactions accountATransaction1 and accountAtransaction3. Let's assume that accountATransaction1 is the kept transaction. We would have accountATransaction1merged3 <-> accountBTransaction2. The question is: what should we do with accountBTransaction4? Should we remove the transfer link and leave it, or delete it?
In my personal workflow, I would prefer to delete it. BUT, I think the safer thing overall is to leave it as a non-transfer transaction so that the user can choose what to do with it.
@alecbakholdin commented on GitHub (Apr 23, 2026):
@cesjn thanks for looking into this!
EDIT
I realized that I misread what you wrote. To answer the question you actually asked, I think we should delete the second transaction. If you're merging a transfer with another transfer, then the 4 transactions should be reduced to 2, and we simply perform two merges: one in account A and one in account B, using the logic already present. Just have to make sure the transfer is properly conserved even if we end up keeping accountATransaction1 and accountBTransaction4, for example
I think what you're describing is a symptom of the merge criteria not being strict enough. In my original implementation #4739 I have it set to only allow merges if the amounts are the same. I'm thinking we can add new criteria to simplify the problem statement:- Amounts are the same (currently the only requirement)
- Accounts are the same
- If both are transfers, the destination account (aka payee) must be the same
I propose that we allow merges if all the below are true:
I'm struggling to come up with a real-world scenario where I would need to do what you're describing. Can you share an example where you would need to merge transfers that don't follow the above criteria?
@alecbakholdin commented on GitHub (Apr 23, 2026):
I've gone ahead and implemented a fix for this which simply adds logic to the keep/drop determination step. A transfer is now prioritized over an imported transaction for keep/drop logic.
@cesjn commented on GitHub (Apr 24, 2026):
I will pull the branch and try it out. It might help if I describe my use case a little better:
I often have bank transfers or credit card payments that show up from import on different days (i.e. the payment leaves my checking account on 4/22 but isn't credited to my credit card until 4/23 or later (if there is a weekend or holiday involved). Since actual has "learned" that these transactions are transfers, it will assign them as such when they are imported. Since the import doesn't match the two (due to the different dates) this results in the 4 transaction scenario described above:
CheckingTransaction1 which is imported/cleared and linked as a transfer to CreditCardPayment2 (uncleared and no matching import)
CreditCardPayment3 which is imported/cleared and linked as a transfer to CheckingTransaction4 (uncleared and no matching import)
In an ideal world I would be able to merge either CheckingTransaction1 and CheckingTransaction4 or CreditCardPayment2 and CreditCardPayment3 and end up with CheckingTransaction1 and CreditCardPayment3 (since these are the imported transactions and the dates will match the respective bank statements, etc.).
Obviously there is an alternative means to this end: namely remove or re-work the import rules to not mark the imported transactions as transfers and then manually link them as transfers after both are imported, but this is a less than intuitive workflow, especially for new users.
@cesjn commented on GitHub (Apr 24, 2026):
Had a chance to test out the branch. It just so happens that in my current budget file I have a situation where I have CreditCardPayment1 on 4/21 (cleared with import info in notes, no category)
CheckingTransaction2 on 4/22 (cleared with import info in notes) linked as transfer to an auto-generated CreditCardPayment3 (uncleared, note matches CheckingTransaction2)
When I merge CreditCardPayment1 with CreditCardPayment3 I end up with the CreditCardPayment3 (4/22 date, cleared, note matches CheckingTransaction2).
While not perfect (it would be better to retain the 4/21 date for the CreditCardPayment), it is probably good enough.
The other scenario I need to test is when one of the accounts is off budget, thus requiring a category other than transfer for the on budget transaction.
@alecbakholdin commented on GitHub (Apr 24, 2026):
I see what you mean. I think rather than modifying the keep/drop logic what I need to do is keep the keep/drop logic as is but if the dropped transaction is the transfer then I need to move the transfer link to point to the new transaction. Then if there are two transfers, I do keep/drop detection on both and create a single transfer based on the best 2 of the 4 transactions?
@cesjn commented on GitHub (Apr 24, 2026):
Agreed that the original keep/drop logic was better and if the dropped is a transfer and the kept is not, we should move the transfer link over. If there are 4 transactions it seems like we need to be able to merge the two sets of two. I was playing with this last night and I haven't quite gotten it to work right yet (mostly my limited familiarity with javascript). I also need to think through what information can be merged when transactions are a transfer (notes are linked for instance and category is restricted for on budget accounts... I also need to think through whether subtransactions are a possibility here... maybe when the transfer is from an on-budget account to off-budget account).
@alecbakholdin commented on GitHub (Apr 24, 2026):
@cesjn just pushed an implementation. If the builds fail, it's because I can't run unit tests locally for some reason so I'll be working on fixing that but in the meantime you're welcome to pull the branch and test for your use case.
Basically the new logic is (given accountA-> accountB):
await setTransfers([a.id, b.id, aTransferId, bTransferId], null);const transferId = await mergeTransfers(aTransferId, bTransferId);const keptTxId = await mergeTransactionsNoTransfer(a, b);Also, if you use the "make transfer" feature, then you can create transfers that have different dates and notes. This merge logic follows similar logic, meaning if you have
TransA (Apr 24) transNote -> TransB (Apr 24) transNotemerged with
TransC (Apr 1) noteYou will end up with the following
TransC (Apr 1) note -> TransB (Apr 24) transNotePlease give this a shot and let me know if this works for you!
@cesjn commented on GitHub (Apr 24, 2026):
Looks great... here is a summary of what I have tested:
3 transactions to 2: both imported transactions are retained with their respective dates and notes
4 transaction to 2: both imported transactions are retained with their respective dates and notes (edit: I tested both merge scenarios, i.e. merge the two account A transactions or merge the two account B transactions)
I then created on Off-budget to on-budget transfer and an on-budget imported transaction that was split into sub-transactions. The imported/split transaction was retained with its sub-transactions.
I ran yarn test and everything passed.
From my point of view, this looks perfect.
Huge thanks for all the efforts here!
@alecbakholdin commented on GitHub (Apr 24, 2026):
Sorry for the year-long turnaround!