fix price
This commit is contained in:
@@ -34,7 +34,8 @@ export function isProductTradingHoursOpen(
|
||||
auto_close_at?: string | null
|
||||
} | null,
|
||||
) {
|
||||
if (!product) return false
|
||||
// روت /gold محصول را prop نمیگیرد؛ نبود محصول یعنی ساعت محصول اعمال نشود (مثل open_buy)
|
||||
if (!product) return true
|
||||
if (isOutsideProductActivationWindow(product)) return false
|
||||
if (typeof product.trade_open === 'boolean') return product.trade_open
|
||||
return product.show === true
|
||||
|
||||
+109
-24
@@ -27,7 +27,7 @@
|
||||
class="w-full h-10 flex items-center justify-center font-bold rounded-full transition-all"
|
||||
:class="isBuy ? 'bg-green-600 text-white shadow-sm' : 'text-green-600'"
|
||||
@click.stop="setIsBuy(true)"
|
||||
:style="!isProductBuyOpen(props?.ProductItem) ? 'pointer-events: none; opacity: 0.35;' : ''"
|
||||
:style="!isProductBuyOpen(tradeProduct) ? 'pointer-events: none; opacity: 0.35;' : ''"
|
||||
>
|
||||
خرید
|
||||
</div>
|
||||
@@ -35,7 +35,7 @@
|
||||
class="w-full h-10 flex items-center justify-center font-bold rounded-full transition-all"
|
||||
:class="!isBuy ? 'bg-red-600 text-white shadow-sm' : 'text-red-600'"
|
||||
@click.stop="setIsBuy(false)"
|
||||
:style="!isProductSellOpen(props?.ProductItem) ? 'pointer-events: none; opacity: 0.35;' : ''"
|
||||
:style="!isProductSellOpen(tradeProduct) ? 'pointer-events: none; opacity: 0.35;' : ''"
|
||||
>
|
||||
فروش
|
||||
</div>
|
||||
@@ -98,7 +98,7 @@
|
||||
</div>-->
|
||||
</div>
|
||||
<div v-else class="font-bold text-xs">
|
||||
{{ formatCashWalletBalanceText(usePriceWithoutType(cashWalletBalance), props?.ProductItem?.group_type) }}
|
||||
{{ formatCashWalletBalanceText(usePriceWithoutType(cashWalletBalance), tradeProduct?.group_type) }}
|
||||
</div>
|
||||
</Transition>
|
||||
<Transition mode="out-in" name="fade">
|
||||
@@ -241,7 +241,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import img1 from '@/assets/img/home_ly2.svg'
|
||||
import { usePrice, usePriceWithoutType } from '@/utils/usePrice'
|
||||
import BasicInput from '@/components/BasicPacks/BasicInput.vue'
|
||||
@@ -313,6 +313,12 @@ import {
|
||||
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
|
||||
import { formatProductWalletBalanceText, getCashWalletBalance } from '@/utils/productAssets'
|
||||
import { useWalletAssets } from '@/composables/useWalletAssets'
|
||||
import {
|
||||
findProductInCatalog,
|
||||
getProductsCatalog,
|
||||
getProductsCatalogRef,
|
||||
} from '@/composables/useProductsCatalog'
|
||||
import { subscribeProductListStream } from '@/utils/productStreamBridge'
|
||||
import { usesQuantityTrade } from '@/utils/productCategories'
|
||||
import { useSettingsStore } from '@/store/settingsStore'
|
||||
import { storeToRefs } from 'pinia'
|
||||
@@ -365,8 +371,54 @@ const contentClass = computed(() => {
|
||||
const isBuy = ref<boolean>(true)
|
||||
const inputLock = ref<TradeInputLock>(null)
|
||||
|
||||
const catalogProducts = getProductsCatalogRef()
|
||||
const standaloneProductId = ref<number>()
|
||||
let unsubscribeProductStream: (() => void) | undefined
|
||||
|
||||
/** شناسه محصول آبشده از استریم last / تنظیمات — مثل مسیر خرید محصول */
|
||||
function resolveMeltedTradeProductId(): number | undefined {
|
||||
const fromPrice = Number(lastPrice.value?.main_product ?? 0)
|
||||
if (Number.isFinite(fromPrice) && fromPrice > 0) return fromPrice
|
||||
|
||||
const mainProduct = Number(settingsStore.getSettingByKey('main_product') ?? 0)
|
||||
if (Number.isFinite(mainProduct) && mainProduct > 0) return mainProduct
|
||||
|
||||
const raw = String(settingsStore.getSettingByKey('main_wallet_products') ?? '').trim()
|
||||
if (!raw) return undefined
|
||||
|
||||
let parts: unknown[] = []
|
||||
try {
|
||||
const decoded = JSON.parse(raw)
|
||||
parts = Array.isArray(decoded) ? decoded : raw.split(',')
|
||||
} catch {
|
||||
parts = raw.split(',')
|
||||
}
|
||||
|
||||
for (const part of parts) {
|
||||
const id = Number(String(part).trim())
|
||||
if (Number.isFinite(id) && id > 0) return id
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
function pickStandaloneMeltedProduct(): Product | undefined {
|
||||
void catalogProducts.value
|
||||
const id = standaloneProductId.value ?? resolveMeltedTradeProductId()
|
||||
if (id) {
|
||||
const match = findProductInCatalog(id)
|
||||
?? catalogProducts.value.find((product) => Number(product.id) === Number(id))
|
||||
if (match) return match
|
||||
}
|
||||
|
||||
return catalogProducts.value.find((product) => product.title === 'آبشده نقدی')
|
||||
?? catalogProducts.value.find((product) => product.group_type === 'آبشده')
|
||||
}
|
||||
|
||||
const tradeProduct = computed(() => props.ProductItem ?? pickStandaloneMeltedProduct())
|
||||
|
||||
const tradeProductLabel = computed(() => {
|
||||
const title = props.ProductItem?.title?.trim()
|
||||
const title = tradeProduct.value?.title?.trim()
|
||||
return title || meltedGoldLabel.value
|
||||
})
|
||||
const amountFieldLabel = computed(() => `مقدار ${tradeProductLabel.value}`)
|
||||
@@ -377,7 +429,7 @@ const productWalletBalance = computed(() =>
|
||||
|
||||
const productWalletBalanceText = computed(() =>
|
||||
formatProductWalletBalanceText(
|
||||
props.ProductItem,
|
||||
tradeProduct.value,
|
||||
assetsSummary.value?.inventory_cards ?? [],
|
||||
walletStore?.walletInfo?.gold
|
||||
)
|
||||
@@ -403,7 +455,7 @@ const sellPagination = ref<TableEngineInput>({
|
||||
})
|
||||
|
||||
const unitPrice = computed(() => {
|
||||
const product = props.ProductItem
|
||||
const product = tradeProduct.value
|
||||
if (usesQuantityTrade(product)) {
|
||||
return isBuy.value ? getProductBuyPrice(product!) : getProductSellPrice(product!)
|
||||
}
|
||||
@@ -498,10 +550,10 @@ const feeFormHint = computed(() =>
|
||||
}).formHint
|
||||
)
|
||||
|
||||
const minOrderCash = computed(() => productMinOrderCash(props.ProductItem, isBuy.value))
|
||||
const maxOrderCash = computed(() => productMaxOrderCash(props.ProductItem))
|
||||
const minOrderCash = computed(() => productMinOrderCash(tradeProduct.value, isBuy.value))
|
||||
const maxOrderCash = computed(() => productMaxOrderCash(tradeProduct.value))
|
||||
const cashValidationMessage = computed(() =>
|
||||
productCashValidationMessage(props.ProductItem, form.value?.goldCash, isBuy.value, usePriceWithoutType)
|
||||
productCashValidationMessage(tradeProduct.value, form.value?.goldCash, isBuy.value, usePriceWithoutType)
|
||||
)
|
||||
|
||||
const priceUnavailable = computed(() => {
|
||||
@@ -512,15 +564,15 @@ const priceUnavailable = computed(() => {
|
||||
const disableTransaction = computed(() =>
|
||||
loading.value ||
|
||||
isStoreClosed() ||
|
||||
!isProductTradingHoursOpen(props.ProductItem) ||
|
||||
!isProductTradeOpen(props.ProductItem, isBuy.value) ||
|
||||
!isProductTradingHoursOpen(tradeProduct.value) ||
|
||||
!isProductTradeOpen(tradeProduct.value, isBuy.value) ||
|
||||
form.value?.goldValue === undefined ||
|
||||
form.value?.goldValue === '' ||
|
||||
form.value?.goldCash === '' ||
|
||||
form.value?.goldCash === undefined ||
|
||||
(isBuy.value
|
||||
? (form.value?.goldCash ?? 0) < minOrderCash.value
|
||||
: (productMinOrderCash(props.ProductItem, false) > 0 || productMaxOrderCash(props.ProductItem) != null
|
||||
: (productMinOrderCash(tradeProduct.value, false) > 0 || productMaxOrderCash(tradeProduct.value) != null
|
||||
? ((form.value?.goldCash ?? 0) < minOrderCash.value || (maxOrderCash.value != null && (form.value?.goldCash ?? 0) > maxOrderCash.value))
|
||||
: (form.value?.goldValue ?? 0) < 0.001)) ||
|
||||
(maxOrderCash.value != null && (form.value?.goldCash ?? 0) > maxOrderCash.value) ||
|
||||
@@ -620,8 +672,25 @@ async function initSellTable() {
|
||||
// }
|
||||
|
||||
onMounted(async () => {
|
||||
if (!props.ProductItem) {
|
||||
try {
|
||||
await getProductsCatalog()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
unsubscribeProductStream = subscribeProductListStream((products) => {
|
||||
if (Array.isArray(products) && products.length) {
|
||||
catalogProducts.value = products
|
||||
}
|
||||
})
|
||||
standaloneProductId.value = resolveMeltedTradeProductId()
|
||||
const picked = pickStandaloneMeltedProduct()
|
||||
if (picked?.id) {
|
||||
standaloneProductId.value = Number(picked.id)
|
||||
}
|
||||
}
|
||||
isBuy.value = resolveProductTradeIsBuy(
|
||||
props?.ProductItem,
|
||||
tradeProduct.value,
|
||||
router.currentRoute.value.query.state?.toString(),
|
||||
)
|
||||
await initPrice()
|
||||
@@ -630,10 +699,26 @@ onMounted(async () => {
|
||||
await initBuyTable()*/
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
unsubscribeProductStream?.()
|
||||
unsubscribeProductStream = undefined
|
||||
})
|
||||
|
||||
watch(
|
||||
() => [props?.ProductItem?.id, props?.ProductItem?.open_buy, props?.ProductItem?.open_sell],
|
||||
() => [tradeProduct.value?.id, tradeProduct.value?.open_buy, tradeProduct.value?.open_sell],
|
||||
() => {
|
||||
isBuy.value = resolveProductTradeIsBuy(props?.ProductItem, isBuy.value ? 'buy' : 'sell')
|
||||
isBuy.value = resolveProductTradeIsBuy(tradeProduct.value, isBuy.value ? 'buy' : 'sell')
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => lastPrice.value?.main_product,
|
||||
(id) => {
|
||||
if (props.ProductItem) return
|
||||
const next = Number(id)
|
||||
if (Number.isFinite(next) && next > 0) {
|
||||
standaloneProductId.value = next
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -713,7 +798,7 @@ function syncFormWithLatestPrice() {
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [unitPrice.value, isBuy.value, props.ProductItem?.id],
|
||||
() => [unitPrice.value, isBuy.value, tradeProduct.value?.id],
|
||||
() => {
|
||||
syncFormWithLatestPrice()
|
||||
}
|
||||
@@ -769,8 +854,8 @@ function useStyle() {
|
||||
|
||||
|
||||
function setIsBuy(val: boolean) {
|
||||
if (val && !isProductBuyOpen(props?.ProductItem)) return
|
||||
if (!val && !isProductSellOpen(props?.ProductItem)) return
|
||||
if (val && !isProductBuyOpen(tradeProduct.value)) return
|
||||
if (!val && !isProductSellOpen(tradeProduct.value)) return
|
||||
isBuy.value = val
|
||||
form.value.goldValue = undefined
|
||||
form.value.goldCash = undefined
|
||||
@@ -811,11 +896,11 @@ function okConfirm() {
|
||||
message.warning(getStoreClosedMessage())
|
||||
return
|
||||
}
|
||||
if (!isProductTradingHoursOpen(props.ProductItem)) {
|
||||
if (!isProductTradingHoursOpen(tradeProduct.value)) {
|
||||
message.warning(productHoursClosedMessage())
|
||||
return
|
||||
}
|
||||
if (!isProductTradeOpen(props.ProductItem, isBuy.value)) {
|
||||
if (!isProductTradeOpen(tradeProduct.value, isBuy.value)) {
|
||||
message.warning(productTradeClosedMessage(isBuy.value))
|
||||
return
|
||||
}
|
||||
@@ -834,11 +919,11 @@ async function ok() {
|
||||
message.warning(getStoreClosedMessage())
|
||||
return
|
||||
}
|
||||
if (!isProductTradingHoursOpen(props.ProductItem)) {
|
||||
if (!isProductTradingHoursOpen(tradeProduct.value)) {
|
||||
message.warning(productHoursClosedMessage())
|
||||
return
|
||||
}
|
||||
if (!isProductTradeOpen(props.ProductItem, isBuy.value)) {
|
||||
if (!isProductTradeOpen(tradeProduct.value, isBuy.value)) {
|
||||
message.warning(productTradeClosedMessage(isBuy.value))
|
||||
return
|
||||
}
|
||||
@@ -853,7 +938,7 @@ async function ok() {
|
||||
amount: normalizeOrderGoldAmount(orderGoldAmount.value),
|
||||
// ریال قفل → مبلغ دقیق به سرور میرود (کارمزد از طلا). گرم قفل → target_cash خالی، وزن دقیق معامله میشود.
|
||||
target_cash: calcTradeTargetCash(form.value.goldCash, inputLock.value),
|
||||
abshode_id: props.ProductItem?.id,
|
||||
abshode_id: tradeProduct.value?.id,
|
||||
})
|
||||
const result = await afterCreateOrder(res)
|
||||
if (result !== 'success') {
|
||||
|
||||
Reference in New Issue
Block a user