Prevent duplicate notes when re-evaluating automation rules
Add appendNoteIfNotPresent helper to check if rule note already exists in transaction notes before appending, preventing duplicate concatenation when rules are re-evaluated multiple times.
This commit is contained in:
parent
d04b6a0174
commit
f6f1cba041
|
|
@ -23,6 +23,7 @@ import { useEncryptionKey } from '@/contexts/encryption-key-context';
|
|||
import { decrypt, encrypt, importKey } from '@/lib/crypto';
|
||||
import { getStoredKey } from '@/lib/key-storage';
|
||||
import { evaluateRulesForNewTransaction } from '@/lib/rule-engine';
|
||||
import { appendNoteIfNotPresent } from '@/lib/utils';
|
||||
import { automationRuleSyncService } from '@/services/automation-rule-sync';
|
||||
import { transactionSyncService } from '@/services/transaction-sync';
|
||||
import {
|
||||
|
|
@ -198,11 +199,10 @@ export function EditTransactionDialog({
|
|||
result.noteIv,
|
||||
);
|
||||
|
||||
if (finalNotes) {
|
||||
finalNotes = `${finalNotes}\n${decryptedRuleNote}`;
|
||||
} else {
|
||||
finalNotes = decryptedRuleNote;
|
||||
}
|
||||
finalNotes = appendNoteIfNotPresent(
|
||||
finalNotes || undefined,
|
||||
decryptedRuleNote,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,12 @@ function formatMonth(yearMonth: string): string {
|
|||
|
||||
const isCurrentYear = date.getFullYear() === new Date().getFullYear();
|
||||
|
||||
return date.toLocaleDateString('en-US', isCurrentYear ? { month: 'short' } : { year: '2-digit', month: 'short' });
|
||||
return date.toLocaleDateString(
|
||||
'en-US',
|
||||
isCurrentYear
|
||||
? { month: 'short' }
|
||||
: { year: '2-digit', month: 'short' },
|
||||
);
|
||||
}
|
||||
|
||||
export function useDashboardData(): DashboardData {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { decrypt, encrypt, importKey } from '@/lib/crypto';
|
||||
import { getStoredKey } from '@/lib/key-storage';
|
||||
import { evaluateRules } from '@/lib/rule-engine';
|
||||
import { appendNoteIfNotPresent } from '@/lib/utils';
|
||||
import { automationRuleSyncService } from '@/services/automation-rule-sync';
|
||||
import { transactionSyncService } from '@/services/transaction-sync';
|
||||
import type { Account, Bank } from '@/types/account';
|
||||
|
|
@ -77,17 +78,23 @@ export function useReEvaluateAllTransactions() {
|
|||
let finalNotesIv = transaction.notes_iv;
|
||||
|
||||
if (result.note && result.noteIv) {
|
||||
if (transaction.decryptedNotes) {
|
||||
const combinedNote = `${transaction.decryptedNotes}\n${await decrypt(result.note, key, result.noteIv)}`;
|
||||
const decryptedRuleNote = await decrypt(
|
||||
result.note,
|
||||
key,
|
||||
result.noteIv,
|
||||
);
|
||||
const combinedNote = appendNoteIfNotPresent(
|
||||
transaction.decryptedNotes,
|
||||
decryptedRuleNote,
|
||||
);
|
||||
|
||||
if (combinedNote !== transaction.decryptedNotes) {
|
||||
const encrypted = await encrypt(
|
||||
combinedNote,
|
||||
key,
|
||||
);
|
||||
finalNotes = encrypted.encrypted;
|
||||
finalNotesIv = encrypted.iv;
|
||||
} else {
|
||||
finalNotes = result.note;
|
||||
finalNotesIv = result.noteIv;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,3 +16,18 @@ export function isSameUrl(
|
|||
export function resolveUrl(url: NonNullable<InertiaLinkProps['href']>): string {
|
||||
return typeof url === 'string' ? url : url.url;
|
||||
}
|
||||
|
||||
export function appendNoteIfNotPresent(
|
||||
existingNotes: string | undefined,
|
||||
newNote: string,
|
||||
): string {
|
||||
if (!existingNotes) {
|
||||
return newNote;
|
||||
}
|
||||
|
||||
if (existingNotes.includes(newNote)) {
|
||||
return existingNotes;
|
||||
}
|
||||
|
||||
return `${existingNotes}\n${newNote}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import { consoleDebug } from '@/lib/debug';
|
|||
import { db } from '@/lib/dexie-db';
|
||||
import { getStoredKey } from '@/lib/key-storage';
|
||||
import { evaluateRules } from '@/lib/rule-engine';
|
||||
import { appendNoteIfNotPresent } from '@/lib/utils';
|
||||
import { automationRuleSyncService } from '@/services/automation-rule-sync';
|
||||
import { transactionSyncService } from '@/services/transaction-sync';
|
||||
import { type BreadcrumbItem } from '@/types';
|
||||
|
|
@ -600,18 +601,23 @@ export default function Transactions({ categories, accounts, banks }: Props) {
|
|||
|
||||
if (result.note && result.noteIv) {
|
||||
consoleDebug('Adding note from rule');
|
||||
if (transaction.decryptedNotes) {
|
||||
const combinedNote = `${transaction.decryptedNotes}\n${await decrypt(result.note, key, result.noteIv)}`;
|
||||
const decryptedRuleNote = await decrypt(
|
||||
result.note,
|
||||
key,
|
||||
result.noteIv,
|
||||
);
|
||||
const combinedNote = appendNoteIfNotPresent(
|
||||
transaction.decryptedNotes,
|
||||
decryptedRuleNote,
|
||||
);
|
||||
|
||||
if (combinedNote !== transaction.decryptedNotes) {
|
||||
const encrypted = await encrypt(combinedNote, key);
|
||||
finalNotes = encrypted.encrypted;
|
||||
finalNotesIv = encrypted.iv;
|
||||
consoleDebug(
|
||||
'Combined existing notes with rule note',
|
||||
);
|
||||
consoleDebug('Combined notes with rule note');
|
||||
} else {
|
||||
finalNotes = result.note;
|
||||
finalNotesIv = result.noteIv;
|
||||
consoleDebug('Set rule note as new note');
|
||||
consoleDebug('Rule note already present, skipping');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -744,18 +750,23 @@ export default function Transactions({ categories, accounts, banks }: Props) {
|
|||
|
||||
if (result.note && result.noteIv) {
|
||||
consoleDebug('Adding note from rule');
|
||||
if (transaction.decryptedNotes) {
|
||||
const combinedNote = `${transaction.decryptedNotes}\n${await decrypt(result.note, key, result.noteIv)}`;
|
||||
const decryptedRuleNote = await decrypt(
|
||||
result.note,
|
||||
key,
|
||||
result.noteIv,
|
||||
);
|
||||
const combinedNote = appendNoteIfNotPresent(
|
||||
transaction.decryptedNotes,
|
||||
decryptedRuleNote,
|
||||
);
|
||||
|
||||
if (combinedNote !== transaction.decryptedNotes) {
|
||||
const encrypted = await encrypt(combinedNote, key);
|
||||
finalNotes = encrypted.encrypted;
|
||||
finalNotesIv = encrypted.iv;
|
||||
consoleDebug(
|
||||
'Combined existing notes with rule note',
|
||||
);
|
||||
consoleDebug('Combined notes with rule note');
|
||||
} else {
|
||||
finalNotes = result.note;
|
||||
finalNotesIv = result.noteIv;
|
||||
consoleDebug('Set rule note as new note');
|
||||
consoleDebug('Rule note already present, skipping');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue