fix(trade): keep exact grams when the input shows rounded display
Percent and cash conversions no longer lose precision by rounding the gram field to three decimals. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -65,6 +65,44 @@ export function formatTradeGramInputValue(grams?: number | null): string | undef
|
||||
return value.toFixed(TRADE_GRAM_INPUT_DECIMALS)
|
||||
}
|
||||
|
||||
/** متن اینپوت گرم — فقط نمایش سهرقمی؛ منبع حقیقت همان گرم دقیق است */
|
||||
export function tradeGramInputDisplay(exactGrams?: number | string | null): string {
|
||||
if (exactGrams === undefined || exactGrams === null || exactGrams === '') return ''
|
||||
const n = Number(exactGrams)
|
||||
if (!Number.isFinite(n) || n <= 0) return ''
|
||||
return formatTradeGramInputValue(n) ?? ''
|
||||
}
|
||||
|
||||
/** گرم دقیق از درصد کیف — بدون رند نمایشی اینپوت */
|
||||
export function exactGoldFromWalletPercent(balance: number, percent: number): number {
|
||||
if (!(Number(percent) > 0) || !(Number(balance) > 0)) return 0
|
||||
return normalizeOrderGoldAmount((Number(balance) * Number(percent)) / 100)
|
||||
}
|
||||
|
||||
/**
|
||||
* اگر متن اینپوت همان نمایش سهرقمی مقدار دقیق فعلی باشد، دقیق را نگه میدارد.
|
||||
* در غیر این صورت عدد تایپشده منبع حقیقت میشود.
|
||||
*/
|
||||
export function goldFromGramInputDisplay(
|
||||
raw: unknown,
|
||||
exactGrams?: number | string | null
|
||||
): number | undefined {
|
||||
if (raw === '' || raw == null) return undefined
|
||||
const text = String(raw).trim()
|
||||
if (text === '') return undefined
|
||||
const typed = Number(text)
|
||||
if (!Number.isFinite(typed) || typed <= 0) return undefined
|
||||
|
||||
const exact = Number(exactGrams)
|
||||
if (Number.isFinite(exact) && exact > 0) {
|
||||
const shown = formatTradeGramInputValue(exact)
|
||||
if (shown != null && text === shown) {
|
||||
return normalizeOrderGoldAmount(exact)
|
||||
}
|
||||
}
|
||||
return normalizeOrderGoldAmount(typed)
|
||||
}
|
||||
|
||||
function feeRate() {
|
||||
return Number(serviceFeePercentage.value)
|
||||
}
|
||||
|
||||
@@ -81,10 +81,10 @@
|
||||
type="price" @onchange="calculateGold" />
|
||||
</a-form-item>
|
||||
<a-form-item :rules="[justNumber()]">
|
||||
<BasicInput v-model:value="form.goldValue" :addon-before="weightUnit" :addon-bg-color="colors.primary"
|
||||
<BasicInput v-model:value="goldValueInput" :addon-before="weightUnit" :addon-bg-color="colors.primary"
|
||||
addon-text-color="white"
|
||||
:place-holder="amountFieldLabel"
|
||||
size="large" type="text" inputmode="decimal" @onchange="calculateCash" />
|
||||
size="large" type="text" inputmode="decimal" />
|
||||
</a-form-item>
|
||||
<div v-if="cashValidationMessage" class="text-red-700 text-xs font-bold mt-2">
|
||||
{{ cashValidationMessage }}
|
||||
@@ -289,7 +289,9 @@ import {
|
||||
calcTradeTargetCash,
|
||||
buildTradeConfirmBreakdown,
|
||||
formatTradeGramDisplay,
|
||||
formatTradeGramInputValue,
|
||||
tradeGramInputDisplay,
|
||||
exactGoldFromWalletPercent,
|
||||
goldFromGramInputDisplay,
|
||||
loadServiceFeeFromSettings,
|
||||
normalizeOrderGoldAmount,
|
||||
serviceFeePercentage,
|
||||
@@ -306,7 +308,7 @@ import {
|
||||
resolveProductTradeIsBuy,
|
||||
} from '@/utils/productTradeOpen'
|
||||
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
|
||||
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
|
||||
import { formatProductWalletBalanceText, getCashWalletBalance } from '@/utils/productAssets'
|
||||
import { useWalletAssets } from '@/composables/useWalletAssets'
|
||||
import { usesQuantityTrade } from '@/utils/productCategories'
|
||||
import { useSettingsStore } from '@/store/settingsStore'
|
||||
@@ -367,11 +369,7 @@ const tradeProductLabel = computed(() => {
|
||||
const amountFieldLabel = computed(() => `مقدار ${tradeProductLabel.value}`)
|
||||
|
||||
const productWalletBalance = computed(() =>
|
||||
getProductInventoryQuantity(
|
||||
assetsSummary.value?.inventory_cards ?? [],
|
||||
props.ProductItem?.id,
|
||||
walletStore?.walletInfo?.gold
|
||||
)
|
||||
Number(walletStore?.walletInfo?.gold ?? 0)
|
||||
)
|
||||
|
||||
const productWalletBalanceText = computed(() =>
|
||||
@@ -443,6 +441,24 @@ const displayTradeGoldAmount = computed(() =>
|
||||
formatTradeGramDisplay(orderGoldAmount.value)
|
||||
)
|
||||
|
||||
const goldValueInput = computed({
|
||||
get() {
|
||||
const display = tradeGramInputDisplay(form.value.goldValue)
|
||||
return display === '' ? undefined : display
|
||||
},
|
||||
set(raw: string | number | null | undefined) {
|
||||
const next = goldFromGramInputDisplay(raw, form.value.goldValue)
|
||||
form.value.goldValue = next
|
||||
if (next == null) {
|
||||
form.value.goldCash = undefined
|
||||
form.value.percentWallet = 0
|
||||
inputLock.value = null
|
||||
return
|
||||
}
|
||||
calculateCash(next)
|
||||
},
|
||||
})
|
||||
|
||||
const feeFormHint = computed(() =>
|
||||
buildTradeConfirmBreakdown({
|
||||
isBuy: isBuy.value,
|
||||
@@ -634,9 +650,10 @@ function percentChange(val: number) {
|
||||
form.value.goldCash = unitCashCalculator.value * val
|
||||
calculateGold(form.value.goldCash)
|
||||
} else {
|
||||
form.value.goldValue = formatTradeGramInputValue(parseFloat(String(unitGoldCalculator.value * val)))
|
||||
if (form.value.goldValue != null) {
|
||||
calculateCash(Number(form.value.goldValue))
|
||||
const grams = exactGoldFromWalletPercent(productWalletBalance.value, val)
|
||||
form.value.goldValue = grams > 0 ? grams : undefined
|
||||
if (grams > 0) {
|
||||
calculateCash(grams)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -646,8 +663,6 @@ function percentChange(val: number) {
|
||||
}
|
||||
}
|
||||
|
||||
const unitGoldCalculator = computed(() => productWalletBalance.value / 100)
|
||||
|
||||
const unitCashCalculator = computed(() => {
|
||||
return cashWalletBalance.value / 100
|
||||
})
|
||||
@@ -701,7 +716,8 @@ function calculateGold(val: number) {
|
||||
if (!unit || Number.isNaN(unit)) return
|
||||
|
||||
if (val) {
|
||||
form.value.goldValue = formatTradeGramInputValue(calcGramFromLockedRial(val, unit, isBuy.value))
|
||||
const grams = calcGramFromLockedRial(val, unit, isBuy.value)
|
||||
form.value.goldValue = grams > 0 ? grams : undefined
|
||||
} else if (val.toString() === '') {
|
||||
form.value.goldValue = undefined
|
||||
inputLock.value = null
|
||||
|
||||
Reference in New Issue
Block a user