fix: automated rules broken and now they work in batches
This commit is contained in:
parent
c3b1a8df4c
commit
890593d967
|
|
@ -105,7 +105,7 @@ export async function prepareTransactionData(
|
|||
),
|
||||
amount: transaction.amount / 100,
|
||||
transaction_date: transaction.transaction_date,
|
||||
bank_name: bank?.name || '',
|
||||
bank_name: (bank?.name || '').toLowerCase(),
|
||||
account_name: accountName.toLowerCase(),
|
||||
category: category?.name || null,
|
||||
notes: transaction.decryptedNotes
|
||||
|
|
@ -257,7 +257,7 @@ export async function evaluateRulesForNewTransaction(
|
|||
),
|
||||
amount: transactionData.amount,
|
||||
transaction_date: transactionData.transaction_date,
|
||||
bank_name: bank?.name || '',
|
||||
bank_name: (bank?.name || '').toLowerCase(),
|
||||
account_name: accountName.toLowerCase(),
|
||||
category: null,
|
||||
notes: transactionData.notes
|
||||
|
|
|
|||
|
|
@ -689,7 +689,6 @@ export default function Transactions({
|
|||
categories,
|
||||
accounts,
|
||||
banks,
|
||||
labels,
|
||||
key,
|
||||
);
|
||||
|
||||
|
|
@ -776,10 +775,11 @@ export default function Transactions({
|
|||
consoleDebug('=== Re-evaluation complete ===');
|
||||
}
|
||||
},
|
||||
[isKeySet, categories, accounts, banks, labels, updateTransaction],
|
||||
[isKeySet, categories, accounts, banks, updateTransaction],
|
||||
);
|
||||
|
||||
async function handleBulkReEvaluateRules() {
|
||||
const BATCH_SIZE = 25;
|
||||
consoleDebug('=== Re-evaluating rules for bulk transactions ===');
|
||||
consoleDebug(`Selected ${selectedIds.length} transactions`);
|
||||
|
||||
|
|
@ -822,7 +822,8 @@ export default function Transactions({
|
|||
})),
|
||||
);
|
||||
|
||||
const updates: Array<{
|
||||
// Collect all updates first without updating IndexedDB
|
||||
const allUpdates: Array<{
|
||||
transaction: DecryptedTransaction;
|
||||
categoryId: number | null;
|
||||
category: Category | null;
|
||||
|
|
@ -831,6 +832,15 @@ export default function Transactions({
|
|||
decryptedNotes: string | null;
|
||||
}> = [];
|
||||
|
||||
const dbUpdates: Array<{
|
||||
id: string;
|
||||
data: {
|
||||
category_id: number | null;
|
||||
notes: string | null;
|
||||
notes_iv: string | null;
|
||||
};
|
||||
}> = [];
|
||||
|
||||
for (const transaction of selectedTransactions) {
|
||||
consoleDebug(`\nEvaluating transaction ${transaction.id}...`);
|
||||
const result = await evaluateRules(
|
||||
|
|
@ -839,7 +849,6 @@ export default function Transactions({
|
|||
categories,
|
||||
accounts,
|
||||
banks,
|
||||
labels,
|
||||
key,
|
||||
);
|
||||
|
||||
|
|
@ -877,13 +886,13 @@ export default function Transactions({
|
|||
notes: finalNotes,
|
||||
notes_iv: finalNotesIv,
|
||||
};
|
||||
consoleDebug('Updating transaction with:', updateData);
|
||||
consoleDebug('Queuing update for transaction:', updateData);
|
||||
|
||||
await transactionSyncService.update(
|
||||
transaction.id,
|
||||
updateData,
|
||||
);
|
||||
consoleDebug('✓ Transaction updated in IndexedDB');
|
||||
// Collect for batch IndexedDB update
|
||||
dbUpdates.push({
|
||||
id: transaction.id,
|
||||
data: updateData,
|
||||
});
|
||||
|
||||
const selectedCategory = result.categoryId
|
||||
? categories.find((c) => c.id === result.categoryId) ||
|
||||
|
|
@ -899,7 +908,7 @@ export default function Transactions({
|
|||
);
|
||||
}
|
||||
|
||||
updates.push({
|
||||
allUpdates.push({
|
||||
transaction,
|
||||
categoryId: result.categoryId,
|
||||
category: selectedCategory,
|
||||
|
|
@ -917,34 +926,57 @@ export default function Transactions({
|
|||
}
|
||||
}
|
||||
|
||||
consoleDebug(`\nApplying ${updates.length} updates to UI state...`);
|
||||
if (updates.length > 0) {
|
||||
setTransactions((previous) =>
|
||||
previous.map((transaction) => {
|
||||
const update = updates.find(
|
||||
(u) => u.transaction.id === transaction.id,
|
||||
);
|
||||
if (update) {
|
||||
consoleDebug(
|
||||
`Updating UI for transaction ${transaction.id}:`,
|
||||
{
|
||||
newCategory:
|
||||
update.category?.name || 'None',
|
||||
hasNotes: !!update.decryptedNotes,
|
||||
},
|
||||
);
|
||||
return {
|
||||
...transaction,
|
||||
category_id: update.categoryId,
|
||||
category: update.category,
|
||||
notes: update.notes,
|
||||
notes_iv: update.notesIv,
|
||||
decryptedNotes: update.decryptedNotes,
|
||||
};
|
||||
}
|
||||
return transaction;
|
||||
}),
|
||||
// Batch update IndexedDB
|
||||
if (dbUpdates.length > 0) {
|
||||
consoleDebug(
|
||||
`\nBatch updating ${dbUpdates.length} transactions in IndexedDB...`,
|
||||
);
|
||||
await transactionSyncService.updateManyIndividual(dbUpdates);
|
||||
consoleDebug('✓ IndexedDB batch update complete');
|
||||
}
|
||||
|
||||
// Update UI state in batches
|
||||
consoleDebug(
|
||||
`\nApplying ${allUpdates.length} updates to UI state in batches of ${BATCH_SIZE}...`,
|
||||
);
|
||||
if (allUpdates.length > 0) {
|
||||
for (let i = 0; i < allUpdates.length; i += BATCH_SIZE) {
|
||||
const batch = allUpdates.slice(i, i + BATCH_SIZE);
|
||||
const batchIds = new Set(
|
||||
batch.map((u) => u.transaction.id),
|
||||
);
|
||||
|
||||
consoleDebug(
|
||||
`Applying batch ${Math.floor(i / BATCH_SIZE) + 1} (${batch.length} updates)...`,
|
||||
);
|
||||
|
||||
setTransactions((previous) =>
|
||||
previous.map((transaction) => {
|
||||
if (!batchIds.has(transaction.id)) {
|
||||
return transaction;
|
||||
}
|
||||
const update = batch.find(
|
||||
(u) => u.transaction.id === transaction.id,
|
||||
);
|
||||
if (update) {
|
||||
return {
|
||||
...transaction,
|
||||
category_id: update.categoryId,
|
||||
category: update.category,
|
||||
notes: update.notes,
|
||||
notes_iv: update.notesIv,
|
||||
decryptedNotes: update.decryptedNotes,
|
||||
};
|
||||
}
|
||||
return transaction;
|
||||
}),
|
||||
);
|
||||
|
||||
// Small delay between batches to allow React to process renders
|
||||
if (i + BATCH_SIZE < allUpdates.length) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
}
|
||||
}
|
||||
consoleDebug('✓ UI state updated successfully');
|
||||
} else {
|
||||
consoleDebug('❌ No updates to apply');
|
||||
|
|
|
|||
|
|
@ -497,6 +497,50 @@ class TransactionSyncService {
|
|||
});
|
||||
}
|
||||
|
||||
async updateManyIndividual(
|
||||
updates: Array<{ id: string; data: TransactionUpdateData }>,
|
||||
): Promise<void> {
|
||||
const timestamp = new Date().toISOString();
|
||||
const dbUpdates: Transaction[] = [];
|
||||
const pendingChanges: Array<{
|
||||
store: string;
|
||||
operation: string;
|
||||
data: Transaction;
|
||||
timestamp: string;
|
||||
}> = [];
|
||||
|
||||
for (const { id, data } of updates) {
|
||||
const existing = await this.getById(id);
|
||||
|
||||
if (!existing) {
|
||||
console.warn(`Transaction ${id} not found, skipping`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { label_ids, ...transactionData } = data;
|
||||
|
||||
const updated = {
|
||||
...existing,
|
||||
...transactionData,
|
||||
updated_at: timestamp,
|
||||
} as Transaction;
|
||||
|
||||
dbUpdates.push(updated);
|
||||
pendingChanges.push({
|
||||
store: 'transactions',
|
||||
operation: 'update',
|
||||
data: updated,
|
||||
timestamp,
|
||||
});
|
||||
}
|
||||
|
||||
if (dbUpdates.length > 0) {
|
||||
await db.transactions.bulkPut(dbUpdates);
|
||||
await db.pending_changes.bulkAdd(pendingChanges);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteMany(ids: string[]): Promise<void> {
|
||||
const timestamp = new Date().toISOString();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue