feat: remove commission word and calculations from user app

This commit is contained in:
2026-11-07 12:24:36 +03:30
parent 0547b9ebaa
commit 187fda391f
9 changed files with 27 additions and 261 deletions
@@ -101,6 +101,8 @@ const breakdown = computed(() =>
payablePrice: props.payablePrice,
unitPriceRial: props.unitPriceRial,
sellGoldDebit: props.sellGoldDebit,
metalName: 'مس',
weightUnit: props.weightUnit || 'کیلوگرم',
}),
)
</script>
+21 -138
View File
@@ -33,53 +33,22 @@ export function formatTradeGramDisplay(grams?: number | null): number {
}
function feeRate() {
return normalizeServiceFeeRatio(Number(serviceFeePercentage.value))
return 0
}
/** نسبت کارمزد (۰٫۰۱ = ۱٪). مقدار ≥۱ یعنی درصد انسانی اشتباه وارد شده. */
/** نسبت کارمزد — در بورس مس کارمزد روی قیمت اعلامی لحاظ شده است و کارمزد جداگانه صفر است */
export function normalizeServiceFeeRatio(value: number): number {
if (!Number.isFinite(value) || value <= 0) {
return 0
}
if (value >= 1) {
return value / 100
}
return value
return 0
}
export async function loadServiceFeeFromSettings() {
try {
const settingsStore = useSettingsStore()
if (!settingsStore.loaded) {
await settingsStore.fetchSettings()
}
const settings = settingsStore.settings
if (settings?.length) {
const feeSetting = settings.find(
(s) => s?.key === 'fee_service_charge_percentage' && s?.is_active === true
)
if (feeSetting?.value !== undefined && feeSetting?.value !== null) {
const raw = String(feeSetting.value).trim()
serviceFeePercentage.value = raw === '' ? 0 : normalizeServiceFeeRatio(Number(raw))
}
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)
}
// در بورس مس کارمزد روی قیمت اعلامی لحاظ شده و کارمزد مجزا وجود ندارد
serviceFeePercentage.value = 0
feeDeductFromGold.value = false
}
export function calcFeeInGrams(goldValue?: number | null) {
return parseFloat(((goldValue ?? 0) * feeRate()).toFixed(4))
return 0
}
/** گرم معادل برای دریافت دقیق مبلغ ریالی در فروش */
@@ -253,7 +222,7 @@ export interface TradeConfirmBreakdown {
}
function hasTradeFee(feeInGrams: number, feeInRial: number) {
return feeInGrams > 0 || feeInRial > 0
return false
}
function grossGoldFromRial(rial: number, unitPriceRial: number) {
@@ -263,9 +232,7 @@ function grossGoldFromRial(rial: number, unitPriceRial: number) {
/**
* جزئیات مدال تأیید — دو بخش «کسر از کیف» و «واریز به کیف».
* فقط بر پایهٔ قفل ورودی تصمیم می‌گیرد:
* • ریال قفل → مبلغ دقیق، کارمزد از طلا.
* • گرم قفل → وزن دقیق، کارمزد از ریال.
* در بورس مس قیمت نهایی است و کارمزد مجزا وجود ندارد.
*/
export function buildTradeConfirmBreakdown(params: {
isBuy: boolean
@@ -276,126 +243,42 @@ export function buildTradeConfirmBreakdown(params: {
payablePrice: number
unitPriceRial: number
sellGoldDebit?: number
metalName?: string
weightUnit?: string
}): TradeConfirmBreakdown {
const {
isBuy,
inputLock,
orderGoldAmount,
feeInGrams,
feeInRial,
payablePrice,
unitPriceRial,
sellGoldDebit,
orderGoldAmount,
} = params
const hasFee = hasTradeFee(feeInGrams, feeInRial)
const rialLocked = isRialLocked(inputLock)
const metal = params.metalName ?? 'مس'
const unit = params.weightUnit ?? 'کیلوگرم'
const weight = orderGoldAmount
if (!isBuy) {
if (rialLocked) {
const debit = sellGoldDebit ?? parseFloat((weight + feeInGrams).toFixed(4))
const goldRows: TradeConfirmRow[] = hasFee
? [
{ label: 'وزن معادل مبلغ', gram: weight },
{ label: 'کارمزد', gram: feeInGrams, minus: true },
{ label: 'جمع کسر از کیف طلا', gram: debit, bold: true, dividerBefore: true },
]
: [{ label: 'وزن فروش', gram: weight, bold: true }]
return {
sections: [
{ heading: 'از کیف طلا کسر می‌شود', rows: goldRows },
{
heading: 'به کیف پول واریز می‌شود',
rows: [{ label: 'مبلغ دریافتی', rial: payablePrice, bold: true }],
footnote: hasFee
? 'دقیقاً همان مبلغی که وارد کردید واریز می‌شود؛ کارمزد فقط از طلای کیف کسر می‌شود.'
: undefined,
},
],
formHint: hasFee
? `${payablePrice.toLocaleString('fa-IR')} ریال دریافت — ${formatTradeGramDisplay(debit)} گرم از کیف کسر می‌شود (شامل ${formatTradeGramDisplay(feeInGrams)} گرم کارمزد)`
: `${payablePrice.toLocaleString('fa-IR')} ریال دریافت`,
}
}
const grossSellRial = Math.round(weight * unitPriceRial)
const cashRows: TradeConfirmRow[] = hasFee
? [
{ label: 'ارزش فروش', rial: grossSellRial },
{ label: 'کارمزد', rial: feeInRial, minus: true },
{ label: 'خالص دریافتی', rial: payablePrice, bold: true, dividerBefore: true },
]
: [{ label: 'مبلغ دریافتی', rial: payablePrice, bold: true }]
return {
sections: [
{ heading: 'از کیف طلا کسر می‌شود', rows: [{ label: 'وزن فروش', gram: weight, bold: true }] },
{ heading: `از کیف ${metal} کسر می‌شود`, rows: [{ label: 'وزن فروش', gram: weight, bold: true }] },
{
heading: 'به کیف پول واریز می‌شود',
rows: cashRows,
footnote: hasFee ? 'کارمزد از مبلغ ریالی دریافتی کم شده است.' : undefined,
rows: [{ label: 'مبلغ دریافتی', rial: payablePrice, bold: true }],
},
],
formHint: hasFee
? `${formatTradeGramDisplay(weight)} گرم فروش — ${feeInRial.toLocaleString('fa-IR')} ریال کارمزد از مبلغ دریافتی کسر می‌شود`
: `${formatTradeGramDisplay(weight)} گرم فروش — ${payablePrice.toLocaleString('fa-IR')} ریال به کیف پول`,
formHint: `${formatTradeGramDisplay(weight)} ${unit} فروش — ${payablePrice.toLocaleString('fa-IR')} ریال به کیف پول`,
}
}
if (rialLocked) {
const grossGram = grossGoldFromRial(payablePrice, unitPriceRial)
const feeGram = parseFloat(Math.max(0, grossGram - weight).toFixed(4))
const goldRows: TradeConfirmRow[] = hasFee
? [
{ label: 'معادل طلای خام', gram: grossGram },
{ label: 'کارمزد', gram: feeGram, minus: true },
{ label: 'خالص واریزی به کیف طلا', gram: weight, bold: true, dividerBefore: true },
]
: [{ label: 'واریزی به کیف طلا', gram: weight, bold: true }]
return {
sections: [
{
heading: 'از کیف پول کسر می‌شود',
rows: [{ label: 'مبلغ پرداختی', rial: payablePrice, bold: true }],
footnote: 'دقیقاً همان مبلغی که وارد کردید؛ کارمزد جداگانه اضافه نمی‌شود.',
},
{
heading: 'به کیف طلا واریز می‌شود',
rows: goldRows,
footnote: hasFee ? 'کارمزد از وزن طلای دریافتی کسر شده است.' : undefined,
},
],
formHint: hasFee
? `${payablePrice.toLocaleString('fa-IR')} ریال پرداخت — ${formatTradeGramDisplay(weight)} گرم واریز (کارمزد از طلا کسر شد)`
: `${payablePrice.toLocaleString('fa-IR')} ریال پرداخت`,
}
}
const basePriceRial = calcTradeBasePriceRial(weight, unitPriceRial)
const cashRows: TradeConfirmRow[] = hasFee
? [
{ label: `ارزش ${formatTradeGramDisplay(weight)} گرم`, rial: basePriceRial },
{ label: 'کارمزد', rial: feeInRial, plus: true },
{ label: 'جمع پرداختی', rial: payablePrice, bold: true, dividerBefore: true },
]
: [{ label: 'مبلغ پرداختی', rial: payablePrice, bold: true }]
return {
sections: [
{
heading: 'از کیف پول کسر می‌شود',
rows: cashRows,
footnote: hasFee ? 'کارمزد به مبلغ پرداختی اضافه شده است.' : undefined,
rows: [{ label: 'مبلغ پرداختی', rial: payablePrice, bold: true }],
},
{
heading: 'به کیف طلا واریز می‌شود',
rows: [{ label: 'دقیقاً', gram: weight, bold: true }],
heading: `به کیف ${metal} واریز می‌شود`,
rows: [{ label: 'مقدار واریزی', gram: weight, bold: true }],
},
],
formHint: hasFee
? `${payablePrice.toLocaleString('fa-IR')} ریال (شامل ${feeInRial.toLocaleString('fa-IR')} ریال کارمزد) — ${formatTradeGramDisplay(weight)} گرم واریز`
: `${payablePrice.toLocaleString('fa-IR')} ریال پرداخت`,
formHint: `${payablePrice.toLocaleString('fa-IR')} ریال پرداخت — ${formatTradeGramDisplay(weight)} ${unit} واریز`,
}
}
+1 -15
View File
@@ -124,23 +124,9 @@
<!-- <div>{{form?.goldValue? true: false}}</div>-->
<div v-if="isBuy? ((form?.goldValue || form.goldValue === 0)? form?.goldCash < 500000: false) : false"
class="text-red-700 text-xs font-bold mt-2">
حداقل مقدار طلا جهت خرید 500,000 ریال می باشد.
حداقل مقدار مس جهت خرید 500,000 ریال می باشد.
</div>
</a-form-item>
<div class=" w-full bottom-18 px-6 rounded-xl py-1 border-1 bg-white">
<!-- <BasicInfoItem is-line title="کارمزد" :value="parseFloat(((form.goldValue?? 0)*0.005).toFixed(3))" />-->
<!-- <BasicInfoItem is-line title="کارمزد" :value="parseFloat(((form.goldValue?? 0)*0.005).toFixed(3))" />-->
<div class="flex justify-between items-center">
<div>کارمزد:</div>
<div class="flex gap-2 items-center">
<div class="">{{ feeInGrams }}</div>
<!-- <div class="font-bold text-2xl">{{ 0 }}</div>-->
<div>
گرم
</div>
</div>
</div>
</div>
</a-form>
<!-- <div ref="el" :class="loading? 'h-screen': ''"
class="px-3 overflow-y-scroll w-full h-[49vh] pb-25 max-h-[35vh]">
@@ -44,8 +44,8 @@
شیوهٔ خرید از گروسی گالری
</div>
<div :class="variant === 'desktop' ? 'deducate-content__text' : 'mt-5 text-xs leading-5'">
• سپس از بخش «خرید و فروش» انتخاب کنید که طلای آب‌شده می‌خواهید یا محصولات دیگر (شامل گوی، شمش یا مکعب).<br />
• توجه داشته باشید کارمزد طلای آب‌شده حدود ۲٪ است و کارمزد ریالی محصولات دیگر در پایین صفحه قیمت درج شده است.
• سپس از بخش «خرید و فروش» محصول مورد نظر خود (شامل کاتد مس، مفتول مس یا سیم) را انتخاب کنید.<br />
• قیمت‌های اعلام‌شده نهایی بوده و هیچ‌گونه کارمزد جداگانه‌ای از مشتری دریافت نمی‌شود.
</div>
<img :src="img4" :class="variant === 'desktop' ? 'deducate-content__image' : ''" />
-12
View File
@@ -141,7 +141,6 @@
class="text-red-700 text-xs font-bold mt-2">
مقدار {{ weightUnit }} وارد شده جهت فروش ({{ form.goldValue }}{{ weightUnit }}) بیشتر از مقدار موجودی شما
({{ productWalletBalance }}{{ weightUnit }}) می باشد.
<span v-if="feeDeductFromGold"> (با احتساب {{ feeInGrams }}{{ weightUnit }} کارمزد، مجموعاً {{ sellGoldDebit }}{{ weightUnit }} کسر می‌شود)</span>
</div>
<!-- <div>{{form?.goldValue? true: false}}</div>-->
<div v-if="isBuy ? (payablePrice > cashWalletBalance) : false"
@@ -149,17 +148,6 @@
موجودی کیف پول ناکافی می باشد.
</div>
</a-form-item>
<div class="w-full px-4 rounded-2xl py-2 border-1 bg-white gold-fee-box">
<div class="flex justify-between items-center">
<div>کارمزد:</div>
<div class="flex gap-2 items-center">
<div class="">{{ feeInGrams }}</div>
<div>
{{ weightUnit }}
</div>
</div>
</div>
</div>
</a-form>
<!-- <div ref="el" :class="loading? 'h-screen': ''"
class="px-3 overflow-y-scroll w-full h-[49vh] pb-25 max-h-[35vh]">
@@ -54,7 +54,7 @@
</div>
<p :class="desktop ? 'dgift-form__hint' : 'text-xs text-gray-500 mb-2'">
خرید با {{ feeShop }}٪ کارمزد ({{ feeGateway }}٪ دیجی‌پی + {{ feeExtra }}٪) محاسبه می‌شود.
خرید اقساطی با {{ feeShop }}٪ افزایش ({{ feeGateway }}٪ دیجی‌پی + {{ feeExtra }}٪) محاسبه می‌شود.
</p>
<BasicInput
v-model:value="amountText"
@@ -159,38 +159,7 @@
<div v-else>{{ !isBuy ? 'فروش' : 'خرید' }}</div>
</div>
</BasicButton>
<!-- <div class=" w-full !z-100 px-6 rounded-xl py-1 border-1 bg-white mt-2">
&lt;!&ndash; <BasicInfoItem is-line title="کارمزد" :value="parseFloat(((form.goldValue?? 0)*0.005).toFixed(3))" />&ndash;&gt;
&lt;!&ndash; <BasicInfoItem is-line title="کارمزد" :value="parseFloat(((form.goldValue?? 0)*0.005).toFixed(3))" />&ndash;&gt;
<div class="flex justify-between items-center">
<div>کارمزد:</div>
<div class="flex gap-2 items-center">
&lt;!&ndash; <div class="line-through">{{ parseFloat(((form.goldValue ?? 0) * 0.005).toFixed(3)) }}</div>&ndash;&gt;
&lt;!&ndash; <div>{{props.ProductItem.price}}</div>&ndash;&gt;
<div v-if="isBuy && form.method=='cash' " class="">{{
usePriceWithoutType(buyFee ?? 0)
}}
</div>
<div v-if="isBuy && form.method!='cash'" class="">{{
buyFeeGeram ?? 0
}}
</div>
<div v-if="!isBuy && form.method=='cash' " class="">{{
usePriceWithoutType(sellFee ?? 0)
}}
</div>
<div v-if="!isBuy && form.method!='cash'" class="">{{
sellFeeGeram ?? 0
}}
</div>
<div>
{{ form.method == "cash" ? "ریال" : "گرم" }}
</div>
</div>
</div>
</div>-->
<!-- <div v-if="!isBuy && form.goldValue > walletStore?.walletInfo?.gold"
class="text-red-700 text-xs font-bold mt-2">
مقدار گرم طلای وارد شده جهت فروش ({{ form.goldValue }}گرم) بیشتر از مقدار موجودی شما
@@ -238,21 +207,7 @@
</div>
</div>
<div class="flex justify-between mt-3">
<div>کارمزد:</div>
<div class="flex items-center gap-2">
<div v-if="isBuy" class="">{{
buyFee
}}
</div>
<div v-else class="">{{
sellFee
}}
</div>
<div class="text-xs mr-1">ریال</div>
</div>
</div>
<div class="flex justify-between mt-3">
<div>{{ isBuy ? 'قیمت قابل پرداخت:' : (isMetalReceiveDeal ? 'دریافت:' : 'مبلغ دریافتی:') }}</div>
@@ -118,38 +118,7 @@
<div v-else>{{ !isBuy ? 'فروش' : 'خرید' }}</div>
</div>
</BasicButton>
<!-- <div class=" w-full !z-100 px-6 rounded-xl py-1 border-1 bg-white mt-2">
&lt;!&ndash; <BasicInfoItem is-line title="کارمزد" :value="parseFloat(((form.goldValue?? 0)*0.005).toFixed(3))" />&ndash;&gt;
&lt;!&ndash; <BasicInfoItem is-line title="کارمزد" :value="parseFloat(((form.goldValue?? 0)*0.005).toFixed(3))" />&ndash;&gt;
<div class="flex justify-between items-center">
<div>کارمزد:</div>
<div class="flex gap-2 items-center">
&lt;!&ndash; <div class="line-through">{{ parseFloat(((form.goldValue ?? 0) * 0.005).toFixed(3)) }}</div>&ndash;&gt;
&lt;!&ndash; <div>{{props.ProductItem.price}}</div>&ndash;&gt;
<div v-if="isBuy && form.method=='cash' " class="">{{
usePriceWithoutType(buyFee ?? 0)
}}
</div>
<div v-if="isBuy && form.method!='cash'" class="">{{
buyFeeGeram ?? 0
}}
</div>
<div v-if="!isBuy && form.method=='cash' " class="">{{
usePriceWithoutType(sellFee ?? 0)
}}
</div>
<div v-if="!isBuy && form.method!='cash'" class="">{{
sellFeeGeram ?? 0
}}
</div>
<div>
{{ form.method == "cash" ? "ریال" : "گرم" }}
</div>
</div>
</div>
</div>-->
<!-- <div v-if="!isBuy && form.goldValue > walletStore?.walletInfo?.gold"
class="text-red-700 text-xs font-bold mt-2">
مقدار گرم طلای وارد شده جهت فروش ({{ form.goldValue }}گرم) بیشتر از مقدار موجودی شما
@@ -196,22 +165,7 @@
<div class="text-xs mr-1">ریال</div>
</div>
</div>
<div class="flex justify-between mt-3">
<div>کارمزد:</div>
<div class="flex items-center gap-2">
<div v-if="isBuy" class="">{{
buyFee
}}
</div>
<!-- <div class="font-bold line-through">{{ 0 }}</div>-->
<div v-else class="">{{
sellFee
}}
</div>
<div class="text-xs mr-1">ریال</div>
</div>
</div>
<div class="flex justify-between mt-3">
<div>{{ isBuy ? 'قیمت قابل پرداخت:' : 'مبلغ دریافتی:' }}</div>
<div class="flex items-center">
-2
View File
@@ -33,7 +33,6 @@ function getDefaultRulesItems(nameProject: string): string[] {
`در صورت واریز اشتباه وجه، ${brand} مجاز است نسبت به رفع اشتباه و برداشت از حساب اقدام کند و کاربر حق اعتراض را از خود ساقط می‌داند.`,
`در صورت ابهام در معاملات، ${brand} حق ابطال معامله و عودت دارایی‌ها را دارد. در صورت اشکال از سمت ${brand}، جبران خسارت انجام می‌شود.`,
`در صورت فوت یا حجر کاربر، ${brand} پیرو قوانین جمهوری اسلامی ایران است.`,
`هزینه خدمات و کارمزد مطابق راهنمای استفاده از ${brand} محاسبه می‌شود.`,
`کلیه حقوق مادی و معنوی ${brand} محفوظ است و استفاده بدون رضایت مجاز نیست.`,
`ابطال هر بند، بر سایر بندها اثر ندارد.`,
]
@@ -79,7 +78,6 @@ function getBoursecuRulesBlocks(nameProject: string): RulesBlock[] {
`کاربران متعهدند از ${brand} برای معاملات صوری، دستکاری قیمت، تبانی، پولشویی یا فعالیت غیرقانونی استفاده نکنند.`,
`در صورت اختلاف در معامله، ${brand} حق ابطال معامله و بازگرداندن دارایی طرفین را دارد. اگر خطا از سمت ${brand} باشد، جبران خسارت انجام می‌شود.`,
`در صورت فوت یا حجر کاربر، ${brand} تابع قوانین جمهوری اسلامی ایران خواهد بود.`,
`کارمزد و هزینه خدمات مطابق راهنمای ${brand} محاسبه می‌شود.`,
`تمامی حقوق مادی و معنوی ${brand} محفوظ است.`,
`ابطال هر بند، اعتبار سایر بندها را مخدوش نمی‌کند.`,
],