fix some bugs

This commit is contained in:
2026-07-01 22:28:25 +03:30
parent 2feeefc26f
commit e097f6b2bb
24 changed files with 579 additions and 189 deletions
+57 -5
View File
@@ -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 بک‌اند */
+80
View File
@@ -3,6 +3,9 @@ import { getSettings } from '@/api/configuration'
export const serviceFeePercentage = ref<number>(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
}