diff --git a/packages/desktop-client/src/components/settings/FixSplits.tsx b/packages/desktop-client/src/components/settings/FixSplits.tsx index 2897ee431a0..aa33f81b5ef 100644 --- a/packages/desktop-client/src/components/settings/FixSplits.tsx +++ b/packages/desktop-client/src/components/settings/FixSplits.tsx @@ -15,40 +15,47 @@ import { Setting } from './UI'; type Results = Awaited>; function renderResults(results: Results) { - const { numBlankPayees, numCleared, numDeleted } = results; - let result = ''; + const { numBlankPayees, numCleared, numDeleted, mismatchedSplits } = results; + const result: string[] = []; - if (numBlankPayees === 0 && numCleared === 0 && numDeleted === 0) { - result = 'No split transactions found needing repair.'; + if ( + numBlankPayees === 0 && + numCleared === 0 && + numDeleted === 0 && + mismatchedSplits.length === 0 + ) { + result.push('No split transactions found needing repair.'); } else { if (numBlankPayees > 0) { - result += `Fixed ${numBlankPayees} splits with a blank payee.`; + result.push(`Fixed ${numBlankPayees} splits with a blank payee.`); } if (numCleared > 0) { - if (result !== '') { - result += '\n'; - } - result += `Fixed ${numCleared} splits with the wrong cleared flag.`; + result.push(`Fixed ${numCleared} splits with the wrong cleared flag.`); } if (numDeleted > 0) { - if (result !== '') { - result += '\n'; - } - result += `Fixed ${numDeleted} splits that weren’t properly deleted.`; + result.push(`Fixed ${numDeleted} splits that weren’t properly deleted.`); + } + if (mismatchedSplits.length > 0) { + result.push( + `Found ${mismatchedSplits.length} split transaction${mismatchedSplits.length > 1 ? 's' : ''} ` + + `with mismatched amounts on the below date${mismatchedSplits.length > 1 ? 's' : ''}. ` + + `Please fix ${mismatchedSplits.length > 1 ? 'these' : 'this'} manually:\n` + + mismatchedSplits.map(t => `- ${t.date}`).join('\n'), + ); } } return ( - {result} + {result.join('\n')} ); } @@ -61,6 +68,7 @@ export function FixSplits() { async function onFix() { setLoading(true); const res = await send('tools/fix-split-transactions'); + setResults(res); setLoading(false); } @@ -70,11 +78,9 @@ export function FixSplits() { primaryAction={ diff --git a/packages/loot-core/src/server/tools/app.ts b/packages/loot-core/src/server/tools/app.ts index 31b48447a83..95cb254f9f3 100644 --- a/packages/loot-core/src/server/tools/app.ts +++ b/packages/loot-core/src/server/tools/app.ts @@ -1,6 +1,8 @@ // @ts-strict-ignore +import { q } from '../../shared/query'; import { batchUpdateTransactions } from '../accounts/transactions'; import { createApp } from '../app'; +import { runQuery } from '../aql'; import * as db from '../db'; import { runMutator } from '../mutators'; @@ -54,9 +56,27 @@ app.method('tools/fix-split-transactions', async () => { await batchUpdateTransactions({ updated }); }); + const splitTransactions = ( + await runQuery( + q('transactions') + .options({ splits: 'grouped' }) + .filter({ + is_parent: true, + }) + .select('*'), + ) + ).data; + + const mismatchedSplits = splitTransactions.filter(t => { + const subValue = t.subtransactions.reduce((acc, st) => acc + st.amount, 0); + + return subValue !== t.amount; + }); + return { numBlankPayees: blankPayeeRows.length, numCleared: clearedRows.length, numDeleted: deletedRows.length, + mismatchedSplits, }; }); diff --git a/packages/loot-core/src/server/tools/types/handlers.d.ts b/packages/loot-core/src/server/tools/types/handlers.d.ts index 841db08c084..8a31465a369 100644 --- a/packages/loot-core/src/server/tools/types/handlers.d.ts +++ b/packages/loot-core/src/server/tools/types/handlers.d.ts @@ -1,7 +1,10 @@ +import { TransactionEntity } from './models'; + export interface ToolsHandlers { 'tools/fix-split-transactions': () => Promise<{ numBlankPayees: number; numCleared: number; numDeleted: number; + mismatchedSplits: TransactionEntity[]; }>; } diff --git a/upcoming-release-notes/3970.md b/upcoming-release-notes/3970.md new file mode 100644 index 00000000000..ec541471f6b --- /dev/null +++ b/upcoming-release-notes/3970.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [matt-fidd] +--- + +Extend fix splits tool to report splits with mismatched amounts