diff --git a/src/views/base/transactions/TransactionEditPageBase.ts b/src/views/base/transactions/TransactionEditPageBase.ts index 17df0a20..e96f6713 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 } from '@/consts/transaction.ts'; +import { TRANSACTION_MAX_PICTURE_COUNT, TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts'; import { Account, type CategorizedAccountWithDisplayBalance } from '@/models/account.ts'; import type { TransactionCategory } from '@/models/transaction_category.ts'; @@ -26,13 +26,19 @@ import { Transaction } from '@/models/transaction.ts'; import { TransactionTemplate } from '@/models/transaction_template.ts'; import { - isArray + isArray, + isNumber } from '@/lib/common.ts'; import { - getExchangedAmountByRate + getExchangedAmountByRate, + getAmountWithDecimalNumberCount } from '@/lib/numeral.ts'; +import { + getCurrencyFraction +} from '@/lib/currency.ts'; + import { getUtcOffsetByUtcOffsetMinutes, getTimezoneOffsetMinutes, @@ -421,6 +427,57 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo } }); + // Watch for account changes and recalculate destination amount for transfers + watch(() => [transaction.value.sourceAccountId, transaction.value.destinationAccountId], ([newSourceAccountId, newDestinationAccountId], [oldSourceAccountId, oldDestinationAccountId]) => { + if (mode.value === TransactionEditPageMode.View || loading.value) { + return; + } + + if (transaction.value.type !== TransactionType.Transfer) { + 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) { + return; + } + } + + 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; + } + }); + return { // constants isSupportGeoLocation,