From e097f6b2bb245cd9026eeff378ac609e8fd418de Mon Sep 17 00:00:00 2001 From: adonis Date: Wed, 1 Jul 2026 22:28:25 +0330 Subject: [PATCH] fix some bugs --- index.html | 18 +- src/app/setupRouter.ts | 4 - src/config/load-config.ts | 32 ++- src/config/load-version.ts | 30 +- src/models/order.ts | 1 + src/models/walletAssets.ts | 16 +- src/store/walletStore.ts | 44 +-- src/utils/productAssets.ts | 62 ++++- src/utils/serviceFee.ts | 80 ++++++ src/views/base/copper&silver/index.vue | 19 +- src/views/base/gold/index.vue | 72 +++-- .../base/home/components/AssetsSection.vue | 12 +- .../base/home/components/BalanceSheet.vue | 24 +- .../home/components/PortfolioOverview.vue | 259 ++++++++++++++++++ .../base/home/composables/useHomePage.ts | 5 +- .../components/DesktopAssetsMetrics.vue | 10 +- .../desktop/components/DesktopHomeAlerts.vue | 25 +- .../desktop/layouts/DefaultDesktopHome.vue | 10 +- .../base/home/layouts/configs/boursecu.ts | 1 - .../base/home/layouts/configs/default.ts | 3 +- .../sections/LimitedPriceAlertSection.vue | 28 -- src/views/base/home/layouts/sections/index.ts | 2 - src/views/base/home/layouts/types.ts | 1 - .../base/products/components/DealProduct.vue | 10 - 24 files changed, 579 insertions(+), 189 deletions(-) create mode 100644 src/views/base/home/components/PortfolioOverview.vue delete mode 100644 src/views/base/home/layouts/sections/LimitedPriceAlertSection.vue diff --git a/index.html b/index.html index bbf2d59..7d33675 100644 --- a/index.html +++ b/index.html @@ -365,7 +365,15 @@ } function getVersionUrls() { - return ['https://nerkh.gold/get_version', 'https://tablo.talasevin.ir/get_version', 'https://abshode-service.montgit.ir/server/get_version'] + var protocol = getProtocol() + + return [ + 'https://nerkh.gold/get_version', + 'https://tablo.talasevin.ir/get_version', + 'https://abshode-service.montgit.ir/server/get_version', + protocol + '//212.23.201.173:8381/get_version', + protocol + '//91.212.174.137:4040/server/get_version' + ] } function getConfigUrls() { @@ -492,6 +500,9 @@ localStorage.setItem(VERSION_SUCCESS_URL_KEY, url) return version } catch (error) { + if (localStorage.getItem(VERSION_SUCCESS_URL_KEY) === url) { + localStorage.removeItem(VERSION_SUCCESS_URL_KEY) + } console.warn('Version failed:', url, error) return undefined } finally { @@ -535,6 +546,9 @@ url: url } } catch (error) { + if (localStorage.getItem(CONFIG_SUCCESS_URL_KEY) === url) { + localStorage.removeItem(CONFIG_SUCCESS_URL_KEY) + } console.warn('Config failed:', url, 'round:', round, error) } } @@ -688,7 +702,7 @@ renderRecovering('در حال دریافت تنظیمات جدید برنامه...') var version = await loadRemoteVersion(5) - var freshConfigResult = await fetchFreshConfig(2) + var freshConfigResult = await fetchFreshConfig(5) clearReadableCookies() // clearLocalStorageExceptToken() diff --git a/src/app/setupRouter.ts b/src/app/setupRouter.ts index 1014bc8..03880be 100644 --- a/src/app/setupRouter.ts +++ b/src/app/setupRouter.ts @@ -2,7 +2,6 @@ import { computed, watch } from 'vue' import router from '@/router' import { authenticateWithFingerprint, getToken, isIphone, removeToken } from '@/utils' import { useUserStore } from '@/store/userStore' -import { useWalletStore } from '@/store/walletStore' import { useFundUserStore } from '@/store/fundStore' import type { NavigationGuardNext } from 'vue-router' import { useAuthStore } from '@/store/useAuthStore' @@ -25,7 +24,6 @@ function goToHome(next: NavigationGuardNext) { export function setupRouterGuards() { const userStore = useUserStore() - const walletStore = useWalletStore() const fundStore = useFundUserStore() const authStore = useAuthStore() @@ -38,8 +36,6 @@ export function setupRouterGuards() { async function start() { if (getToken()) { - await walletStore.getLimitedPrice() - await walletStore.getLimitedBuyGold() await fundStore.getMyFund() } } diff --git a/src/config/load-config.ts b/src/config/load-config.ts index 3eebce7..b73be78 100644 --- a/src/config/load-config.ts +++ b/src/config/load-config.ts @@ -2,6 +2,7 @@ import type { AppConfig } from '@/config/types' import { readCachedAppConfig, writeCachedAppConfig } from '@/config/config-cache' const CONFIG_SUCCESS_URL_KEY = 'CONFIG_Success_URL' +export const CONFIG_RETRY_ROUNDS = 5 function getProtocol() { return window.location.protocol === 'https:' ? 'https:' : 'http:' @@ -29,6 +30,12 @@ export function sortConfigUrls(urls: string[]) { }) } +function clearStaleConfigSuccessUrl(url: string) { + if (localStorage.getItem(CONFIG_SUCCESS_URL_KEY) === url) { + localStorage.removeItem(CONFIG_SUCCESS_URL_KEY) + } +} + async function fetchConfig(url: string, timeout = 3000): Promise { const controller = new AbortController() const timeoutId = window.setTimeout(() => controller.abort(), timeout) @@ -59,22 +66,25 @@ async function fetchConfig(url: string, timeout = 3000): Promise { } } -export async function fetchFreshAppConfig(): Promise { +export async function fetchFreshAppConfig(rounds = CONFIG_RETRY_ROUNDS): Promise { const urls = sortConfigUrls(getConfigUrls()) - for (let index = 0; index < urls.length; index++) { - const url = urls[index] + for (let round = 1; round <= rounds; round++) { + for (let index = 0; index < urls.length; index++) { + const url = urls[index] - try { - const timeout = index === urls.length - 1 ? 5000 : 2500 - const config = await fetchConfig(url, timeout) + try { + const timeout = index === urls.length - 1 ? 7000 : 4000 + const config = await fetchConfig(url, timeout) - localStorage.setItem(CONFIG_SUCCESS_URL_KEY, url) - writeCachedAppConfig(config) + localStorage.setItem(CONFIG_SUCCESS_URL_KEY, url) + writeCachedAppConfig(config) - return config - } catch (error) { - console.warn(`Config failed from ${url}`, error) + return config + } catch (error) { + clearStaleConfigSuccessUrl(url) + console.warn(`Config failed from ${url}. Round: ${round}`, error) + } } } diff --git a/src/config/load-version.ts b/src/config/load-version.ts index 04dbc4e..5cbd77d 100644 --- a/src/config/load-version.ts +++ b/src/config/load-version.ts @@ -9,16 +9,24 @@ type VersionResponse = } const VERSION_SUCCESS_URL_KEY = 'VERSION_Success_URL' -const VERSION_RETRY_ROUNDS = 5 +export const VERSION_RETRY_ROUNDS = 5 let versionFetchPromise: Promise | null = null let cachedVersionResult: string | null | undefined +function getProtocol() { + return window.location.protocol === 'https:' ? 'https:' : 'http:' +} + function getVersionUrls() { + const protocol = getProtocol() + return [ 'https://nerkh.gold/get_version', 'https://tablo.talasevin.ir/get_version', - 'https://abshode-service.montgit.ir/server/get_version' + 'https://abshode-service.montgit.ir/server/get_version', + `${protocol}//212.23.201.173:8381/get_version`, + `${protocol}//91.212.174.137:4040/server/get_version` ] } @@ -33,6 +41,12 @@ function sortVersionUrls(urls: string[]) { return [lastSuccessUrl, ...others] } +function clearStaleVersionSuccessUrl(url: string) { + if (localStorage.getItem(VERSION_SUCCESS_URL_KEY) === url) { + localStorage.removeItem(VERSION_SUCCESS_URL_KEY) + } +} + function readUserVersion(user: unknown) { if (!user || typeof user !== 'object' || Array.isArray(user)) { return '' @@ -82,7 +96,6 @@ async function fetchVersion(url: string, timeout = 3500): Promise }) if (!response.ok) { - // Non-2xx/timeout should be treated as "request failed" and we may try the next URL. throw new Error(`Version request failed with status ${response.status}`) } @@ -94,10 +107,8 @@ async function fetchVersion(url: string, timeout = 3500): Promise const version = normalizeVersionResponse(data) - // IMPORTANT: if the request returned 200/ok, we stop here even if we couldn't extract a version. - // This prevents unnecessary looping when the endpoint is "reachable" but returns an empty payload. if (!version) { - return null + throw new Error('Version response is empty') } localStorage.setItem(VERSION_SUCCESS_URL_KEY, url) @@ -118,10 +129,11 @@ async function fetchVersionWithRetry(rounds = VERSION_RETRY_ROUNDS): Promise stop immediately. - return version + if (version) { + return version + } } catch (error) { + clearStaleVersionSuccessUrl(url) console.warn(`Version failed from ${url}. Round: ${round}`, error) } } diff --git a/src/models/order.ts b/src/models/order.ts index 84fd9d9..16da822 100644 --- a/src/models/order.ts +++ b/src/models/order.ts @@ -8,6 +8,7 @@ export interface Order { sts_str?: string payment_sts?: number payment_amount?: number + target_cash?: number service_charge_price?: number total_fee?: number total_price?: number diff --git a/src/models/walletAssets.ts b/src/models/walletAssets.ts index 748bbd5..558fa83 100644 --- a/src/models/walletAssets.ts +++ b/src/models/walletAssets.ts @@ -35,6 +35,19 @@ export interface WalletMetalTotal { unit: string } +export interface WalletPortfolioInsight { + total_rial_value: number + cash_rial: number + metal_rial_value: number + gold_weight: number + gold_rial_value: number + average_buy_price?: number | null + cost_basis_rial?: number | null + unrealized_profit_rial?: number | null + unrealized_profit_percent?: number | null + live_gold_price: number +} + export interface WalletAssetsSummary { meta: WalletAssetsMeta cash_wallet: number @@ -44,5 +57,6 @@ export interface WalletAssetsSummary { assets_rial_value: number total_rial_value: number /** boursecu — سود یا زیان کل دارایی (مثبت = سود، منفی = زیان) */ - profit_loss?: number + profit_loss?: number | null + portfolio?: WalletPortfolioInsight } diff --git a/src/store/walletStore.ts b/src/store/walletStore.ts index 52c678b..d557f67 100644 --- a/src/store/walletStore.ts +++ b/src/store/walletStore.ts @@ -1,15 +1,9 @@ -import { type ComputedRef, ref } from 'vue' +import { ref } from 'vue' import {defineStore} from "pinia"; -import {getMe} from "@/api/me"; -import type {User} from "@/models/login"; import type {Wallet} from "@/models/wallet"; import {getWallet} from "@/api/wallet"; -import type {Const} from "@/models/const"; -import {getConstByKey} from "@/api/const"; export const useWalletStore = defineStore('wallet', () => { const walletInfo = ref(undefined) - const limitedPrice = ref() - const limitedBuyGold = ref() async function getMyWallet() { try { @@ -19,40 +13,6 @@ export const useWalletStore = defineStore('wallet', () => { console.log(e) } } - async function getLimitedPrice(){ - try { - limitedPrice.value = await getConstByKey('limited_price') - return limitedPrice.value - }catch (e) { - console.log(e) - } - } - async function getLimitedBuyGold(){ - try { - limitedBuyGold.value = await getConstByKey('first_customer_wallet_value') - return limitedBuyGold.value - }catch (e) { - console.log(e) - } - } - -/* const permissions: ComputedRef = computed(() => { - const permissions: string[] = get(userInfo.value, 'permission', []) - const excludes: string[] = get(userInfo.value, 'exclude', []) - return permissions.filter((item) => !excludes.includes(item)) - })*/ - -/* - function canAccess(permissionKey: string) { - if (isAdmin.value) return true - return permissions.value.includes(permissionKey) - } -*/ -/* - const isAdmin = computed(() => { - return userInfo.value?.is_admin - })*/ - - return { walletInfo, getMyWallet, getLimitedPrice, getLimitedBuyGold, limitedPrice, limitedBuyGold/* permissions, canAccess, isAdmin*/ } + return { walletInfo, getMyWallet } }) diff --git a/src/utils/productAssets.ts b/src/utils/productAssets.ts index e617968..eccd939 100644 --- a/src/utils/productAssets.ts +++ b/src/utils/productAssets.ts @@ -209,7 +209,7 @@ function formatRialNumber(value: number): string { return usePriceWithoutType(Math.round(value)) } -function formatBoursecuProfitLossLine(profitLoss?: number): BoursecuAssetPopupLine { +function formatBoursecuProfitLossLine(profitLoss?: number | null): BoursecuAssetPopupLine { const amount = Number(profitLoss ?? 0) if (amount > 0) { @@ -398,14 +398,66 @@ export function formatMetalAssetsInfoText(metal: WalletMetalTotal): string { return `${metal.label}: مجموع کیف محصولات (${metal.product_weight} ${unit}) + موجودی کیف اصلی (${metal.melted_weight} ${unit})` } +/** نمایش سود/زیان برای داشبورد */ +export function formatPortfolioProfitLabel(profitRial?: number | null): 'profit' | 'loss' | 'neutral' { + const amount = Number(profitRial ?? 0) + if (amount > 0) return 'profit' + if (amount < 0) return 'loss' + return 'neutral' +} + +export function formatPortfolioProfitText(profitRial?: number | null): string { + const amount = Number(profitRial ?? 0) + if (amount > 0) { + return `+${formatRialNumber(amount)} ریال سود` + } + if (amount < 0) { + return `${formatRialNumber(Math.abs(amount))} ریال زیان` + } + return `${formatRialNumber(0)} ریال` +} + +export function formatPortfolioProfitPercent(percent?: number | null): string { + if (percent == null || Number.isNaN(Number(percent))) { + return '' + } + const value = Number(percent) + const sign = value > 0 ? '+' : '' + return `${sign}${value.toFixed(2)}٪` +} + /** متن توضیح مودال دارایی ریالی */ -export function formatRialAssetsInfoText(cashWallet: number, metalRialValue: number): string { +export function formatRialAssetsInfoText( + cashWallet: number, + metalRialValue: number, + portfolio?: { + unrealized_profit_rial?: number | null + unrealized_profit_percent?: number | null + average_buy_price?: number | null + cost_basis_rial?: number | null + } | null +): string { const total = cashWallet + metalRialValue - return [ + const lines = [ `کیف پول ریالی: ${formatRialNumber(cashWallet)} ریال`, `ارزش ریالی طلا (وزن × قیمت زنده): ${formatRialNumber(metalRialValue)} ریال`, - `مجموع: ${formatRialNumber(total)} ریال`, - ].join('\n') + `مجموع کل دارایی: ${formatRialNumber(total)} ریال`, + ] + + if (portfolio?.average_buy_price != null && portfolio.average_buy_price > 0) { + lines.push(`میانگین قیمت خرید شما: ${formatRialNumber(portfolio.average_buy_price)} ریال`) + } + if (portfolio?.cost_basis_rial != null && portfolio.cost_basis_rial > 0) { + lines.push(`بهای تمام‌شده طلا: ${formatRialNumber(portfolio.cost_basis_rial)} ریال`) + } + if (portfolio?.unrealized_profit_rial != null) { + const pct = formatPortfolioProfitPercent(portfolio.unrealized_profit_percent) + lines.push( + `سود/زیان تحقق‌نیافته: ${formatPortfolioProfitText(portfolio.unrealized_profit_rial)}${pct ? ` (${pct})` : ''}` + ) + } + + return lines.join('\n') } /** ارزش ریالی فلزات از وزن × قیمت زنده — fallback کلاینت قبل از deploy بک‌اند */ diff --git a/src/utils/serviceFee.ts b/src/utils/serviceFee.ts index d2cfdda..c91b6aa 100644 --- a/src/utils/serviceFee.ts +++ b/src/utils/serviceFee.ts @@ -3,6 +3,9 @@ import { getSettings } from '@/api/configuration' export const serviceFeePercentage = ref(0.01) +/** true = مبالغ رند: فروش → ریال دقیق (کارمزد از طلا)؛ خرید → وزن دقیق (کارمزد از ریال) */ +export const feeDeductFromGold = ref(false) + export async function loadServiceFeeFromSettings() { try { const settings = await getSettings() @@ -13,6 +16,16 @@ export async function loadServiceFeeFromSettings() { if (feeSetting?.value !== undefined && feeSetting?.value !== null) { serviceFeePercentage.value = Number(feeSetting.value) } + + const feeModeSetting = settings.find( + (s) => s?.key === 'fee_deduct_from_gold' && s?.is_active === true + ) + if (feeModeSetting?.value !== undefined && feeModeSetting?.value !== null) { + const raw = String(feeModeSetting.value).trim().toLowerCase() + feeDeductFromGold.value = raw === 'true' || raw === '1' + } else { + feeDeductFromGold.value = false + } } } catch (e) { console.log(e) @@ -22,3 +35,70 @@ export async function loadServiceFeeFromSettings() { export function calcFeeInGrams(goldValue?: number | null) { return parseFloat(((goldValue ?? 0) * Number(serviceFeePercentage.value)).toFixed(4)) } + +/** گرم معادل برای دریافت دقیق مبلغ ریالی در فروش */ +export function calcGoldAmountFromTargetRial(rialAmount: number, unitPriceRial: number) { + if (!rialAmount || !unitPriceRial) return 0 + return parseFloat((rialAmount / unitPriceRial).toFixed(6)) +} + +/** مبلغ نهایی قابل پرداخت (خرید) یا دریافت (فروش) به ریال */ +export function calcPayablePriceRial( + finalPriceRial: number, + feeInRial: number, + isBuy: boolean, + targetRialCash?: number | null +) { + if (feeDeductFromGold.value) { + if (isBuy) return finalPriceRial + feeInRial + if (targetRialCash != null && Number(targetRialCash) > 0) return Number(targetRialCash) + return finalPriceRial + } + return isBuy ? finalPriceRial : Math.max(0, finalPriceRial - feeInRial) +} + +/** وزن ارسالی به سرور — فروش رند: از مبلغ ریالی هدف */ +export function calcOrderGoldAmount( + goldValue?: number | null, + goldCash?: number | null, + unitPriceRial?: number, + isBuy?: boolean +) { + const gold = Number(goldValue ?? 0) + if (isBuy || !feeDeductFromGold.value) { + return parseFloat(gold.toFixed(6)) + } + const targetCash = calcSellTargetCash(goldCash, goldValue, unitPriceRial) + const unit = Number(unitPriceRial ?? 0) + if (targetCash != null && unit > 0) { + return calcGoldAmountFromTargetRial(targetCash, unit) + } + return parseFloat(gold.toFixed(6)) +} + +/** مبلغ ریالی دقیق دریافتی در فروش (فقط وقتی کاربر با ریال وارد کرده) */ +export function calcSellTargetCash( + goldCash?: number | null, + goldValue?: number | null, + unitPriceRial?: number +) { + const cash = Number(goldCash ?? 0) + if (!feeDeductFromGold.value || cash <= 0) return undefined + const gold = Number(goldValue ?? 0) + const unit = Number(unitPriceRial ?? 0) + if (gold > 0 && unit > 0) { + const derived = Math.round(gold * unit) + if (Math.abs(derived - Math.round(cash)) <= 1) return undefined + } + return Math.round(cash) +} + +/** کل طلای کسرشونده از کیف در فروش (شامل کارمزد وقتی fee_deduct_from_gold روشن است) */ +export function calcSellGoldDebit(goldValue?: number | null, feeInGrams?: number | null) { + const gold = Number(goldValue ?? 0) + const fee = Number(feeInGrams ?? 0) + if (feeDeductFromGold.value) { + return parseFloat((gold + fee).toFixed(4)) + } + return gold +} diff --git a/src/views/base/copper&silver/index.vue b/src/views/base/copper&silver/index.vue index b28432f..0a896b7 100644 --- a/src/views/base/copper&silver/index.vue +++ b/src/views/base/copper&silver/index.vue @@ -36,11 +36,6 @@
-
- - حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد. -
@@ -236,7 +231,7 @@ import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@ import type { Product } from '@/models/products' import { useFundUserStore } from '@/store/fundStore' import {useConfigStore} from "@/store/configStore"; -import { calcFeeInGrams } from '@/utils/serviceFee' +import { calcFeeInGrams, calcPayablePriceRial, calcSellGoldDebit, feeDeductFromGold, loadServiceFeeFromSettings } from '@/utils/serviceFee' import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod' import { getCashWalletBalance } from '@/utils/productAssets' import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours' @@ -315,8 +310,9 @@ const finalPrice = computed(() => { }) const payablePrice = computed(() => - isBuy.value ? finalPrice.value + feeInRial.value : finalPrice.value - feeInRial.value + calcPayablePriceRial(finalPrice.value, feeInRial.value, isBuy.value) ) +const sellGoldDebit = computed(() => calcSellGoldDebit(form.value?.goldValue, feeInGrams.value)) const feeInGrams = computed(() => calcFeeInGrams(form.value?.goldValue)) const unitPrice = computed(() => (props?.ProductItem?.price_profit ?? 0) + (props?.ProductItem?.price ?? 0) @@ -332,7 +328,8 @@ const disableTransaction = computed(() => form.value?.goldCash === '' || form.value?.goldCash === undefined || (isBuy.value ? (form.value?.goldCash ?? 0) < 500000 : (form.value?.goldValue ?? 0) < 0.001) || - (!isBuy.value && form.value.goldValue > walletStore?.walletInfo?.gold) || + (!isBuy.value && sellGoldDebit.value > (walletStore?.walletInfo?.gold ?? 0)) || + (isBuy.value && payablePrice.value > cashWalletBalance.value) || !lastPrice.value || (isBuy.value ? getTradeBuyPrice(lastPrice.value) <= 0 : getTradeSellPrice(lastPrice.value) <= 0)) @@ -436,6 +433,7 @@ onMounted(async () => { break } await initPrice() + await loadServiceFeeFromSettings() /* await initSellTable() await initBuyTable()*/ }) @@ -499,11 +497,6 @@ const unitCashCalculator = computed(() => { return cashWalletBalance.value / 100 }) -const limitedPrice = computed(() => { - if (walletStore.limitedPrice) - return walletStore?.limitedPrice[0] -}) - /*function calculateCash(val: number) { priceErrorVisible.value = false // console.log(val) diff --git a/src/views/base/gold/index.vue b/src/views/base/gold/index.vue index 10aa80f..a95506f 100644 --- a/src/views/base/gold/index.vue +++ b/src/views/base/gold/index.vue @@ -56,11 +56,6 @@
-
- - حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد. -
@@ -137,13 +132,14 @@
{{ !isBuy ? 'فروش' : 'خرید' }}
-
مقدار {{ weightUnit }} وارد شده جهت فروش ({{ form.goldValue }}{{ weightUnit }}) بیشتر از مقدار موجودی شما ({{ productWalletBalance }}{{ weightUnit }}) می باشد. + (با احتساب {{ feeInGrams }}{{ weightUnit }} کارمزد، مجموعاً {{ sellGoldDebit }}{{ weightUnit }} کسر می‌شود)
-
موجودی کیف پول ناکافی می باشد.
@@ -196,6 +192,20 @@
(معادل {{ equivalentPrice }} ریال)
+
+
طلا دریافتی:
+
+
{{ form.goldValue }}
+
{{ weightUnit }} (دقیق — کارمزد از ریال)
+
+
+
+
کسر از کیف طلا:
+
+
{{ sellGoldDebit }}
+
{{ weightUnit }}
+
+
{{ isBuy ? 'قیمت قابل پرداخت:' : 'مبلغ دریافتی:' }}
@@ -237,6 +247,20 @@
(معادل {{ equivalentPrice }} ریال)
+
+
طلا دریافتی:
+
+
{{ form.goldValue }}
+
{{ weightUnit }} (دقیق — کارمزد از ریال)
+
+
+
+
کسر از کیف طلا:
+
+
{{ sellGoldDebit }}
+
{{ weightUnit }}
+
+
{{ isBuy ? 'قیمت قابل پرداخت:' : 'مبلغ دریافتی:' }}
@@ -306,7 +330,7 @@ import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@ import type { Product } from '@/models/products' import { useFundUserStore } from '@/store/fundStore' import {useConfigStore} from "@/store/configStore"; -import { calcFeeInGrams, loadServiceFeeFromSettings } from '@/utils/serviceFee' +import { calcFeeInGrams, calcOrderGoldAmount, calcPayablePriceRial, calcSellGoldDebit, calcSellTargetCash, feeDeductFromGold, loadServiceFeeFromSettings } from '@/utils/serviceFee' import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours' import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod' import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets' @@ -411,13 +435,22 @@ const unitPrice = computed(() => { } return isBuy.value ? getTradeBuyPrice(lastPrice.value) : getTradeSellPrice(lastPrice.value) }) -const feeInGrams = computed(() => calcFeeInGrams(form.value?.goldValue)) -const finalPrice = computed(() => (form.value?.goldValue ?? 0) * unitPrice.value) +const orderGoldAmount = computed(() => + calcOrderGoldAmount(form.value?.goldValue, form.value?.goldCash, unitPrice.value, isBuy.value) +) +const feeInGrams = computed(() => calcFeeInGrams(orderGoldAmount.value)) +const finalPrice = computed(() => orderGoldAmount.value * unitPrice.value) const feeInRial = computed(() => unitPrice.value * feeInGrams.value) const equivalentPrice = computed(() => usePriceWithoutType(feeInRial.value.toFixed(0))) const payablePrice = computed(() => - isBuy.value ? finalPrice.value + feeInRial.value : finalPrice.value - feeInRial.value + calcPayablePriceRial( + finalPrice.value, + feeInRial.value, + isBuy.value, + !isBuy.value ? form.value?.goldCash : undefined + ) ) +const sellGoldDebit = computed(() => calcSellGoldDebit(orderGoldAmount.value, feeInGrams.value)) const minOrderCash = computed(() => productMinOrderCash(props.ProductItem, isBuy.value)) const maxOrderCash = computed(() => productMaxOrderCash(props.ProductItem)) @@ -444,7 +477,8 @@ const disableTransaction = computed(() => : (form.value?.goldValue ?? 0) < 0.001)) || (maxOrderCash.value != null && (form.value?.goldCash ?? 0) > maxOrderCash.value) || cashValidationMessage.value !== '' || - (!isBuy.value && form.value.goldValue > walletStore?.walletInfo?.gold) || + (!isBuy.value && sellGoldDebit.value > productWalletBalance.value) || + (isBuy.value && payablePrice.value > cashWalletBalance.value) || priceUnavailable.value) function refreshTable() { @@ -609,11 +643,6 @@ const unitCashCalculator = computed(() => { return cashWalletBalance.value / 100 }) -const limitedPrice = computed(() => { - if (walletStore.limitedPrice) - return walletStore?.limitedPrice[0] -}) - function syncFormWithLatestPrice() { const unit = unitPrice.value if (!unit || Number.isNaN(unit)) return @@ -661,7 +690,11 @@ function calculateGold(val: number) { priceErrorVisible.value = false } } else if (val) { - form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / unit))) + if (!isBuy.value && feeDeductFromGold.value) { + form.value.goldValue = parseFloat((val / unit).toFixed(6)) + } else { + form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / unit))) + } priceErrorVisible.value = parseInt(String(finalPrice.value)) > 0 } else if (val.toString() === '') { form.value.goldValue = undefined @@ -744,7 +777,8 @@ async function ok() { await createOrder({ direction: isBuy.value ? 1 : 2, price: Math.round(unitPrice.value), - amount: form.value.goldValue ?? 0, + amount: orderGoldAmount.value, + target_cash: calcSellTargetCash(form.value.goldCash, form.value.goldValue, unitPrice.value), abshode_id: props.ProductItem?.id, }) confirmAction.value = false diff --git a/src/views/base/home/components/AssetsSection.vue b/src/views/base/home/components/AssetsSection.vue index 5145ba1..ec0075a 100644 --- a/src/views/base/home/components/AssetsSection.vue +++ b/src/views/base/home/components/AssetsSection.vue @@ -3,19 +3,21 @@
محصولات:
{{ usePriceWithoutType(countBasedInventory, false) }} عدد
+ + -