Skip to content

Commit 5c7c70d

Browse files
lwarrenthompsonL. Warren Thompsonclaude
authored andcommitted
Fix updateTransaction corrupting split parents with partial updates (#7242)
* [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 <noreply@anthropic.com> * [AI] Add release notes for PR #7242 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Address review feedback: remove verbose comment and simplify release note Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: L. Warren Thompson <lwarrenthompson@Warren-MBP.local> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3cc5450 commit 5c7c70d

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

packages/loot-core/src/shared/transactions.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,40 @@ describe('Transactions', () => {
201201
expect(data.length).toBe(5);
202202
});
203203

204+
test('partially updating a split parent preserves amount and does not set error', () => {
205+
const transactions = [
206+
makeTransaction({ amount: 2001 }),
207+
...makeSplitTransaction({ id: 't1', amount: 2500 }, [
208+
{ id: 't2', amount: 2000 },
209+
{ id: 't3', amount: 500 },
210+
]),
211+
makeTransaction({ amount: 3002 }),
212+
];
213+
214+
// Simulate a partial update (only `notes`) on the parent — this is
215+
// how `api.updateTransaction(id, { notes: '...' })` calls it in
216+
// `api.ts`: `updateTransaction(transactions, { id, ...fields })`.
217+
const { data, diff } = updateTransaction(transactions, {
218+
id: 't1',
219+
notes: 'updated note',
220+
} as TransactionEntity);
221+
222+
// The parent should get the updated notes without an error
223+
const parent = data.find(d => d.id === 't1');
224+
expect(parent?.notes).toBe('updated note');
225+
expect(parent?.amount).toBe(2500);
226+
expect(parent?.error).toBeNull();
227+
228+
// Children should be unchanged
229+
expect(data.filter(t => t.parent_id === 't1').length).toBe(2);
230+
231+
expect(diff).toEqual({
232+
added: [],
233+
deleted: [],
234+
updated: [expect.objectContaining({ id: 't1', notes: 'updated note' })],
235+
});
236+
});
237+
204238
test('deleting a split transaction works', () => {
205239
const transactions = [
206240
makeTransaction({ amount: 2001 }),

packages/loot-core/src/shared/transactions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ export function updateTransaction(
262262
) {
263263
return replaceTransactions(transactions, transaction.id, trans => {
264264
if (trans.is_parent) {
265-
const parent = trans.id === transaction.id ? transaction : trans;
265+
const parent =
266+
trans.id === transaction.id ? { ...trans, ...transaction } : trans;
266267
const originalSubtransactions =
267268
parent.subtransactions ?? trans.subtransactions;
268269
const sub = originalSubtransactions?.map(t => {

upcoming-release-notes/7242.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
category: Bugfixes
3+
authors: [lwarrenthompson]
4+
---
5+
6+
Fix `api.updateTransaction()` corrupting split parent transactions when doing partial updates

0 commit comments

Comments
 (0)