From d262f7d8b24c178690be7a38bca84b802e181c29 Mon Sep 17 00:00:00 2001 From: "L. Warren Thompson" Date: Sun, 5 Apr 2026 01:01:06 -0700 Subject: [PATCH] Fix updateTransaction corrupting split parents with partial updates (#7242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [AI] Fix updateTransaction corrupting split parents with partial updates When `api.updateTransaction(id, { notes: '...' })` is called on a split parent, the `updateTransaction` helper replaces the parent with the sparse update object (`{ id, notes }`) instead of merging it with the existing transaction data. This causes `recalculateSplit` to see `amount` as `undefined` (→ 0), which doesn't match the children's total and sets a `SplitTransactionError` on the parent. `makeChild` also inherits undefined `account`, `date`, and `cleared` values, potentially creating broken child rows. Fix: merge the incoming partial fields (`{ ...trans, ...transaction }`) so all existing properties are preserved. Add a test that performs a notes-only update on a split parent and asserts no error is set and the amount stays intact. Co-Authored-By: Claude Opus 4.6 * [AI] Add release notes for PR #7242 Co-Authored-By: Claude Opus 4.6 * Address review feedback: remove verbose comment and simplify release note Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: L. Warren Thompson Co-authored-by: Claude Opus 4.6 --- .../loot-core/src/shared/transactions.test.ts | 34 +++++++++++++++++++ packages/loot-core/src/shared/transactions.ts | 3 +- upcoming-release-notes/7242.md | 6 ++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 upcoming-release-notes/7242.md diff --git a/packages/loot-core/src/shared/transactions.test.ts b/packages/loot-core/src/shared/transactions.test.ts index bedd5a6ec0..028eb8e9b1 100644 --- a/packages/loot-core/src/shared/transactions.test.ts +++ b/packages/loot-core/src/shared/transactions.test.ts @@ -201,6 +201,40 @@ describe('Transactions', () => { expect(data.length).toBe(5); }); + test('partially updating a split parent preserves amount and does not set error', () => { + const transactions = [ + makeTransaction({ amount: 2001 }), + ...makeSplitTransaction({ id: 't1', amount: 2500 }, [ + { id: 't2', amount: 2000 }, + { id: 't3', amount: 500 }, + ]), + makeTransaction({ amount: 3002 }), + ]; + + // Simulate a partial update (only `notes`) on the parent — this is + // how `api.updateTransaction(id, { notes: '...' })` calls it in + // `api.ts`: `updateTransaction(transactions, { id, ...fields })`. + const { data, diff } = updateTransaction(transactions, { + id: 't1', + notes: 'updated note', + } as TransactionEntity); + + // The parent should get the updated notes without an error + const parent = data.find(d => d.id === 't1'); + expect(parent?.notes).toBe('updated note'); + expect(parent?.amount).toBe(2500); + expect(parent?.error).toBeNull(); + + // Children should be unchanged + expect(data.filter(t => t.parent_id === 't1').length).toBe(2); + + expect(diff).toEqual({ + added: [], + deleted: [], + updated: [expect.objectContaining({ id: 't1', notes: 'updated note' })], + }); + }); + test('deleting a split transaction works', () => { const transactions = [ makeTransaction({ amount: 2001 }), diff --git a/packages/loot-core/src/shared/transactions.ts b/packages/loot-core/src/shared/transactions.ts index 866ecee574..5b0c93f7f7 100644 --- a/packages/loot-core/src/shared/transactions.ts +++ b/packages/loot-core/src/shared/transactions.ts @@ -262,7 +262,8 @@ export function updateTransaction( ) { return replaceTransactions(transactions, transaction.id, trans => { if (trans.is_parent) { - const parent = trans.id === transaction.id ? transaction : trans; + const parent = + trans.id === transaction.id ? { ...trans, ...transaction } : trans; const originalSubtransactions = parent.subtransactions ?? trans.subtransactions; const sub = originalSubtransactions?.map(t => { diff --git a/upcoming-release-notes/7242.md b/upcoming-release-notes/7242.md new file mode 100644 index 0000000000..57c2fe7572 --- /dev/null +++ b/upcoming-release-notes/7242.md @@ -0,0 +1,6 @@ +--- +category: Bugfixes +authors: [lwarrenthompson] +--- + +Fix `api.updateTransaction()` corrupting split parent transactions when doing partial updates