160 lines
5.2 KiB
TypeScript
160 lines
5.2 KiB
TypeScript
import type { last } from '@/model/price'
|
|
import type { MethodePrices } from '@/model/product'
|
|
import type { MeltedPriceSource } from '@/utils/productCategories'
|
|
import { isMeltedTradeGroup } from '@/utils/productCategories'
|
|
|
|
const GOLD_DOT_REFERENCE_NAME = 'گلد دات ای از آبشده - رسمی - نقد فردا'
|
|
|
|
export function findMethodPriceEntry(
|
|
prices: MethodePrices[],
|
|
readingMethod?: string | null
|
|
): MethodePrices | undefined {
|
|
if (!readingMethod) return undefined
|
|
|
|
return prices.find(
|
|
(entry) =>
|
|
entry.key === readingMethod ||
|
|
entry.id === readingMethod ||
|
|
entry.name === readingMethod
|
|
)
|
|
}
|
|
|
|
export function normalizeReferenceBase(entry: MethodePrices): { base: number; profit: number } {
|
|
let base = Number(entry.price) || 0
|
|
const profit = Number(entry.profit) || 0
|
|
|
|
if (entry.name === GOLD_DOT_REFERENCE_NAME) {
|
|
base = base / 4.3318
|
|
}
|
|
|
|
return { base, profit }
|
|
}
|
|
|
|
export function adjustedProductPrice(
|
|
basePrice: number,
|
|
baseProfit: number,
|
|
offsetPercent: number
|
|
): number {
|
|
const reference = basePrice + baseProfit
|
|
return Math.round(reference * (1 + (Number(offsetPercent) || 0) / 100))
|
|
}
|
|
|
|
export function resolveAppBasePrice(lastPrice?: Partial<last> & { price?: number } | null): number {
|
|
if (!lastPrice) return 0
|
|
|
|
const rawPrice = Number(lastPrice.price)
|
|
if (rawPrice > 0) return rawPrice
|
|
|
|
const buy = Number(lastPrice.buy) || 0
|
|
const sell = Number(lastPrice.sell) || 0
|
|
if (buy > 0 && sell > 0) return Math.round((buy + sell) / 2)
|
|
|
|
return Number(lastPrice.price_last) || 0
|
|
}
|
|
|
|
export type ProductEditorPricePreview =
|
|
| { status: 'ready'; amount: number; source: string }
|
|
| { status: 'empty'; message: string }
|
|
|
|
function resolveStoredFallbackPrice(
|
|
storedPrice: number | null | undefined,
|
|
useLastPriceIfZero: boolean | undefined
|
|
): number {
|
|
if (!useLastPriceIfZero) {
|
|
return 0
|
|
}
|
|
|
|
return Number(storedPrice) || 0
|
|
}
|
|
|
|
export function computeProductEditorPricePreview(input: {
|
|
form: {
|
|
group_type?: string
|
|
price?: number | null
|
|
reading_method?: string | null
|
|
price_offset_percent?: number | null
|
|
use_last_price_if_zero?: boolean | null
|
|
}
|
|
methodOption: string
|
|
meltedPriceOption: MeltedPriceSource
|
|
pricesData: MethodePrices[]
|
|
appLastPrice?: (Partial<last> & { price?: number }) | null
|
|
}): ProductEditorPricePreview {
|
|
const offsetPercent = Number(input.form.price_offset_percent ?? 0)
|
|
const melted = isMeltedTradeGroup(input.form.group_type)
|
|
|
|
if (melted) {
|
|
if (input.meltedPriceOption === 'fixed') {
|
|
const amount = Number(input.form.price) || 0
|
|
return amount > 0
|
|
? { status: 'ready', amount, source: 'قیمت ثابت' }
|
|
: { status: 'empty', message: 'قیمت ثابت را وارد کنید' }
|
|
}
|
|
|
|
if (input.meltedPriceOption === 'app') {
|
|
const base = resolveAppBasePrice(input.appLastPrice)
|
|
if (base > 0) {
|
|
return {
|
|
status: 'ready',
|
|
amount: adjustedProductPrice(base, 0, offsetPercent),
|
|
source: 'قیمت صفحه اصلی اپ'
|
|
}
|
|
}
|
|
const fallback = resolveStoredFallbackPrice(
|
|
input.form.price,
|
|
input.form.use_last_price_if_zero ?? false
|
|
)
|
|
return fallback > 0
|
|
? { status: 'ready', amount: fallback, source: 'آخرین قیمت ذخیرهشده' }
|
|
: { status: 'empty', message: 'قیمت provider صفر است' }
|
|
}
|
|
|
|
if (!input.form.reading_method) {
|
|
return { status: 'empty', message: 'مرجع قیمت را انتخاب کنید' }
|
|
}
|
|
const entry = findMethodPriceEntry(input.pricesData, input.form.reading_method)
|
|
if (!entry) {
|
|
return { status: 'empty', message: '' }
|
|
}
|
|
const { base, profit } = normalizeReferenceBase(entry)
|
|
const liveAmount = adjustedProductPrice(base, profit, offsetPercent)
|
|
if (liveAmount > 0) {
|
|
return { status: 'ready', amount: liveAmount, source: entry.name }
|
|
}
|
|
const fallback = resolveStoredFallbackPrice(
|
|
input.form.price,
|
|
input.form.use_last_price_if_zero ?? false
|
|
)
|
|
return fallback > 0
|
|
? { status: 'ready', amount: fallback, source: 'آخرین قیمت ذخیرهشده' }
|
|
: { status: 'empty', message: 'قیمت provider صفر است' }
|
|
}
|
|
|
|
if (input.methodOption === '1') {
|
|
const amount = Number(input.form.price) || 0
|
|
return amount > 0
|
|
? { status: 'ready', amount, source: 'قیمت دستی' }
|
|
: { status: 'empty', message: 'قیمت وسط را وارد کنید' }
|
|
}
|
|
|
|
if (!input.form.reading_method) {
|
|
return { status: 'empty', message: 'مرجع قیمت را انتخاب کنید' }
|
|
}
|
|
const entry = findMethodPriceEntry(input.pricesData, input.form.reading_method)
|
|
if (!entry) {
|
|
return { status: 'empty', message: '' }
|
|
}
|
|
const { base, profit } = normalizeReferenceBase(entry)
|
|
const liveAmount = adjustedProductPrice(base, profit, offsetPercent)
|
|
if (liveAmount > 0) {
|
|
return { status: 'ready', amount: liveAmount, source: entry.name }
|
|
}
|
|
const fallback = resolveStoredFallbackPrice(
|
|
input.form.price,
|
|
input.form.use_last_price_if_zero ?? false
|
|
)
|
|
return fallback > 0
|
|
? { status: 'ready', amount: fallback, source: 'آخرین قیمت ذخیرهشده' }
|
|
: { status: 'empty', message: 'قیمت provider صفر است' }
|
|
}
|