From a730ebab8f6bfd863a6b29cdf9bd16cff5a52bf5 Mon Sep 17 00:00:00 2001 From: GaryOu Date: Fri, 9 Jan 2026 00:05:05 +0800 Subject: [PATCH] Refactor transfer amount calculation to handle account changes - Refactor `setTransactionSuitableDestinationAmount` in transactions store to handle account ID changes and avoid logic duplication. - Recalculate transfer-in amount when changing accounts, while preserving manual edits by verifying previous exchange rate relationships. - Clean up redundant calculation logic in `TransactionEditPageBase.ts`. --- src/stores/transaction.ts | 40 +++++++++++------ .../transactions/TransactionEditPageBase.ts | 45 ++----------------- 2 files changed, 31 insertions(+), 54 deletions(-) diff --git a/src/stores/transaction.ts b/src/stores/transaction.ts index a732056e..c839d8d8 100644 --- a/src/stores/transaction.ts +++ b/src/stores/transaction.ts @@ -556,34 +556,48 @@ export const useTransactionsStore = defineStore('transactions', () => { clearUserTransactionDraft(); } - function setTransactionSuitableDestinationAmount(transaction: Transaction, oldValue: number, newValue: number): void { + function setTransactionSuitableDestinationAmount(transaction: Transaction, oldSourceAmount: number, newSourceAmount: number, oldSourceAccountId?: string, oldDestinationAccountId?: string): void { if (transaction.type === TransactionType.Expense || transaction.type === TransactionType.Income) { - transaction.destinationAmount = newValue; + transaction.destinationAmount = newSourceAmount; } else if (transaction.type === TransactionType.Transfer) { const sourceAccount = accountsStore.allAccountsMap[transaction.sourceAccountId]; const destinationAccount = accountsStore.allAccountsMap[transaction.destinationAccountId]; - if (sourceAccount && destinationAccount && sourceAccount.currency !== destinationAccount.currency) { - const decimalNumberCount = getCurrencyFraction(destinationAccount.currency); - const exchangedOldValue = exchangeRatesStore.getExchangedAmount(oldValue, sourceAccount.currency, destinationAccount.currency); - const exchangedNewValue = exchangeRatesStore.getExchangedAmount(newValue, sourceAccount.currency, destinationAccount.currency); + if (!sourceAccount || !destinationAccount) { + return; + } + + const oldSourceAccount = oldSourceAccountId ? accountsStore.allAccountsMap[oldSourceAccountId] : sourceAccount; + const oldDestinationAccount = oldDestinationAccountId ? accountsStore.allAccountsMap[oldDestinationAccountId] : destinationAccount; + + let oldValueToCompare = oldSourceAmount; + let newValueToSet = newSourceAmount; + + if (oldSourceAccount && oldDestinationAccount && oldSourceAccount.currency !== oldDestinationAccount.currency) { + const decimalNumberCount = getCurrencyFraction(oldDestinationAccount.currency); + const exchangedOldValue = exchangeRatesStore.getExchangedAmount(oldSourceAmount, oldSourceAccount.currency, oldDestinationAccount.currency); if (isNumber(decimalNumberCount) && isNumber(exchangedOldValue)) { - oldValue = Math.trunc(exchangedOldValue); - oldValue = getAmountWithDecimalNumberCount(oldValue, decimalNumberCount); + oldValueToCompare = Math.trunc(exchangedOldValue); + oldValueToCompare = getAmountWithDecimalNumberCount(oldValueToCompare, decimalNumberCount); } + } + + if (sourceAccount.currency !== destinationAccount.currency) { + const decimalNumberCount = getCurrencyFraction(destinationAccount.currency); + const exchangedNewValue = exchangeRatesStore.getExchangedAmount(newSourceAmount, sourceAccount.currency, destinationAccount.currency); if (isNumber(decimalNumberCount) && isNumber(exchangedNewValue)) { - newValue = Math.trunc(exchangedNewValue); - newValue = getAmountWithDecimalNumberCount(newValue, decimalNumberCount); + newValueToSet = Math.trunc(exchangedNewValue); + newValueToSet = getAmountWithDecimalNumberCount(newValueToSet, decimalNumberCount); } else { return; } } - if ((!sourceAccount || !destinationAccount || transaction.destinationAmount === oldValue || transaction.destinationAmount === 0) && - (TRANSACTION_MIN_AMOUNT <= newValue && newValue <= TRANSACTION_MAX_AMOUNT)) { - transaction.destinationAmount = newValue; + if ((transaction.destinationAmount === oldValueToCompare || transaction.destinationAmount === 0) && + (TRANSACTION_MIN_AMOUNT <= newValueToSet && newValueToSet <= TRANSACTION_MAX_AMOUNT)) { + transaction.destinationAmount = newValueToSet; } } } diff --git a/src/views/base/transactions/TransactionEditPageBase.ts b/src/views/base/transactions/TransactionEditPageBase.ts index e96f6713..9db98bcf 100644 --- a/src/views/base/transactions/TransactionEditPageBase.ts +++ b/src/views/base/transactions/TransactionEditPageBase.ts @@ -16,7 +16,7 @@ import type { LocalizedTimezoneInfo } from '@/core/timezone.ts'; import { TransactionType } from '@/core/transaction.ts'; import { TemplateType } from '@/core/template.ts'; import { DISPLAY_HIDDEN_AMOUNT } from '@/consts/numeral.ts'; -import { TRANSACTION_MAX_PICTURE_COUNT, TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts'; +import { TRANSACTION_MAX_PICTURE_COUNT } from '@/consts/transaction.ts'; import { Account, type CategorizedAccountWithDisplayBalance } from '@/models/account.ts'; import type { TransactionCategory } from '@/models/transaction_category.ts'; @@ -26,19 +26,13 @@ import { Transaction } from '@/models/transaction.ts'; import { TransactionTemplate } from '@/models/transaction_template.ts'; import { - isArray, - isNumber + isArray } from '@/lib/common.ts'; import { - getExchangedAmountByRate, - getAmountWithDecimalNumberCount + getExchangedAmountByRate } from '@/lib/numeral.ts'; -import { - getCurrencyFraction -} from '@/lib/currency.ts'; - import { getUtcOffsetByUtcOffsetMinutes, getTimezoneOffsetMinutes, @@ -437,11 +431,6 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo return; } - // Only recalculate if accounts actually changed - if (newSourceAccountId === oldSourceAccountId && newDestinationAccountId === oldDestinationAccountId) { - return; - } - // Only recalculate if accounts actually changed (skip initial watch call) if (oldSourceAccountId !== undefined && oldDestinationAccountId !== undefined) { if (newSourceAccountId === oldSourceAccountId && newDestinationAccountId === oldDestinationAccountId) { @@ -449,33 +438,7 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo } } - const sourceAccount = allAccountsMap.value[transaction.value.sourceAccountId]; - const destinationAccount = allAccountsMap.value[transaction.value.destinationAccountId]; - - if (!sourceAccount || !destinationAccount) { - return; - } - - // Recalculate destination amount based on source amount and exchange rate - if (sourceAccount.currency !== destinationAccount.currency) { - const exchangedAmount = exchangeRatesStore.getExchangedAmount(transaction.value.sourceAmount, sourceAccount.currency, destinationAccount.currency); - - if (isNumber(exchangedAmount)) { - const decimalNumberCount = getCurrencyFraction(destinationAccount.currency); - let newDestinationAmount = Math.trunc(exchangedAmount); - - if (isNumber(decimalNumberCount)) { - newDestinationAmount = getAmountWithDecimalNumberCount(newDestinationAmount, decimalNumberCount); - } - - if (TRANSACTION_MIN_AMOUNT <= newDestinationAmount && newDestinationAmount <= TRANSACTION_MAX_AMOUNT) { - transaction.value.destinationAmount = newDestinationAmount; - } - } - } else { - // Same currency, just copy the source amount - transaction.value.destinationAmount = transaction.value.sourceAmount; - } + transactionsStore.setTransactionSuitableDestinationAmount(transaction.value, transaction.value.sourceAmount, transaction.value.sourceAmount, oldSourceAccountId as string, oldDestinationAccountId as string); }); return {