From 4cd11919f526e6c3dcd6b6dc05d87aeb1e9dc2f1 Mon Sep 17 00:00:00 2001 From: adonis Date: Tue, 28 Jul 2026 17:43:35 +0330 Subject: [PATCH] fix some bugs from accounting --- .../customer/CustomerWalletBalancePanel.vue | 13 +++++++++--- src/model/wallet.ts | 2 ++ .../base/components/WalletChargeForm.vue | 20 ++++++++++++++----- .../base/components/WalletChargeModalBody.vue | 20 ++++++++++++++++++- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/components/customer/CustomerWalletBalancePanel.vue b/src/components/customer/CustomerWalletBalancePanel.vue index 7a17f42..857b529 100644 --- a/src/components/customer/CustomerWalletBalancePanel.vue +++ b/src/components/customer/CustomerWalletBalancePanel.vue @@ -143,6 +143,7 @@ import type { ChargeTarget } from '@/model/wallet' import type { WalletAssetsSummary, WalletInventoryCard, WalletMetalTotal } from '@/model/walletAssets' import { usePrice } from '@core/utils/usePrice' import { formatMetalDisplayValue } from '@/utils/metalWeight' +import { isMeltedTradeGroup } from '@/utils/productCategories' const props = withDefaults( defineProps<{ @@ -247,10 +248,16 @@ function balanceForTarget(target: ChargeTarget) { const card = inventoryCards().find((row) => Number(row.product_id) === Number(target.product_id)) if (card) return formatCard(card) - const unit = target.unit || (target.trade_by_quantity ? 'عدد' : 'گرم') - if (target.trade_by_quantity) { - return `۰ ${unit}` + // تعدادی: همیشه «عدد» — نه گرم (وزن هر قطعه در فیلد unit محصول است) + const isCount = + target.allows_decimal === false || + target.unit === 'عدد' || + (target.trade_by_quantity === false && !isMeltedTradeGroup(target.group_type)) + + if (isCount) { + return '۰ عدد' } + return formatMetalDisplayValue(0, target.metal_id ?? 1) } diff --git a/src/model/wallet.ts b/src/model/wallet.ts index ed627ec..b721df4 100644 --- a/src/model/wallet.ts +++ b/src/model/wallet.ts @@ -116,6 +116,8 @@ export interface ChargeTarget { metal_id?: number uses_main_wallet?: boolean trade_by_quantity?: boolean + /** false برای محصولات تعدادی — فقط عدد صحیح */ + allows_decimal?: boolean group_type?: string active?: boolean } diff --git a/src/pages/menuPages/customers/base/components/WalletChargeForm.vue b/src/pages/menuPages/customers/base/components/WalletChargeForm.vue index 0aec76d..62a4e57 100644 --- a/src/pages/menuPages/customers/base/components/WalletChargeForm.vue +++ b/src/pages/menuPages/customers/base/components/WalletChargeForm.vue @@ -37,6 +37,7 @@ v-model:value="modelValue.amountAbs" :addon-before="resolvedUnit" :type="resolvedInputType" + :step="integerOnly ? 1 : undefined" :place-holder="amountPlaceholder" />
@@ -66,11 +67,14 @@ const props = withDefaults( unitLabel?: string /** true = ورودی قیمتی (ریال)، false = عددی */ isMoney?: boolean + /** محصولات تعدادی — فقط عدد صحیح */ + integerOnly?: boolean /** نام کیف پول برای پیش‌نمایش */ walletLabel?: string }>(), { variant: 'money', + integerOnly: false, }, ) @@ -80,6 +84,7 @@ const resolvedUnit = computed( () => props.unitLabel ?? (props.variant === 'money' ? 'ریال' : 'گرم'), ) const isMoney = computed(() => props.isMoney ?? props.variant === 'money') +const integerOnly = computed(() => props.integerOnly === true) const resolvedInputType = computed(() => (isMoney.value ? 'price' : 'number')) const isDischarge = computed(() => props.modelValue.direction === 'discharge') @@ -107,15 +112,17 @@ const amountLabel = computed(() => const noteLabel = computed(() => (isDischarge.value ? 'علت دشارژ' : 'علت شارژ')) -const amountPlaceholder = computed(() => - isMoney.value ? 'مثلاً ۱۰۰٬۰۰۰' : 'مثلاً ۰.۵', -) +const amountPlaceholder = computed(() => { + if (isMoney.value) return 'مثلاً ۱۰۰٬۰۰۰' + if (integerOnly.value) return 'مثلاً ۱' + return 'مثلاً ۰.۵' +}) const notePlaceholder = computed(() => isDischarge.value ? 'دلیل کسر موجودی' : 'دلیل افزایش موجودی', ) -const amountRules = [ +const amountRules = computed(() => [ ...inputRules('مقدار'), { validator: (_rule: unknown, value: string | number | undefined) => { @@ -123,10 +130,13 @@ const amountRules = [ if (!num) { return Promise.reject('مقدار باید بیشتر از صفر باشد') } + if (integerOnly.value && Math.abs(num - Math.round(num)) > 0.000001) { + return Promise.reject('برای محصول تعدادی فقط عدد صحیح مجاز است') + } return Promise.resolve() }, }, -] +]) defineExpose({ validateFields: () => formRef.value?.validateFields(), diff --git a/src/pages/menuPages/customers/base/components/WalletChargeModalBody.vue b/src/pages/menuPages/customers/base/components/WalletChargeModalBody.vue index 05cc77b..89a91ed 100644 --- a/src/pages/menuPages/customers/base/components/WalletChargeModalBody.vue +++ b/src/pages/menuPages/customers/base/components/WalletChargeModalBody.vue @@ -42,8 +42,9 @@
@@ -56,6 +57,7 @@ import CustomerWalletBalancePanel from '@/components/customer/CustomerWalletBala import { getCustomersList } from '@/api/customer' import type { Charge, ChargeTarget } from '@/model/wallet' import type { Customer } from '@/model/customer' +import { isMeltedTradeGroup } from '@/utils/productCategories' const props = defineProps<{ formCharge: Charge @@ -111,6 +113,22 @@ const targetOptions = computed(() => })), ) +/** تعدادی: فقط عدد صحیح — از allows_decimal سرور یا واحد «عدد» */ +const isIntegerOnlyTarget = computed(() => { + const target = props.selectedTarget + if (!target || target.kind === 'money') return false + if (typeof target.allows_decimal === 'boolean') return !target.allows_decimal + if (target.unit === 'عدد') return true + // fallback قبل از آپدیت سرور: تعدادی ≠ آبشده/کاتد + return target.trade_by_quantity === false && !isMeltedTradeGroup(target.group_type) +}) + +const chargeUnitLabel = computed(() => { + if (props.selectedTarget?.kind === 'money') return 'ریال' + if (isIntegerOnlyTarget.value) return 'عدد' + return props.selectedTarget?.unit ?? 'گرم' +}) + function filterCustomer(input: string, option?: { label?: string }) { return String(option?.label ?? '').toLowerCase().includes(input.toLowerCase()) }