665 lines
19 KiB
TypeScript
665 lines
19 KiB
TypeScript
import type { SelectItem } from '@/models/SelectItem'
|
|
import type { Product } from '@/models/products'
|
|
import type { WalletInventoryCard } from '@/models/walletAssets'
|
|
import { isBoursecuProject } from '@/utils/config'
|
|
import { useSettingsStore } from '@/store/settingsStore'
|
|
import {
|
|
isLegacyMaftolGroup,
|
|
isMeltedTradeGroup,
|
|
LEGACY_GROUP_KATOD,
|
|
LEGACY_GROUP_MAFTOL,
|
|
normalizeProductGroupType,
|
|
PRODUCT_CATEGORY_ABSHODE,
|
|
usesQuantityTrade,
|
|
} from '@/utils/productCategories'
|
|
import { formatInventoryCardValue } from '@/utils/productAssets'
|
|
|
|
/** @deprecated از isMeltedTradeGroup استفاده کنید */
|
|
export const BOURSECU_GROUP_ABSHODE = PRODUCT_CATEGORY_ABSHODE
|
|
export const BOURSECU_GROUP_KATOD = LEGACY_GROUP_KATOD
|
|
export const BOURSECU_GROUP_MAFTOL = LEGACY_GROUP_MAFTOL
|
|
|
|
export const BOURSECU_WALLET_LABEL_GENERIC = 'موجودی کیف'
|
|
|
|
export function isBoursecuDealProductGroup(groupType?: string | null) {
|
|
if (!isBoursecuProject()) {
|
|
return false
|
|
}
|
|
|
|
const group = normalizeProductGroupType(groupType)
|
|
return group === BOURSECU_GROUP_MAFTOL
|
|
|| group === BOURSECU_GROUP_KATOD
|
|
|| group === BOURSECU_GROUP_ABSHODE
|
|
|| group === 'مس'
|
|
}
|
|
|
|
export function isMaftolMesGroup(groupType?: string | null) {
|
|
const group = normalizeProductGroupType(groupType)
|
|
return group === BOURSECU_GROUP_MAFTOL || (isBoursecuProject() && group === 'مس')
|
|
}
|
|
|
|
export function isKatodMesGroup(groupType?: string | null) {
|
|
return normalizeProductGroupType(groupType) === BOURSECU_GROUP_KATOD
|
|
}
|
|
|
|
export function isShamshMesGroup(groupType?: string | null, title?: string | null) {
|
|
if (!isBoursecuProject()) {
|
|
return false
|
|
}
|
|
|
|
const group = normalizeProductGroupType(groupType)
|
|
if (group === 'شمش') {
|
|
return true
|
|
}
|
|
|
|
return (title ?? '').includes('شمش')
|
|
}
|
|
|
|
export function isGoldOnlyDealGroup(groupType?: string | null) {
|
|
return isMeltedTradeGroup(groupType)
|
|
}
|
|
|
|
export interface ProductUnitSource {
|
|
unit?: string | null
|
|
direct_price?: number | null
|
|
group_type?: string | null
|
|
amount?: number | null
|
|
trade_by_quantity?: boolean | number | null
|
|
}
|
|
|
|
export function isWeightBasedProductUnit(unit?: string | null) {
|
|
const value = (unit ?? '').trim()
|
|
return value === 'کیلوگرم' || value === 'گرم'
|
|
}
|
|
|
|
const COUNT_BASED_GROUP_TYPES = ['سکه', 'گوی', 'مکعب', 'شمش', 'سکه پارسیان']
|
|
|
|
/** مطابق ادمین: وزن «دارد» => amount > 0 ؛ «ندارد» => amount = 0 */
|
|
export function hasProductUnitWeight(product?: ProductUnitSource | null) {
|
|
if (isMeltedTradeGroup(product?.group_type)) {
|
|
return false
|
|
}
|
|
|
|
const amount = Number(product?.amount ?? 0)
|
|
return amount > 0
|
|
}
|
|
|
|
/** ضریب قیمت — فقط «متغیر» بدون مرجع اتوماتیک: قیمت هر گرم × وزن */
|
|
export function productPriceAmountFactor(product?: ProductUnitSource | null) {
|
|
if (product?.reading_method) {
|
|
return 1
|
|
}
|
|
|
|
if (isCountBasedProduct(product)) {
|
|
return 1
|
|
}
|
|
|
|
if (Number(product?.direct_price ?? 0) !== 0) {
|
|
return 1
|
|
}
|
|
|
|
if (hasProductUnitWeight(product)) {
|
|
const amount = Number(product?.amount ?? 0)
|
|
return amount > 0 ? amount : 1
|
|
}
|
|
|
|
return 1
|
|
}
|
|
|
|
export function getProductWeightUnit(product?: ProductUnitSource | null) {
|
|
const unit = product?.unit?.trim()
|
|
if (unit && isWeightBasedProductUnit(unit)) {
|
|
return unit
|
|
}
|
|
|
|
if (isBoursecuProject()) {
|
|
const group = normalizeProductGroupType(product?.group_type)
|
|
if (group === BOURSECU_GROUP_MAFTOL || group === BOURSECU_GROUP_KATOD || group === BOURSECU_GROUP_ABSHODE || group === 'مس' || isMeltedTradeGroup(group)) {
|
|
return getWeightUnit()
|
|
}
|
|
}
|
|
|
|
if (!isCountBasedProduct(product) || isMeltedTradeGroup(product?.group_type)) {
|
|
return getWeightUnit()
|
|
}
|
|
|
|
return 'گرم'
|
|
}
|
|
|
|
export function formatProductWeightAmount(amount?: number | null, product?: ProductUnitSource | null) {
|
|
const value = Number(amount ?? 0)
|
|
const weightUnit = getProductWeightUnit(product)
|
|
|
|
if (weightUnit === 'گرم' && value > 0 && value < 1) {
|
|
return `${value * 1000} سوت`
|
|
}
|
|
|
|
return `${value} ${weightUnit}`
|
|
}
|
|
|
|
/** فقط محصول تعدادی (مثل سکه): «هر عدد X گرم» — معامله مقداری با trade_by_quantity نیست */
|
|
export function shouldShowPerUnitWeightHint(product?: ProductUnitSource | null) {
|
|
if (!product || !hasProductUnitWeight(product) || usesQuantityTrade(product)) {
|
|
return false
|
|
}
|
|
|
|
return isCountBasedProduct(product)
|
|
}
|
|
|
|
export function getProductUnitWeightLabel(product?: ProductUnitSource | null) {
|
|
if (!shouldShowPerUnitWeightHint(product)) {
|
|
return null
|
|
}
|
|
|
|
return formatProductWeightAmount(product?.amount, product)
|
|
}
|
|
|
|
export function getProductTotalWeightLabel(count?: number | null, product?: ProductUnitSource | null) {
|
|
if (!hasProductUnitWeight(product)) {
|
|
return null
|
|
}
|
|
|
|
const quantity = Number(count ?? 0)
|
|
return formatProductWeightAmount(quantity * Number(product?.amount ?? 0), product)
|
|
}
|
|
|
|
export function shouldShowProductTotalWeight(product?: ProductUnitSource | null) {
|
|
if (!product) {
|
|
return false
|
|
}
|
|
|
|
if (!isCountBasedProduct(product)) {
|
|
return true
|
|
}
|
|
|
|
return hasProductUnitWeight(product)
|
|
}
|
|
|
|
export function formatProductInventoryBalance(product?: (ProductUnitSource & { wallet?: { gold?: number | null } }) | null) {
|
|
const count = product?.wallet?.gold ?? 0
|
|
const quantityPart = `${count} ${getProductQuantityUnit(product)}`
|
|
const unitWeight = getProductUnitWeightLabel(product)
|
|
|
|
if (!unitWeight) {
|
|
return quantityPart
|
|
}
|
|
|
|
return `${quantityPart} · هر عدد ${unitWeight}`
|
|
}
|
|
|
|
/** محصول تعدادی: موجودی wallet.gold = تعداد قلم، نه وزن — معامله مقداری با trade_by_quantity نیست */
|
|
export function isCountBasedProduct(product?: ProductUnitSource | null) {
|
|
if (!product) {
|
|
return false
|
|
}
|
|
|
|
if (usesQuantityTrade(product)) {
|
|
return false
|
|
}
|
|
|
|
if (isWeightBasedProductUnit(product.unit)) {
|
|
return false
|
|
}
|
|
|
|
if (product.direct_price != null && product.direct_price !== 0) {
|
|
return true
|
|
}
|
|
|
|
const group = normalizeProductGroupType(product.group_type)
|
|
if (group === BOURSECU_GROUP_MAFTOL || isLegacyMaftolGroup(group) || (isBoursecuProject() && group === 'مس')) {
|
|
return true
|
|
}
|
|
|
|
return COUNT_BASED_GROUP_TYPES.includes(group)
|
|
}
|
|
|
|
export function getProductQuantityUnit(product?: ProductUnitSource | null) {
|
|
const unit = product?.unit?.trim()
|
|
if (unit) {
|
|
return unit
|
|
}
|
|
|
|
if (isCountBasedProduct(product)) {
|
|
return 'عدد'
|
|
}
|
|
|
|
return getWeightUnit()
|
|
}
|
|
|
|
export const MELTED_DEAL_METHOD_PREFIX = 'gold:'
|
|
|
|
export interface ProductDealMethodContext {
|
|
tradedProduct?: Product | null
|
|
productMetalId?: number | null
|
|
inventoryCards?: WalletInventoryCard[]
|
|
catalog?: Product[]
|
|
}
|
|
|
|
/** سلکت نحوه معامله فقط وقتی محصول مورد معامله وزن دارد */
|
|
export function shouldShowProductDealMethodSelector(product?: Product | null) {
|
|
return hasProductUnitWeight(product)
|
|
}
|
|
|
|
export function shouldShowProductDealMethodSelect(
|
|
product?: Product | null,
|
|
options?: SelectItem[] | null,
|
|
) {
|
|
return shouldShowProductDealMethodSelector(product) && (options?.length ?? 0) > 1
|
|
}
|
|
|
|
export function buildMeltedDealMethodKey(productId: number) {
|
|
return `${MELTED_DEAL_METHOD_PREFIX}${productId}`
|
|
}
|
|
|
|
export function parseMeltedDealMethodProductId(method?: string | null): number | null {
|
|
if (!method?.startsWith(MELTED_DEAL_METHOD_PREFIX)) {
|
|
return null
|
|
}
|
|
|
|
const productId = Number(method.slice(MELTED_DEAL_METHOD_PREFIX.length))
|
|
return productId > 0 ? productId : null
|
|
}
|
|
|
|
export function isMeltedProductDealMethod(method?: string | null) {
|
|
return parseMeltedDealMethodProductId(method) != null
|
|
}
|
|
|
|
function isQuantityTradeCatalogProduct(
|
|
product?: Product | null,
|
|
metalId?: number | null,
|
|
excludeProductId?: number | null,
|
|
) {
|
|
if (!product || !usesQuantityTrade(product)) {
|
|
return false
|
|
}
|
|
|
|
if (excludeProductId && Number(product.id) === Number(excludeProductId)) {
|
|
return false
|
|
}
|
|
|
|
return Number(product.metal_id) === Number(metalId ?? 0)
|
|
}
|
|
|
|
function findInventoryCardForProduct(
|
|
cards: WalletInventoryCard[],
|
|
productId?: number | null,
|
|
) {
|
|
if (!productId) {
|
|
return undefined
|
|
}
|
|
|
|
return cards.find((card) => Number(card.product_id) === Number(productId))
|
|
}
|
|
|
|
export function getQuantityTradePaymentDealOptions(
|
|
context?: ProductDealMethodContext | null,
|
|
isBuy = true,
|
|
): SelectItem[] {
|
|
const metalId = Number(context?.productMetalId ?? 0)
|
|
const catalog = context?.catalog ?? []
|
|
const cards = context?.inventoryCards ?? []
|
|
const tradedProductId = context?.tradedProduct?.id ?? null
|
|
|
|
if (!metalId || !catalog.length) {
|
|
return []
|
|
}
|
|
|
|
const matchingProducts = catalog.filter((product) =>
|
|
isQuantityTradeCatalogProduct(product, metalId, tradedProductId)
|
|
)
|
|
|
|
if (isBuy) {
|
|
const options: SelectItem[] = []
|
|
|
|
for (const product of matchingProducts) {
|
|
const card = findInventoryCardForProduct(cards, product.id)
|
|
if (!card || Number(card.quantity ?? 0) <= 0) {
|
|
continue
|
|
}
|
|
|
|
options.push({
|
|
key: buildMeltedDealMethodKey(product.id),
|
|
value: `${product.title} — ${formatInventoryCardValue(card)}`,
|
|
})
|
|
}
|
|
|
|
return options
|
|
}
|
|
|
|
return matchingProducts.map((product) => {
|
|
const card = findInventoryCardForProduct(cards, product.id)
|
|
const inventorySuffix = card ? ` — ${formatInventoryCardValue(card)}` : ''
|
|
|
|
return {
|
|
key: buildMeltedDealMethodKey(product.id),
|
|
value: `دریافت ${product.title}${inventorySuffix}`,
|
|
}
|
|
})
|
|
}
|
|
|
|
/** @deprecated از getQuantityTradePaymentDealOptions استفاده کنید */
|
|
export function getMeltedPaymentDealOptions(
|
|
context?: ProductDealMethodContext | null,
|
|
isBuy = true,
|
|
) {
|
|
return getQuantityTradePaymentDealOptions(context, isBuy)
|
|
}
|
|
|
|
export function findMeltedDealMethodCard(
|
|
method?: string | null,
|
|
cards: WalletInventoryCard[] = [],
|
|
) {
|
|
return findInventoryCardForProduct(cards, parseMeltedDealMethodProductId(method))
|
|
}
|
|
|
|
export function findProductDealMethodProduct(
|
|
method?: string | null,
|
|
catalog: Product[] = [],
|
|
) {
|
|
const productId = parseMeltedDealMethodProductId(method)
|
|
if (!productId) {
|
|
return null
|
|
}
|
|
|
|
return catalog.find((product) => Number(product.id) === productId) ?? null
|
|
}
|
|
|
|
export function resolveProductTradeBuyUnitPrice(product?: Product | null) {
|
|
if (!product) {
|
|
return 0
|
|
}
|
|
|
|
const basePrice = (product.price ?? 0) + (product.cash_fee_buy ?? 0)
|
|
return basePrice * productPriceAmountFactor(product)
|
|
}
|
|
|
|
export function resolveProductTradeSellUnitPrice(product?: Product | null) {
|
|
if (!product) {
|
|
return 0
|
|
}
|
|
|
|
const basePrice = (product.price ?? 0) - (product.cash_fee_sell ?? 0)
|
|
return basePrice * productPriceAmountFactor(product)
|
|
}
|
|
|
|
function getDefaultTypeDealOptions(context?: ProductDealMethodContext | null, isBuy = true): SelectItem[] {
|
|
const cashOption: SelectItem = { value: 'نقدی', key: 'cash' }
|
|
|
|
if (!shouldShowProductDealMethodSelector(context?.tradedProduct ?? null)) {
|
|
return [cashOption]
|
|
}
|
|
|
|
const quantityOptions = getQuantityTradePaymentDealOptions(context, isBuy)
|
|
if (quantityOptions.length) {
|
|
return [cashOption, ...quantityOptions]
|
|
}
|
|
|
|
return [cashOption]
|
|
}
|
|
|
|
export function getProductDealMethodOptions(
|
|
groupType?: string | null,
|
|
isBuy = true,
|
|
context?: ProductDealMethodContext | null,
|
|
): SelectItem[] {
|
|
const settingsStore = useSettingsStore()
|
|
|
|
if (!isBoursecuProject()) {
|
|
return getDefaultTypeDealOptions(context, isBuy)
|
|
}
|
|
|
|
if (isMaftolMesGroup(groupType)) {
|
|
if (isBuy) {
|
|
return [
|
|
{ value: `پرداخت با ${settingsStore.metalTypeLabel}`, key: 'katod' },
|
|
{ value: 'نقدی', key: 'cash' },
|
|
]
|
|
}
|
|
|
|
return [
|
|
{ value: 'نقدی', key: 'cash' },
|
|
{ value: `دریافت ${settingsStore.metalTypeLabel}`, key: 'katod' },
|
|
]
|
|
}
|
|
|
|
if (isKatodMesGroup(groupType)) {
|
|
return [{ value: 'نقدی', key: 'cash' }]
|
|
}
|
|
|
|
if (isMeltedTradeGroup(groupType)) {
|
|
return [{ value: settingsStore.meltedGoldLabel, key: 'gold' }]
|
|
}
|
|
|
|
return getDefaultTypeDealOptions(context, isBuy)
|
|
}
|
|
|
|
export function getDefaultProductDealMethod(
|
|
groupType?: string | null,
|
|
isBuy = true,
|
|
context?: ProductDealMethodContext | null,
|
|
) {
|
|
return getProductDealMethodOptions(groupType, isBuy, context)[0]?.key ?? 'cash'
|
|
}
|
|
|
|
export function getProductDealMethodPlaceholder(isBuy = true) {
|
|
return isBuy ? 'نحوه خرید را انتخاب کنید' : 'نحوه دریافت را انتخاب کنید'
|
|
}
|
|
|
|
export function formatMainMetalReceiveText(weight?: number | null) {
|
|
return `${useSettingsStore().metalTypeLabel}: ${weight ?? 0}${getWeightUnit()}`
|
|
}
|
|
|
|
export function calcSellReceivedMetalWeight(
|
|
count?: number | null,
|
|
product?: ProductUnitSource & { percent_fee_sell?: number | null } | null,
|
|
) {
|
|
const quantity = Number(count ?? 0)
|
|
const unitAmount = Number(product?.amount ?? 0)
|
|
if (!quantity || !unitAmount) {
|
|
return 0
|
|
}
|
|
|
|
const grossAmount = quantity * unitAmount
|
|
const feeRate = Number(product?.percent_fee_sell ?? 0)
|
|
return grossAmount - feeRate * grossAmount
|
|
}
|
|
|
|
export function isCashLikeDealMethod(method?: string | null) {
|
|
return method === 'cash'
|
|
}
|
|
|
|
export function isMainMetalWalletDealMethod(method?: string | null) {
|
|
return method === 'gold' || method === 'katod' || isMeltedProductDealMethod(method)
|
|
}
|
|
|
|
export function getMeltedDealMethodBalance(
|
|
method?: string | null,
|
|
cards: WalletInventoryCard[] = [],
|
|
mainWalletGold?: number | null,
|
|
) {
|
|
const card = findMeltedDealMethodCard(method, cards)
|
|
if (card) {
|
|
return Number(card.quantity ?? 0)
|
|
}
|
|
|
|
if (method === 'gold' || method === 'katod') {
|
|
return Number(mainWalletGold ?? 0)
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
/** برچسب کیف فلز اصلی (main wallet gold) — از setting metal_type */
|
|
export function getMainMetalWalletLabel() {
|
|
return `موجودی کیف ${useSettingsStore().metalTypeLabel}`
|
|
}
|
|
|
|
/** برچسب کیف آبشده — از setting metal_type */
|
|
export function getMeltedGoldWalletLabel() {
|
|
return `موجودی کیف ${useSettingsStore().meltedGoldLabel}`
|
|
}
|
|
|
|
export function getBoursecuMetalWalletLabel(groupType?: string | null) {
|
|
const group = normalizeProductGroupType(groupType)
|
|
if (group === BOURSECU_GROUP_MAFTOL) {
|
|
return BOURSECU_GROUP_MAFTOL
|
|
}
|
|
if (group === BOURSECU_GROUP_KATOD) {
|
|
return BOURSECU_GROUP_KATOD
|
|
}
|
|
if (group === BOURSECU_GROUP_ABSHODE) {
|
|
return useSettingsStore().meltedGoldLabel
|
|
}
|
|
|
|
return useSettingsStore().metalTypeLabel
|
|
}
|
|
|
|
export function getGoldWalletLabel(groupType?: string | null) {
|
|
if (!isBoursecuProject()) {
|
|
return getMainMetalWalletLabel()
|
|
}
|
|
|
|
const group = normalizeProductGroupType(groupType)
|
|
if (group === BOURSECU_GROUP_MAFTOL
|
|
|| group === BOURSECU_GROUP_KATOD
|
|
|| group === BOURSECU_GROUP_ABSHODE) {
|
|
return `موجودی کیف ${getBoursecuMetalWalletLabel(groupType)}`
|
|
}
|
|
|
|
if (!group) {
|
|
return getMainMetalWalletLabel()
|
|
}
|
|
|
|
return BOURSECU_WALLET_LABEL_GENERIC
|
|
}
|
|
|
|
/** پرداخت نقدی همیشه از کیف پول ریالی — مستقل از نوع محصول */
|
|
export function getCashWalletLabel(_groupType?: string | null) {
|
|
return 'موجودی کیف پول'
|
|
}
|
|
|
|
export function getMetalAssetLabel() {
|
|
return `دارایی ${useSettingsStore().metalTypeLabel}`
|
|
}
|
|
|
|
export function getMeltedGoldAssetLabel() {
|
|
return `دارایی ${useSettingsStore().meltedGoldLabel}`
|
|
}
|
|
|
|
export function getMaftolAssetLabel() {
|
|
return `دارایی ${BOURSECU_GROUP_MAFTOL}`
|
|
}
|
|
|
|
export function getWeightUnit() {
|
|
return useSettingsStore().tradeWeightUnit
|
|
}
|
|
|
|
export function formatBoursecuAssetAmount(amount?: number | null) {
|
|
return `${amount ?? 0}${getWeightUnit()}`
|
|
}
|
|
|
|
export function formatMainMetalWalletBalanceText(gold: number) {
|
|
return `${getMainMetalWalletLabel()}: ${gold} ${getWeightUnit()}`
|
|
}
|
|
|
|
export function formatGoldWalletBalanceText(gold: number, groupType?: string | null) {
|
|
return `${getGoldWalletLabel(groupType)}: ${gold} ${getWeightUnit()}`
|
|
}
|
|
|
|
export function formatCashWalletBalanceText(cashFormatted: string | number, groupType?: string | null) {
|
|
return `${getCashWalletLabel(groupType)}: ${cashFormatted} ریال`
|
|
}
|
|
|
|
/** برچسب کیف فلزی متناسب با نحوه پرداخت (مثلاً کاتد مس برای خرید مفتول با کیف کاتد) */
|
|
export function getMetalWalletLabelForDealMethod(method?: string | null, groupType?: string | null) {
|
|
if (!isBoursecuProject() || method === 'katod') {
|
|
return getMainMetalWalletLabel()
|
|
}
|
|
|
|
return getGoldWalletLabel(groupType)
|
|
}
|
|
|
|
export function getInsufficientGoldWalletMessage(groupType?: string | null, method?: string | null) {
|
|
return `${getMetalWalletLabelForDealMethod(method, groupType)} ناکافی است`
|
|
}
|
|
|
|
export function getInsufficientCashWalletMessage(_groupType?: string | null) {
|
|
return `${getCashWalletLabel()} ناکافی است`
|
|
}
|
|
|
|
export function getInsufficientMainMetalWalletMessage() {
|
|
return `${getMainMetalWalletLabel()} ناکافی است`
|
|
}
|
|
|
|
export function getMeltedGoldTradeLabel() {
|
|
return useSettingsStore().meltedGoldLabel
|
|
}
|
|
|
|
export function getMetalTypeTradeLabel() {
|
|
return useSettingsStore().metalTypeLabel
|
|
}
|
|
|
|
export function getTradePriceUnitLabel() {
|
|
return useSettingsStore().metalTypeLabel
|
|
}
|
|
|
|
export type TransactionTradeProductSource = {
|
|
product?: (ProductUnitSource & { title?: string | null }) | null
|
|
wallet?: { product?: (ProductUnitSource & { title?: string | null }) | null } | null
|
|
title?: string | null
|
|
}
|
|
|
|
/** محصول معاملهشده — نه لزوماً همان کیف پول (مثلاً خرید مفتول با کیف کاتد) */
|
|
export function resolveTransactionTradeProduct(
|
|
item?: TransactionTradeProductSource | null,
|
|
): (ProductUnitSource & { title?: string | null }) | null {
|
|
if (!item) {
|
|
return null
|
|
}
|
|
|
|
const fromTransaction = item.product
|
|
if ((fromTransaction?.title ?? '').trim()) {
|
|
return fromTransaction ?? null
|
|
}
|
|
|
|
const title = (item.title ?? '').trim()
|
|
const match = title.match(/^(?:خرید|فروش)\s+(.+)$/u)
|
|
if (match?.[1]?.trim()) {
|
|
return {
|
|
...(item.wallet?.product ?? {}),
|
|
title: match[1].trim(),
|
|
}
|
|
}
|
|
|
|
return item.wallet?.product ?? null
|
|
}
|
|
|
|
/** برچسب قیمت حین معامله — نام و واحد همان محصول معاملهشده */
|
|
export function getTransactionTradePriceLabel(product?: (ProductUnitSource & { title?: string | null }) | null) {
|
|
if (!product) {
|
|
return `قیمت هر ${getWeightUnit()} ${getTradePriceUnitLabel()}`
|
|
}
|
|
|
|
const title = (product.title ?? '').trim()
|
|
|
|
if (usesQuantityTrade(product)) {
|
|
const unit = getProductQuantityUnit(product)
|
|
return title ? `قیمت هر ${unit} ${title}` : `قیمت هر ${unit}`
|
|
}
|
|
|
|
if (title) {
|
|
return `قیمت هر ${getWeightUnit()} ${title}`
|
|
}
|
|
|
|
return `قیمت هر ${getWeightUnit()} ${getTradePriceUnitLabel()}`
|
|
}
|
|
|
|
/** وزن کل زیر مقدار مبادلهشده — فقط محصول تعدادی (نه trade_by_quantity) */
|
|
export function shouldShowTransactionTotalWeightLine(product?: ProductUnitSource | null) {
|
|
if (!product || usesQuantityTrade(product) || !hasProductUnitWeight(product)) {
|
|
return false
|
|
}
|
|
|
|
return isCountBasedProduct(product)
|
|
}
|