diff --git a/src/lib/common.ts b/src/lib/common.ts index 3b2f569c..a2331bf0 100644 --- a/src/lib/common.ts +++ b/src/lib/common.ts @@ -120,6 +120,26 @@ export function isYearMonthEquals(val1: unknown, val2: unknown): boolean { return (!!parseInt(items1[0]) && !!parseInt(items1[1])) && (parseInt(items1[0]) === parseInt(items2[0])) && (parseInt(items1[1]) === parseInt(items2[1])); } +export function isArray1SubsetOfArray2(array1: T[], array2: T[]): boolean { + if (array1.length > array2.length) { + return false; + } + + const array2ValuesMap: Map = new Map(); + + for (let i = 0; i < array2.length; i++) { + array2ValuesMap.set(array2[i], true); + } + + for (let i = 0; i < array1.length; i++) { + if (!array2ValuesMap.get(array1[i])) { + return false; + } + } + + return true; +} + export function isObjectEmpty(obj: object): boolean { if (!obj) { return true; diff --git a/src/stores/transaction.ts b/src/stores/transaction.ts index 013e385f..ef29aa6a 100644 --- a/src/stores/transaction.ts +++ b/src/stores/transaction.ts @@ -39,6 +39,7 @@ import { isDefined, isNumber, isString, + isArray1SubsetOfArray2, splitItemsToMap, countSplitItems } from '@/lib/common.ts'; @@ -422,7 +423,7 @@ export const useTransactionsStore = defineStore('transactions', () => { } } - function isTransactionDraftModified(transaction?: Transaction): boolean { + function isTransactionDraftModified(transaction?: Transaction, initCategoryId?: string, initAccountId?: string, initTagIds?: string): boolean { if (!transaction) { return false; } @@ -435,11 +436,11 @@ export const useTransactionsStore = defineStore('transactions', () => { return true; } - if (transaction.sourceAccountId && transaction.sourceAccountId !== '0' && transaction.sourceAccountId !== userStore.currentUserDefaultAccountId) { + if (transaction.sourceAccountId && transaction.sourceAccountId !== '0' && transaction.sourceAccountId !== userStore.currentUserDefaultAccountId && transaction.sourceAccountId !== initAccountId) { return true; } - if (transaction.type === TransactionType.Transfer && transaction.destinationAccountId && transaction.destinationAccountId !== '0' && transaction.destinationAccountId !== userStore.currentUserDefaultAccountId) { + if (transaction.type === TransactionType.Transfer && transaction.destinationAccountId && transaction.destinationAccountId !== '0' && transaction.destinationAccountId !== userStore.currentUserDefaultAccountId && transaction.destinationAccountId !== initAccountId) { return true; } @@ -449,19 +450,19 @@ export const useTransactionsStore = defineStore('transactions', () => { if (transaction.type === TransactionType.Expense) { const defaultCategoryId = getFirstAvailableCategoryId(allCategories[CategoryType.Expense]); - if (transaction.expenseCategoryId && transaction.expenseCategoryId !== '0' && transaction.expenseCategoryId !== defaultCategoryId) { + if (transaction.expenseCategoryId && transaction.expenseCategoryId !== '0' && transaction.expenseCategoryId !== defaultCategoryId && transaction.expenseCategoryId !== initCategoryId) { return true; } } else if (transaction.type === TransactionType.Income) { const defaultCategoryId = getFirstAvailableCategoryId(allCategories[CategoryType.Income]); - if (transaction.incomeCategoryId && transaction.incomeCategoryId !== '0' && transaction.incomeCategoryId !== defaultCategoryId) { + if (transaction.incomeCategoryId && transaction.incomeCategoryId !== '0' && transaction.incomeCategoryId !== defaultCategoryId && transaction.incomeCategoryId !== initCategoryId) { return true; } } else if (transaction.type === TransactionType.Transfer) { const defaultCategoryId = getFirstAvailableCategoryId(allCategories[CategoryType.Transfer]); - if (transaction.transferCategoryId && transaction.transferCategoryId !== '0' && transaction.transferCategoryId !== defaultCategoryId) { + if (transaction.transferCategoryId && transaction.transferCategoryId !== '0' && transaction.transferCategoryId !== defaultCategoryId && transaction.transferCategoryId !== initCategoryId) { return true; } } @@ -472,7 +473,7 @@ export const useTransactionsStore = defineStore('transactions', () => { } if (transaction.tagIds && transaction.tagIds.length > 0) { - return true; + return !initTagIds || !isArray1SubsetOfArray2(transaction.tagIds, initTagIds.split(',')); } if (transaction.pictures && transaction.pictures.length > 0) { @@ -486,14 +487,14 @@ export const useTransactionsStore = defineStore('transactions', () => { return false; } - function saveTransactionDraft(transaction?: Transaction): void { + function saveTransactionDraft(transaction?: Transaction, initCategoryId?: string, initAccountId?: string, initTagIds?: string): void { if (settingsStore.appSettings.autoSaveTransactionDraft !== 'enabled' && settingsStore.appSettings.autoSaveTransactionDraft !== 'confirmation') { clearTransactionDraft(); return; } if (transaction) { - if (!isTransactionDraftModified(transaction)) { + if (!isTransactionDraftModified(transaction, initCategoryId, initAccountId, initTagIds)) { clearTransactionDraft(); return; } diff --git a/src/views/desktop/transactions/list/dialogs/EditDialog.vue b/src/views/desktop/transactions/list/dialogs/EditDialog.vue index 5f1f6cd9..f11f63ee 100644 --- a/src/views/desktop/transactions/list/dialogs/EditDialog.vue +++ b/src/views/desktop/transactions/list/dialogs/EditDialog.vue @@ -553,6 +553,10 @@ const geoMenuState = ref(false); const tagSearchContent = ref(''); const removingPictureId = ref(''); +const initCategoryId = ref(undefined); +const initAccountId = ref(undefined); +const initTagIds = ref(undefined); + let resolveFunc: ((response?: TransactionEditResponse) => void) | null = null; let rejectFunc: ((reason?: unknown) => void) | null = null; @@ -603,6 +607,10 @@ function open(options: TransactionEditOptions): Promise { - transactionsStore.saveTransactionDraft(transaction.value); + transactionsStore.saveTransactionDraft(transaction.value, initCategoryId.value, initAccountId.value, initTagIds.value); doClose(); }).catch(() => { transactionsStore.clearTransactionDraft(); @@ -916,7 +924,7 @@ function cancel(): void { doClose(); } } else if (settingsStore.appSettings.autoSaveTransactionDraft === 'enabled') { - transactionsStore.saveTransactionDraft(transaction.value); + transactionsStore.saveTransactionDraft(transaction.value, initCategoryId.value, initAccountId.value, initTagIds.value); doClose(); } else { doClose(); diff --git a/src/views/mobile/transactions/EditPage.vue b/src/views/mobile/transactions/EditPage.vue index e24dde9a..10616775 100644 --- a/src/views/mobile/transactions/EditPage.vue +++ b/src/views/mobile/transactions/EditPage.vue @@ -1127,9 +1127,9 @@ function onPageBeforeOut(): void { } if (settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') { - if (transactionsStore.isTransactionDraftModified(transaction.value)) { + if (transactionsStore.isTransactionDraftModified(transaction.value, query['categoryId'], query['accountId'], query['tagIds'])) { showConfirm('Do you want to save this transaction draft?', () => { - transactionsStore.saveTransactionDraft(transaction.value); + transactionsStore.saveTransactionDraft(transaction.value, query['categoryId'], query['accountId'], query['tagIds']); }, () => { transactionsStore.clearTransactionDraft(); }); @@ -1137,7 +1137,7 @@ function onPageBeforeOut(): void { transactionsStore.clearTransactionDraft(); } } else if (settingsStore.appSettings.autoSaveTransactionDraft === 'enabled') { - transactionsStore.saveTransactionDraft(transaction.value); + transactionsStore.saveTransactionDraft(transaction.value, query['categoryId'], query['accountId'], query['tagIds']); } }