price handling

This commit is contained in:
2026-06-22 21:10:25 +03:30
parent 9d11616ec7
commit bfc4bec4cd
9 changed files with 388 additions and 50 deletions
+208 -22
View File
@@ -1,4 +1,6 @@
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 {
@@ -8,7 +10,9 @@ import {
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
@@ -183,29 +187,190 @@ export function getProductQuantityUnit(product?: ProductUnitSource | null) {
return getWeightUnit()
}
function getDefaultTypeDealOptions(): SelectItem[] {
const settingsStore = useSettingsStore()
return [
{ value: 'نقدی', key: 'cash' },
{ value: settingsStore.metalTypeLabel, key: 'gold' },
]
export const MELTED_DEAL_METHOD_PREFIX = 'gold:'
export interface ProductDealMethodContext {
tradedProduct?: Product | null
productMetalId?: number | null
inventoryCards?: WalletInventoryCard[]
catalog?: Product[]
}
export function getProductDealMethodOptions(groupType?: string | null, isBuy = true): SelectItem[] {
/** سلکت نحوه معامله فقط وقتی محصول مورد معامله وزن دارد */
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 product.direct_price === 0
? basePrice * (product.amount ?? 0)
: basePrice
}
export function resolveProductTradeSellUnitPrice(product?: Product | null) {
if (!product) {
return 0
}
const basePrice = (product.price ?? 0) - (product.cash_fee_sell ?? 0)
return product.direct_price === 0
? basePrice * (product.amount ?? 0)
: basePrice
}
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()) {
if (isBuy) {
return [
{ value: 'نقدی', key: 'cash' },
{ value: settingsStore.metalTypeLabel, key: 'gold' },
]
}
return [
{ value: 'نقدی', key: 'cash' },
{ value: `دریافت ${settingsStore.metalTypeLabel}`, key: 'gold' },
]
return getDefaultTypeDealOptions(context, isBuy)
}
if (isMaftolMesGroup(groupType)) {
@@ -230,11 +395,15 @@ export function getProductDealMethodOptions(groupType?: string | null, isBuy = t
return [{ value: settingsStore.meltedGoldLabel, key: 'gold' }]
}
return getDefaultTypeDealOptions()
return getDefaultTypeDealOptions(context, isBuy)
}
export function getDefaultProductDealMethod(groupType?: string | null, isBuy = true) {
return getProductDealMethodOptions(groupType, isBuy)[0]?.key ?? 'cash'
export function getDefaultProductDealMethod(
groupType?: string | null,
isBuy = true,
context?: ProductDealMethodContext | null,
) {
return getProductDealMethodOptions(groupType, isBuy, context)[0]?.key ?? 'cash'
}
export function getProductDealMethodPlaceholder(isBuy = true) {
@@ -265,7 +434,24 @@ export function isCashLikeDealMethod(method?: string | null) {
}
export function isMainMetalWalletDealMethod(method?: string | null) {
return method === 'gold' || method === 'katod'
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 */