From 7440a53c807d1d82c0ca973b15a8d67e7913141b Mon Sep 17 00:00:00 2001 From: mohammad sedighi Date: Mon, 17 Aug 2026 13:10:59 +0330 Subject: [PATCH] feat(admin): signed profit/discount fields for special price packages Let buy/sell extras be entered as profit or discount so negative values work in the editor and table. Co-authored-by: Cursor --- src/core/utils/convert.ts | 1 + src/core/utils/usePrice.ts | 10 +- .../components/SignedProfitInput.vue | 152 ++++++++++++++++++ .../components/SpecialPriceEditorForm.vue | 13 +- .../specialPrice/hooks/specialPriceColumns.ts | 13 +- .../customers/specialPrice/index.vue | 4 +- 6 files changed, 180 insertions(+), 13 deletions(-) create mode 100644 src/pages/menuPages/customers/specialPrice/components/SignedProfitInput.vue diff --git a/src/core/utils/convert.ts b/src/core/utils/convert.ts index 185d9df..f1779bc 100644 --- a/src/core/utils/convert.ts +++ b/src/core/utils/convert.ts @@ -27,6 +27,7 @@ export function sanitizeNumericString( const allowDecimal = options.allowDecimal !== false let s = persian2english(String(raw ?? '').trim()) .replace(/[٬,\s]/g, '') + .replace(/[−–—]/g, '-') .replace(/٫/g, '.') .replace(/\//g, '.') diff --git a/src/core/utils/usePrice.ts b/src/core/utils/usePrice.ts index 597b4f4..e7ab5ba 100644 --- a/src/core/utils/usePrice.ts +++ b/src/core/utils/usePrice.ts @@ -2,11 +2,15 @@ import { persian2english, parseNumericValue, sanitizeNumericString } from '@core export function usePrice(price: number | string, digit = true, unit = 'ریال') { const n = typeof price === 'number' ? price : parseNumericValue(price) - let _price = Number.isFinite(n) ? String(n) : persian2english(String(price ?? '')) - if (digit && Number.isFinite(n)) { + const finite = Number.isFinite(n) + const sign = finite && n < 0 ? '-' : '' + const abs = finite ? Math.abs(n) : NaN + let _price = finite ? String(abs) : persian2english(String(price ?? '')) + if (digit && Number.isFinite(abs)) { _price = _price.replace(/\B(?=(\d{3})+(?!\d))/g, ',') } - return `${_price} ${unit}` + const shown = finite ? `${sign}${_price}` : _price + return unit ? `${shown} ${unit}` : shown } export function useTowDecimal(num: string | number): string | number { diff --git a/src/pages/menuPages/customers/specialPrice/components/SignedProfitInput.vue b/src/pages/menuPages/customers/specialPrice/components/SignedProfitInput.vue new file mode 100644 index 0000000..feedd60 --- /dev/null +++ b/src/pages/menuPages/customers/specialPrice/components/SignedProfitInput.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/src/pages/menuPages/customers/specialPrice/components/SpecialPriceEditorForm.vue b/src/pages/menuPages/customers/specialPrice/components/SpecialPriceEditorForm.vue index cc049c7..190f91b 100644 --- a/src/pages/menuPages/customers/specialPrice/components/SpecialPriceEditorForm.vue +++ b/src/pages/menuPages/customers/specialPrice/components/SpecialPriceEditorForm.vue @@ -43,11 +43,11 @@
- - + + - - + +
@@ -76,6 +76,7 @@ import { debounce } from 'lodash' import { onMounted, ref, watch } from 'vue' import BasicInput from '@/components/BasicInput.vue' import BasicSelect from '@/components/BasicSelect.vue' +import SignedProfitInput from './SignedProfitInput.vue' import { syncAndLoadCategories, type CategorySelectItem } from '@/utils/categorySelect' import { getProductsByCategories, @@ -87,8 +88,8 @@ export type SpecialPriceForm = { category_names: string[] product_ids: number[] customer_ids: number[] - profit_buy: number | string - profit_sell: number | string + profit_buy: number + profit_sell: number show_product: boolean is_active: boolean } diff --git a/src/pages/menuPages/customers/specialPrice/hooks/specialPriceColumns.ts b/src/pages/menuPages/customers/specialPrice/hooks/specialPriceColumns.ts index f94ea9d..a13b356 100644 --- a/src/pages/menuPages/customers/specialPrice/hooks/specialPriceColumns.ts +++ b/src/pages/menuPages/customers/specialPrice/hooks/specialPriceColumns.ts @@ -2,6 +2,15 @@ import type { BaseTableColumn } from '@core/type/baseTable' import { usePrice } from '@core/utils/usePrice' import { toJalali } from '@core/utils/useDataTime' +function formatSignedProfit(raw: unknown) { + const n = Number(raw ?? 0) + if (!Number.isFinite(n) || n === 0) { + return usePrice(0, true, '') + } + const label = n < 0 ? 'تخفیف' : 'سود' + return `${label} ${usePrice(Math.abs(n), true, '')}` +} + export function getSpecialPricePackageColumns(): BaseTableColumn[] { return [ { @@ -37,14 +46,14 @@ export function getSpecialPricePackageColumns(): BaseTableColumn[] { dataIndex: 'profit_buy', key: 'profit_buy', type: 'Text', - customRender: ({ record }) => usePrice(record.profit_buy ?? 0, true, '') + customRender: ({ record }) => formatSignedProfit(record.profit_buy) }, { title: 'سود فروش', dataIndex: 'profit_sell', key: 'profit_sell', type: 'Text', - customRender: ({ record }) => usePrice(record.profit_sell ?? 0, true, '') + customRender: ({ record }) => formatSignedProfit(record.profit_sell) }, { title: 'نمایش محصول', diff --git a/src/pages/menuPages/customers/specialPrice/index.vue b/src/pages/menuPages/customers/specialPrice/index.vue index 23986e0..6e3872c 100644 --- a/src/pages/menuPages/customers/specialPrice/index.vue +++ b/src/pages/menuPages/customers/specialPrice/index.vue @@ -88,8 +88,8 @@ async function openEdit(record: any) { category_names: data?.category_names ?? [], product_ids: (data?.product_ids ?? []).map(Number), customer_ids: (data?.customer_ids ?? []).map(Number), - profit_buy: data?.package?.profit_buy ?? 0, - profit_sell: data?.package?.profit_sell ?? 0, + profit_buy: Number(data?.package?.profit_buy ?? 0), + profit_sell: Number(data?.package?.profit_sell ?? 0), show_product: Boolean(data?.package?.show_product ?? true), is_active: Boolean(data?.package?.is_active ?? true) }