add price into product

This commit is contained in:
2026-06-10 10:50:53 +03:30
parent cf3dbbceb1
commit 39f7ea00db
5 changed files with 321 additions and 21 deletions
+141
View File
@@ -0,0 +1,141 @@
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 }
| { status: 'loading'; message: string }
export function computeProductEditorPricePreview(input: {
form: {
group_type?: string
price?: number | null
reading_method?: string | null
price_offset_percent?: number | null
}
methodOption: string
meltedPriceOption: MeltedPriceSource
pricesData: MethodePrices[]
appLastPrice?: (Partial<last> & { price?: number }) | null
pricesLoading?: boolean
appPriceLoading?: boolean
}): 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') {
if (input.appPriceLoading) {
return { status: 'loading', message: 'در حال دریافت قیمت اپ...' }
}
const base = resolveAppBasePrice(input.appLastPrice)
if (base <= 0) {
return { status: 'empty', message: 'قیمت اپ در دسترس نیست' }
}
return {
status: 'ready',
amount: adjustedProductPrice(base, 0, offsetPercent),
source: 'قیمت صفحه اصلی اپ'
}
}
if (!input.form.reading_method) {
return { status: 'empty', message: 'مرجع قیمت را انتخاب کنید' }
}
if (input.pricesLoading) {
return { status: 'loading', message: 'در حال دریافت قیمت مرجع...' }
}
const entry = findMethodPriceEntry(input.pricesData, input.form.reading_method)
if (!entry) {
return { status: 'empty', message: 'مرجع قیمت یافت نشد' }
}
const { base, profit } = normalizeReferenceBase(entry)
return {
status: 'ready',
amount: adjustedProductPrice(base, profit, offsetPercent),
source: entry.name
}
}
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: 'مرجع قیمت را انتخاب کنید' }
}
if (input.pricesLoading) {
return { status: 'loading', message: 'در حال دریافت قیمت مرجع...' }
}
const entry = findMethodPriceEntry(input.pricesData, input.form.reading_method)
if (!entry) {
return { status: 'empty', message: 'مرجع قیمت یافت نشد' }
}
const { base, profit } = normalizeReferenceBase(entry)
return {
status: 'ready',
amount: adjustedProductPrice(base, profit, offsetPercent),
source: entry.name
}
}