Identify and fix broken transfers (#4216)

* show broken transfers

* more detail

* feat: add step to fix splits for fixing transfers with categories that should not be there

* reword

* update the setting

* note

* lint

* typo

* another misspelling

---------

Co-authored-by: UnderKoen <koenvanstaveren@hotmail.com>
This commit is contained in:
youngcw
2025-01-22 17:07:15 -07:00
committed by GitHub
parent 2f8b839036
commit 977657a0be
6 changed files with 58 additions and 12 deletions

View File

@@ -18,14 +18,20 @@ function useRenderResults() {
const { t } = useTranslation(); const { t } = useTranslation();
function renderResults(results: Results) { function renderResults(results: Results) {
const { numBlankPayees, numCleared, numDeleted, mismatchedSplits } = const {
results; numBlankPayees,
numCleared,
numDeleted,
numTransfersFixed,
mismatchedSplits,
} = results;
const result: string[] = []; const result: string[] = [];
if ( if (
numBlankPayees === 0 && numBlankPayees === 0 &&
numCleared === 0 && numCleared === 0 &&
numDeleted === 0 && numDeleted === 0 &&
numTransfersFixed === 0 &&
mismatchedSplits.length === 0 mismatchedSplits.length === 0
) { ) {
result.push(t('No split transactions found needing repair.')); result.push(t('No split transactions found needing repair.'));
@@ -51,6 +57,13 @@ function useRenderResults() {
}), }),
); );
} }
if (numTransfersFixed > 0) {
result.push(
t('Fixed {{count}} transfers.', {
count: numTransfersFixed,
}),
);
}
if (mismatchedSplits.length > 0) { if (mismatchedSplits.length > 0) {
const mismatchedSplitInfo = mismatchedSplits const mismatchedSplitInfo = mismatchedSplits
.map(t => `- ${t.date}`) .map(t => `- ${t.date}`)
@@ -83,7 +96,7 @@ function useRenderResults() {
return { renderResults }; return { renderResults };
} }
export function FixSplits() { export function RepairTransactions() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [results, setResults] = useState<Results | null>(null); const [results, setResults] = useState<Results | null>(null);
@@ -108,7 +121,7 @@ export function FixSplits() {
}} }}
> >
<ButtonWithLoading isLoading={loading} onPress={onFix}> <ButtonWithLoading isLoading={loading} onPress={onFix}>
<Trans>Repair split transactions</Trans> <Trans>Repair transactions</Trans>
</ButtonWithLoading> </ButtonWithLoading>
{results && renderResults(results)} {results && renderResults(results)}
</View> </View>
@@ -116,11 +129,11 @@ export function FixSplits() {
> >
<Trans> <Trans>
<Text> <Text>
<strong>Repair split transactions</strong> if you are experiencing <strong>Repair transactions</strong> if you are experiencing bugs
bugs relating to split transactions and the Reset budget cache relating to split transactions or transfers and the Reset budget
button above does not help, this tool may fix them. Some examples of cache button above does not help, this tool may fix them. Some
bugs include seeing blank payees on splits or incorrect account examples of bugs include seeing blank payees on splits or incorrect
balances. This tool does three things: account balances. This tool does four things:
</Text> </Text>
<ul style={{ margin: 0, paddingLeft: '1.5em' }}> <ul style={{ margin: 0, paddingLeft: '1.5em' }}>
<li style={{ marginBottom: '0.5em' }}> <li style={{ marginBottom: '0.5em' }}>
@@ -140,6 +153,10 @@ export function FixSplits() {
amount. If not, these will be flagged below to allow you to easily amount. If not, these will be flagged below to allow you to easily
locate and fix the amounts. locate and fix the amounts.
</li> </li>
<li>
Check if you have any budget transfers that erroneous contain a
category, and remove the category.
</li>
</ul> </ul>
</Trans> </Trans>
</Setting> </Setting>

View File

@@ -30,9 +30,9 @@ import { BudgetTypeSettings } from './BudgetTypeSettings';
import { EncryptionSettings } from './Encryption'; import { EncryptionSettings } from './Encryption';
import { ExperimentalFeatures } from './Experimental'; import { ExperimentalFeatures } from './Experimental';
import { ExportBudget } from './Export'; import { ExportBudget } from './Export';
import { FixSplits } from './FixSplits';
import { FormatSettings } from './Format'; import { FormatSettings } from './Format';
import { LanguageSettings } from './LanguageSettings'; import { LanguageSettings } from './LanguageSettings';
import { RepairTransactions } from './RepairTransactions';
import { ResetCache, ResetSync } from './Reset'; import { ResetCache, ResetSync } from './Reset';
import { ThemeSettings } from './Themes'; import { ThemeSettings } from './Themes';
import { AdvancedToggle, Setting } from './UI'; import { AdvancedToggle, Setting } from './UI';
@@ -209,7 +209,7 @@ export function Settings() {
<AdvancedAbout /> <AdvancedAbout />
<ResetCache /> <ResetCache />
<ResetSync /> <ResetSync />
<FixSplits /> <RepairTransactions />
<ExperimentalFeatures /> <ExperimentalFeatures />
</AdvancedToggle> </AdvancedToggle>
</View> </View>

View File

@@ -1445,7 +1445,9 @@ const Transaction = memo(function Transaction({
: isOffBudget : isOffBudget
? 'Off budget' ? 'Off budget'
: isBudgetTransfer : isBudgetTransfer
? 'Transfer' ? categoryId != null
? 'Needs Repair'
: 'Transfer'
: '' : ''
} }
valueStyle={valueStyle} valueStyle={valueStyle}

View File

@@ -73,10 +73,30 @@ app.method('tools/fix-split-transactions', async () => {
return subValue !== t.amount; return subValue !== t.amount;
}); });
// 5. Fix transfers that should not have categories
const brokenTransfers = await db.all(`
SELECT t1.id
FROM v_transactions_internal t1
JOIN accounts a1 ON t1.account = a1.id
JOIN v_transactions_internal t2 ON t1.transfer_id = t2.id
JOIN accounts a2 ON t2.account = a2.id
WHERE a1.offbudget = a2.offbudget
AND t1.category IS NOT NULL
`);
await runMutator(async () => {
const updated = brokenTransfers.map(row => ({
id: row.id,
category: null,
}));
await batchUpdateTransactions({ updated });
});
return { return {
numBlankPayees: blankPayeeRows.length, numBlankPayees: blankPayeeRows.length,
numCleared: clearedRows.length, numCleared: clearedRows.length,
numDeleted: deletedRows.length, numDeleted: deletedRows.length,
numTransfersFixed: brokenTransfers.length,
mismatchedSplits, mismatchedSplits,
}; };
}); });

View File

@@ -5,6 +5,7 @@ export interface ToolsHandlers {
numBlankPayees: number; numBlankPayees: number;
numCleared: number; numCleared: number;
numDeleted: number; numDeleted: number;
numTransfersFixed: number;
mismatchedSplits: TransactionEntity[]; mismatchedSplits: TransactionEntity[];
}>; }>;
} }

View File

@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [youngcw, UnderKoen]
---
Extend "fix splits" to also fix transfers that have categories and should not.