added pargar
This commit is contained in:
@@ -39,11 +39,13 @@ export function getProductDisplayImage(product?: {
|
||||
return resolveProductImageSrc(product)
|
||||
}
|
||||
|
||||
import { formatGoldAmount } from '@/utils/usePrice'
|
||||
|
||||
export function formatMetalTotal(
|
||||
metal: WalletMetalTotal,
|
||||
inventoryCards: WalletInventoryCard[]
|
||||
): string {
|
||||
return `${resolveSummaryMetalWeight(metal, inventoryCards)}${metal.unit}`
|
||||
return `${formatGoldAmount(resolveSummaryMetalWeight(metal, inventoryCards))}${metal.unit}`
|
||||
}
|
||||
|
||||
export function resolveAssetsRialValue(
|
||||
|
||||
+115
-13
@@ -6,6 +6,31 @@ export const serviceFeePercentage = ref<number>(0.01)
|
||||
/** true = مبالغ رند: فروش → ریال دقیق (کارمزد از طلا)؛ خرید → وزن دقیق (کارمزد از ریال) */
|
||||
export const feeDeductFromGold = ref(false)
|
||||
|
||||
/** آخرین فیلدی که کاربر مستقیم ویرایش کرده — مبنای بهروزرسانی هنگام تغییر قیمت */
|
||||
export type TradeInputLock = 'gram' | 'rial' | null
|
||||
|
||||
/** حداکثر اعشار ذخیره/ارسال به سرور (مطابق orders.amount) */
|
||||
export const TRADE_GRAM_STORAGE_DECIMALS = 10
|
||||
|
||||
/** حداکثر اعشار نمایش به کاربر در اپ */
|
||||
export const TRADE_GRAM_DISPLAY_DECIMALS = 8
|
||||
|
||||
export function normalizeOrderGoldAmount(grams?: number | null): number {
|
||||
const value = Number(grams ?? 0)
|
||||
if (!Number.isFinite(value) || value === 0) return 0
|
||||
return parseFloat(value.toFixed(TRADE_GRAM_STORAGE_DECIMALS))
|
||||
}
|
||||
|
||||
export function formatTradeGramDisplay(grams?: number | null): number {
|
||||
const value = Number(grams ?? 0)
|
||||
if (!Number.isFinite(value)) return 0
|
||||
return parseFloat(value.toFixed(TRADE_GRAM_DISPLAY_DECIMALS))
|
||||
}
|
||||
|
||||
function feeRate() {
|
||||
return Number(serviceFeePercentage.value)
|
||||
}
|
||||
|
||||
export async function loadServiceFeeFromSettings() {
|
||||
try {
|
||||
const settings = await getSettings()
|
||||
@@ -39,7 +64,58 @@ export function calcFeeInGrams(goldValue?: number | null) {
|
||||
/** گرم معادل برای دریافت دقیق مبلغ ریالی در فروش */
|
||||
export function calcGoldAmountFromTargetRial(rialAmount: number, unitPriceRial: number) {
|
||||
if (!rialAmount || !unitPriceRial) return 0
|
||||
return parseFloat((rialAmount / unitPriceRial).toFixed(6))
|
||||
return normalizeOrderGoldAmount(rialAmount / unitPriceRial)
|
||||
}
|
||||
|
||||
/** وقتی کاربر گرم را قفل کرده — ریال نمایشی/قابل پرداخت از همان گرم */
|
||||
export function calcRialFromLockedGram(displayGram: number, unitPriceRial: number, isBuy: boolean) {
|
||||
const grams = Number(displayGram)
|
||||
const unit = Number(unitPriceRial)
|
||||
if (!grams || !unit) return 0
|
||||
const fee = feeRate()
|
||||
|
||||
if (isBuy) {
|
||||
if (feeDeductFromGold.value) {
|
||||
return Math.round(grams * unit * (1 + fee))
|
||||
}
|
||||
return Math.round(grams * unit)
|
||||
}
|
||||
|
||||
if (feeDeductFromGold.value) {
|
||||
return Math.round(grams * unit)
|
||||
}
|
||||
return Math.round(grams * unit * (1 - fee))
|
||||
}
|
||||
|
||||
/** وقتی کاربر ریال را قفل کرده — گرم نمایشی از همان مبلغ */
|
||||
export function calcGramFromLockedRial(rialAmount: number, unitPriceRial: number, isBuy: boolean) {
|
||||
const rial = Number(rialAmount)
|
||||
const unit = Number(unitPriceRial)
|
||||
if (!rial || !unit) return 0
|
||||
const fee = feeRate()
|
||||
|
||||
if (isBuy) {
|
||||
if (feeDeductFromGold.value) {
|
||||
return rial / (unit * (1 + fee))
|
||||
}
|
||||
return (rial / unit) * (1 - fee)
|
||||
}
|
||||
|
||||
if (feeDeductFromGold.value) {
|
||||
return rial / unit
|
||||
}
|
||||
return rial / (unit * (1 - fee))
|
||||
}
|
||||
|
||||
/** مبلغ ریالی قفلشده توسط کاربر — برای ارسال به سرور */
|
||||
export function calcTradeTargetCash(
|
||||
goldCash?: number | null,
|
||||
inputLock?: TradeInputLock,
|
||||
): number | undefined {
|
||||
if (inputLock !== 'rial') return undefined
|
||||
const cash = Number(goldCash ?? 0)
|
||||
if (cash <= 0) return undefined
|
||||
return Math.round(cash)
|
||||
}
|
||||
|
||||
/** مبلغ نهایی قابل پرداخت (خرید) یا دریافت (فروش) به ریال */
|
||||
@@ -49,41 +125,67 @@ export function calcPayablePriceRial(
|
||||
isBuy: boolean,
|
||||
targetRialCash?: number | null
|
||||
) {
|
||||
if (targetRialCash != null && Number(targetRialCash) > 0) {
|
||||
return Number(targetRialCash)
|
||||
}
|
||||
|
||||
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
|
||||
isBuy?: boolean,
|
||||
inputLock?: TradeInputLock
|
||||
) {
|
||||
const gold = Number(goldValue ?? 0)
|
||||
if (isBuy || !feeDeductFromGold.value) {
|
||||
return parseFloat(gold.toFixed(6))
|
||||
}
|
||||
const targetCash = calcSellTargetCash(goldCash, goldValue, unitPriceRial)
|
||||
const cash = Number(goldCash ?? 0)
|
||||
const unit = Number(unitPriceRial ?? 0)
|
||||
if (targetCash != null && unit > 0) {
|
||||
return calcGoldAmountFromTargetRial(targetCash, unit)
|
||||
|
||||
if (isBuy && inputLock === 'rial' && cash > 0 && unit > 0) {
|
||||
if (feeDeductFromGold.value) {
|
||||
const fee = feeRate()
|
||||
return normalizeOrderGoldAmount(cash / (unit * (1 + fee)))
|
||||
}
|
||||
return normalizeOrderGoldAmount(cash / unit)
|
||||
}
|
||||
return parseFloat(gold.toFixed(6))
|
||||
|
||||
if (!isBuy && feeDeductFromGold.value) {
|
||||
if (inputLock === 'rial' && cash > 0 && unit > 0) {
|
||||
return calcGoldAmountFromTargetRial(cash, unit)
|
||||
}
|
||||
if (inputLock !== 'rial') {
|
||||
return normalizeOrderGoldAmount(gold)
|
||||
}
|
||||
const targetCash = calcSellTargetCash(goldCash, goldValue, unitPriceRial, inputLock)
|
||||
if (targetCash != null && unit > 0) {
|
||||
return calcGoldAmountFromTargetRial(targetCash, unit)
|
||||
}
|
||||
}
|
||||
|
||||
return normalizeOrderGoldAmount(gold)
|
||||
}
|
||||
|
||||
/** مبلغ ریالی دقیق دریافتی در فروش (فقط وقتی کاربر با ریال وارد کرده) */
|
||||
export function calcSellTargetCash(
|
||||
goldCash?: number | null,
|
||||
goldValue?: number | null,
|
||||
unitPriceRial?: number
|
||||
unitPriceRial?: number,
|
||||
inputLock?: TradeInputLock
|
||||
) {
|
||||
if (!feeDeductFromGold.value) return undefined
|
||||
if (inputLock === 'gram') return undefined
|
||||
|
||||
const cash = Number(goldCash ?? 0)
|
||||
if (!feeDeductFromGold.value || cash <= 0) return undefined
|
||||
if (cash <= 0) return undefined
|
||||
if (inputLock === 'rial') return Math.round(cash)
|
||||
|
||||
const gold = Number(goldValue ?? 0)
|
||||
const unit = Number(unitPriceRial ?? 0)
|
||||
if (gold > 0 && unit > 0) {
|
||||
|
||||
+88
-14
@@ -1,24 +1,46 @@
|
||||
export function usePrice(price: number, digit = true, unit = 'ریال') {
|
||||
price= price??0
|
||||
let _price = price.toString()
|
||||
function formatGroupedPrice(price: string | number | null | undefined, digit: boolean) {
|
||||
let value = price === null || price === undefined ? '' : String(price)
|
||||
if (digit) {
|
||||
_price = _price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
value = value.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
}
|
||||
return `${_price} ${unit}`
|
||||
return value
|
||||
}
|
||||
|
||||
export function usePriceWithoutType(price?: number, digit = true, unit = 'ریال') {
|
||||
let _price = price?.toString()
|
||||
if (digit) {
|
||||
_price = _price?.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
/** مبلغ ریالی — بدون اعشار، گرد به بالا */
|
||||
export function ceilRial(price?: number | string | null): number {
|
||||
const num = Number(price ?? 0)
|
||||
if (!Number.isFinite(num)) {
|
||||
return 0
|
||||
}
|
||||
return `${_price}`
|
||||
|
||||
return Math.ceil(num)
|
||||
}
|
||||
|
||||
export function formatNumber(value: string | number | null | undefined, grouped = false): string {
|
||||
return formatGroupedPrice(value, grouped)
|
||||
}
|
||||
|
||||
export function usePrice(price: number, digit = true, unit = 'ریال') {
|
||||
const formatted = formatGroupedPrice(ceilRial(price), digit)
|
||||
return `${formatted} ${unit}`
|
||||
}
|
||||
|
||||
export function usePriceWithoutType(price?: number, digit = true) {
|
||||
return formatGroupedPrice(ceilRial(price), digit)
|
||||
}
|
||||
|
||||
export function useTowDecimal(num: string | number): string | number {
|
||||
const temp = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)
|
||||
if (temp && temp.length > 0) return temp[0]
|
||||
return Math.round(+num * 100) / 100
|
||||
if (temp && temp.length > 0) return formatGroupedPrice(temp[0], false)
|
||||
return formatGroupedPrice(Math.round(+num * 100) / 100, false)
|
||||
}
|
||||
|
||||
export function formatSignedPercentChange(value: number): string {
|
||||
if (!value) return '0%'
|
||||
|
||||
const formatted = useTowDecimal(Math.abs(value))
|
||||
const prefix = value > 0 ? '+' : '-'
|
||||
return `${prefix}${formatted}%`
|
||||
}
|
||||
|
||||
export function useFormat(num: string | number, unit = '') {
|
||||
@@ -28,11 +50,26 @@ export function useFormat(num: string | number, unit = '') {
|
||||
type TransactionPriceSource = {
|
||||
cash?: number | null
|
||||
gold?: number | null
|
||||
type?: number | null
|
||||
order?: {
|
||||
price?: number | null
|
||||
total_price?: number | null
|
||||
amount?: number | null
|
||||
sts?: number | null
|
||||
sts_str?: string | number | null
|
||||
payment_sts?: number | null
|
||||
} | null
|
||||
withdraw?: {
|
||||
sts?: number | null
|
||||
sts_str?: string | number | null
|
||||
} | null
|
||||
order_id?: number | null
|
||||
}
|
||||
|
||||
const ORDER_STATUS_LABELS: Record<number, string> = {
|
||||
1: 'باز',
|
||||
2: 'موفق',
|
||||
3: 'ناموفق',
|
||||
}
|
||||
|
||||
export function getTransactionTradePrice(item: TransactionPriceSource): number {
|
||||
@@ -57,6 +94,38 @@ export function getTransactionTradePrice(item: TransactionPriceSource): number {
|
||||
return 0
|
||||
}
|
||||
|
||||
export function resolveTransactionStatusLabel(item?: TransactionPriceSource | null): string {
|
||||
if (!item) return ''
|
||||
|
||||
const raw = item.order?.sts_str ?? item.withdraw?.sts_str
|
||||
if (typeof raw === 'string') {
|
||||
const trimmed = raw.trim()
|
||||
if (trimmed && trimmed !== 'بدون مقدار') {
|
||||
return trimmed
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof raw === 'number' || (typeof raw === 'string' && /^\d+$/.test(String(raw).trim()))) {
|
||||
const mapped = ORDER_STATUS_LABELS[Number(raw)]
|
||||
if (mapped) return mapped
|
||||
}
|
||||
|
||||
const sts = item.order?.sts ?? item.withdraw?.sts
|
||||
if (sts != null && ORDER_STATUS_LABELS[Number(sts)]) {
|
||||
return ORDER_STATUS_LABELS[Number(sts)]
|
||||
}
|
||||
|
||||
if (item.order_id && Number(item.order?.payment_sts) === 4) {
|
||||
return 'موفق'
|
||||
}
|
||||
|
||||
if (item.order_id && (item.type === 1 || item.type === 2 || item.type === 10)) {
|
||||
return 'موفق'
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
export function getTransactionGoldAmount(item: TransactionPriceSource): number {
|
||||
const gold = Number(item.gold) || 0
|
||||
if (Math.abs(gold) > 0) {
|
||||
@@ -74,8 +143,13 @@ export function getTransactionGoldAmount(item: TransactionPriceSource): number {
|
||||
return gold
|
||||
}
|
||||
|
||||
export function formatGoldAmount(amount?: number | null): string {
|
||||
export function formatGoldAmount(amount?: number | null, decimals = 8): string {
|
||||
const num = Number(amount)
|
||||
if (!Number.isFinite(num)) return '0'
|
||||
return String(Number(num.toFixed(3)))
|
||||
return formatGroupedPrice(Number(num.toFixed(decimals)), false)
|
||||
}
|
||||
|
||||
/** وزن فلز (گرم) — بدون گرد کردن به بالا */
|
||||
export function formatWeightAmount(amount?: number | null): string {
|
||||
return formatGoldAmount(amount)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user