diff --git a/src/components/mobile/utils/wallet.ts b/src/components/mobile/utils/wallet.ts index c96f1db..e2339da 100644 --- a/src/components/mobile/utils/wallet.ts +++ b/src/components/mobile/utils/wallet.ts @@ -5,11 +5,104 @@ export function getWallets(wallet?: Wallet | Wallet[]): Wallet[] { return Array.isArray(wallet) ? wallet : [wallet] } -export function getCashBalance(wallet?: Wallet | Wallet[]): number { - return getWallets(wallet)[0]?.cash ?? 0 +/** کیف اصلی مشتری — بدون fund و بدون product */ +export function getMainWallet(wallet?: Wallet | Wallet[]): Wallet | undefined { + const wallets = getWallets(wallet) + return wallets.find((w) => w.fund_id == null && w.product_id == null) } -export function getGoldBalance(wallet?: Wallet | Wallet[]): string { - const sum = getWallets(wallet).reduce((total, item) => total + (item.gold ?? 0), 0) +/** پارس setting `main_wallet_products` — id با کاما یا JSON */ +export function parseMainWalletProductIds(raw?: string | null): number[] { + const value = (raw ?? '').trim() + if (!value) return [] + + try { + const decoded = JSON.parse(value) + if (Array.isArray(decoded)) { + return [...new Set(decoded.map((id) => Number(id)).filter((id) => id > 0))] + } + } catch { + // کاما‌جدا + } + + return [ + ...new Set( + value + .split(',') + .map((part) => Number(part.trim())) + .filter((id) => id > 0) + ) + ] +} + +let cachedMainWalletProductIds: number[] | null = null + +export function setCachedMainWalletProductIds(ids: number[]): void { + cachedMainWalletProductIds = ids +} + +/** بارگذاری یک‌باره از API تنظیمات */ +export async function initMainWalletProductIds(): Promise { + if (cachedMainWalletProductIds !== null) { + return cachedMainWalletProductIds + } + + const { initWalletSettingsFromApi } = await import('@/utils/config') + await initWalletSettingsFromApi() + + return cachedMainWalletProductIds ?? [] +} + +export function getMainWalletProductIds(): number[] { + return cachedMainWalletProductIds ?? [] +} + +/** + * موجودی ریالی کیف اصلی. + * با main_wallet_products ممکن است کیف legacy محصول (مثلاً id=13) cash=0 داشته باشد — فقط کیف اصلی معتبر است. + */ +export function getCashBalance( + wallet?: Wallet | Wallet[], + options?: { walletCash?: number | null } +): number { + if (options?.walletCash != null) { + return Number(options.walletCash) + } + return getMainWallet(wallet)?.cash ?? 0 +} + +/** + * جمع طلای قابل‌نمایش — هم‌راستا با WalletBalanceService سرور. + * کیف legacy محصولات main_wallet_products در جمع نمی‌آید. + */ +export function getGoldBalance( + wallet?: Wallet | Wallet[], + options?: { walletGold?: number | null; mainWalletProductIds?: number[] } +): string { + if (options?.walletGold != null) { + return Number(options.walletGold).toFixed(3) + } + + const mainWalletProductIds = options?.mainWalletProductIds ?? getMainWalletProductIds() + const sum = getWallets(wallet).reduce((total, line) => { + const gold = Number(line.gold ?? 0) + if (gold <= 0) return total + + if (line.fund_id != null) { + return total + gold + } + + if (line.product_id == null) { + return total + gold + } + + const productId = Number(line.product_id) + if (mainWalletProductIds.length > 0 && mainWalletProductIds.includes(productId)) { + return total + } + + return total + gold + }, 0) + return sum.toFixed(3) } diff --git a/src/model/customer.ts b/src/model/customer.ts index 3c04dfb..b58d073 100644 --- a/src/model/customer.ts +++ b/src/model/customer.ts @@ -26,6 +26,8 @@ export interface Customer { city: string province: string wallet: Wallet + wallet_cash?: number + wallet_gold?: number n_code: string | number last_seen_at:string profit_amount: number diff --git a/src/model/wallet.ts b/src/model/wallet.ts index 48653a7..370116c 100644 --- a/src/model/wallet.ts +++ b/src/model/wallet.ts @@ -5,6 +5,8 @@ export interface Wallet { id: number gold: number cash: number + fund_id?: number | null + product_id?: number | null customer: User } @@ -32,11 +34,15 @@ export interface Withdraw { transaction?: WithdrawTransaction[] } +export type WalletChargeDirection = 'charge' | 'discharge' + export interface Charge { value?: number note?: string customer_id?: number talabBedehi?: boolean + direction?: WalletChargeDirection + amountAbs?: number | string } export interface WithdrawStatus { diff --git a/src/pages/menuPages/accounting/index.vue b/src/pages/menuPages/accounting/index.vue index fecc89c..1ef5dd8 100644 --- a/src/pages/menuPages/accounting/index.vue +++ b/src/pages/menuPages/accounting/index.vue @@ -67,13 +67,13 @@ is-line title="کیف پول طلا" class="mt-2" - :value="selectedCustomer?.wallet[0]?.gold ?? '_'" + :value="getGoldBalance(selectedCustomer?.wallet) || '_'" />
@@ -142,6 +142,7 @@ import { usePrice } from '@core/utils/usePrice' import { getLastPrice } from '@/api/price' import type { last } from '@/model/price' import { createOrder } from '@/api/order' +import { getCashBalance, getGoldBalance } from '@/components/mobile/utils/wallet' //loading const loading = ref(false) @@ -217,7 +218,6 @@ async function getPrices() { async function changeUser(val: Customer) { selectedCustomer.value = cloneDeep(val) - console.log(selectedCustomer.value.wallet[0]) } function stopGetPrice() { diff --git a/src/pages/menuPages/configuration/index.vue b/src/pages/menuPages/configuration/index.vue index cdab5cb..a893f5c 100644 --- a/src/pages/menuPages/configuration/index.vue +++ b/src/pages/menuPages/configuration/index.vue @@ -337,7 +337,7 @@ const SETTING_GROUPS: Array<{ id: 'support', title: 'پشتیبانی اپ کاربر', icon: 'vuesax-linear:headphone', - match: (k) => k.startsWith('support_messenger') + match: (k) => k.startsWith('support_messenger') || k === 'deposit_sms_support_number' }, { id: 'bots', diff --git a/src/pages/menuPages/configuration/settingTypes.ts b/src/pages/menuPages/configuration/settingTypes.ts index 19ceacc..24429f5 100644 --- a/src/pages/menuPages/configuration/settingTypes.ts +++ b/src/pages/menuPages/configuration/settingTypes.ts @@ -88,6 +88,7 @@ const KEY_TYPE_FALLBACK: Record = { support_messenger_id: 'text', support_messenger_text: 'longtext', support_messenger: 'select', + deposit_sms_support_number: 'number', zaarbox_price_key: 'select' } diff --git a/src/pages/menuPages/customers/base/components/WalletChargeForm.vue b/src/pages/menuPages/customers/base/components/WalletChargeForm.vue new file mode 100644 index 0000000..0885f7a --- /dev/null +++ b/src/pages/menuPages/customers/base/components/WalletChargeForm.vue @@ -0,0 +1,221 @@ + + + + + diff --git a/src/pages/menuPages/customers/base/hooks/customerColumns.tsx b/src/pages/menuPages/customers/base/hooks/customerColumns.tsx index 1dfa4dc..4b04365 100644 --- a/src/pages/menuPages/customers/base/hooks/customerColumns.tsx +++ b/src/pages/menuPages/customers/base/hooks/customerColumns.tsx @@ -2,6 +2,7 @@ import type { BaseTableColumn } from '@core/type/baseTable' import {toJalali, toJalaliNoTime, toTime} from '@core/utils/useDataTime' import CustomTag from '@/components/CustomTag.vue' import { usePrice } from '@core/utils/usePrice' +import { getCashBalance, getGoldBalance } from '@/components/mobile/utils/wallet' /*import BudgetSelect from '@/components/BudgetSelect.vue' import { useStaticApiListsStore } from '@/store/staticApisStore' import type { FilterSelect } from '@/model/filterSelect' @@ -75,7 +76,7 @@ export const cols: BaseTableColumn[] = [ key: 'wallet.cash', type: 'Number', customRender(data) { - return usePrice(data.record?.wallet[0]?.cash ?? 0, true, '') + return usePrice(getCashBalance(data.record?.wallet, { walletCash: data.record?.wallet_cash }), true, '') } }, { @@ -85,9 +86,7 @@ export const cols: BaseTableColumn[] = [ type: 'Number', filterable: false, customRender(data) { - let sum = 0 - data.record.wallet.forEach((x) => (sum += x.gold)) - return sum.toFixed(3) + return getGoldBalance(data.record?.wallet, { walletGold: data.record?.wallet_gold }) } }, { diff --git a/src/pages/menuPages/customers/base/index.vue b/src/pages/menuPages/customers/base/index.vue index fa4ead0..7c49d03 100644 --- a/src/pages/menuPages/customers/base/index.vue +++ b/src/pages/menuPages/customers/base/index.vue @@ -218,103 +218,59 @@ - - - طلب/بدهی - - - -
- معادل {{ usePrice(formCharge.value / 10, true, 'تومان') }} -
-
- - - -
+
- - - طلب/بدهی - - - -
- معادل {{ usePrice(formCharge.value / 10, true, 'تومان') }} -
-
- - - -
+
- - - طلب/بدهی - - - - - - - - + - - - طلب/بدهی - - - - - - - - + (false) //form const form = ref>({}) -const formCharge = ref({}) const formRef = ref() -const formChargeRef = ref() +const formCharge = ref({}) +const moneyChargeFormRef = ref>() +const goldChargeFormRef = ref>() + +const moneyChargeTitle = computed(() => walletChargeTitle('money', formCharge.value.direction)) +const goldChargeTitle = computed(() => walletChargeTitle('gold', formCharge.value.direction)) +const moneyChargeOkText = computed(() => walletChargeOkText(formCharge.value.direction)) +const goldChargeOkText = computed(() => walletChargeOkText(formCharge.value.direction)) //info let infoParams = reactive({}) @@ -540,21 +510,7 @@ async function add() { } function resetFormCharge(customerId: number) { - formCharge.value = { - customer_id: customerId, - value: undefined, - note: undefined, - talabBedehi: false - } -} - -function buildChargePayload(): Charge { - return { - value: formCharge.value.value, - note: formCharge.value.note, - customer_id: formCharge.value.customer_id, - talabBedehi: formCharge.value.talabBedehi === true - } + formCharge.value = createEmptyChargeForm(customerId) } async function walletMoneyCharge(val: Customer) { @@ -568,11 +524,11 @@ async function walletGoldCharge(val: Customer) { } async function chargeMoneyWallet() { - formChargeRef.value?.validateFields().then(async () => { + moneyChargeFormRef.value?.validateFields()?.then(async () => { try { loading.value = true - await chargeWallet(buildChargePayload(), 'money') - message.success('افزایش اعتبار با موفقیت انجام شد') + await chargeWallet(buildChargePayload(formCharge.value), 'money') + message.success(walletChargeSuccessMessage(formCharge.value.direction)) showMoneyWalletCharge.value = false } catch (e) { console.log(e) @@ -583,11 +539,11 @@ async function chargeMoneyWallet() { } async function chargeGoldWallet() { - formChargeRef.value?.validateFields().then(async () => { + goldChargeFormRef.value?.validateFields()?.then(async () => { try { loading.value = true - await chargeWallet(buildChargePayload(), 'gold') - message.success('افزایش اعتبار با موفقیت انجام شد') + await chargeWallet(buildChargePayload(formCharge.value), 'gold') + message.success(walletChargeSuccessMessage(formCharge.value.direction)) showGoldWalletCharge.value = false } catch (e) { console.log(e) diff --git a/src/pages/menuPages/customers/base/utils/walletChargeForm.ts b/src/pages/menuPages/customers/base/utils/walletChargeForm.ts new file mode 100644 index 0000000..beaaf20 --- /dev/null +++ b/src/pages/menuPages/customers/base/utils/walletChargeForm.ts @@ -0,0 +1,40 @@ +import type { Charge, WalletChargeDirection } from '@/model/wallet' + +export function createEmptyChargeForm(customerId: number): Charge { + return { + customer_id: customerId, + value: undefined, + note: undefined, + talabBedehi: false, + direction: 'charge', + amountAbs: undefined + } +} + +export function buildChargePayload(form: Charge): Charge { + const amount = Math.abs(Number(form.amountAbs) || 0) + const signed = form.direction === 'discharge' ? -amount : amount + return { + value: signed, + note: form.note, + customer_id: form.customer_id, + talabBedehi: form.talabBedehi === true + } +} + +export function walletChargeTitle( + variant: 'money' | 'gold', + direction: WalletChargeDirection = 'charge' +) { + const wallet = variant === 'money' ? 'ریالی' : 'طلایی' + const action = direction === 'discharge' ? 'دشارژ' : 'شارژ' + return `${action} کیف پول ${wallet}` +} + +export function walletChargeOkText(direction: WalletChargeDirection = 'charge') { + return direction === 'discharge' ? 'ثبت دشارژ' : 'ثبت شارژ' +} + +export function walletChargeSuccessMessage(direction: WalletChargeDirection = 'charge') { + return direction === 'discharge' ? 'دشارژ با موفقیت انجام شد' : 'شارژ با موفقیت انجام شد' +} diff --git a/src/utils/config.ts b/src/utils/config.ts index f63ac01..d9bc476 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -8,6 +8,7 @@ export function getConfigApp(key: string) { } let storeModeFromSettings: boolean | null = null +let settingsBootstrapped = false function isSwitchOn(value: string | undefined | null): boolean { const v = (value ?? '').trim().toLowerCase() @@ -18,20 +19,39 @@ export function setStoreModeFromSettings(value: boolean): void { storeModeFromSettings = value } -/** is_store فقط از API تنظیمات (get_settings) خوانده می‌شود — نه از get_user */ -export async function initStoreModeFromSettings(): Promise { - if (storeModeFromSettings !== null) return storeModeFromSettings +async function bootstrapSettingsFromApi(): Promise { + if (settingsBootstrapped) return try { const { getConfiguration } = await import('@/api/configuration') + const { parseMainWalletProductIds } = await import('@/components/mobile/utils/wallet') const rows = await getConfiguration() - const row = Array.isArray(rows) ? rows.find((item) => item.key === 'is_store') : null - storeModeFromSettings = row ? isSwitchOn(row.value) : false + const list = Array.isArray(rows) ? rows : [] + const isStoreRow = list.find((item) => item.key === 'is_store') + const mainWalletRow = list.find((item) => item.key === 'main_wallet_products') + storeModeFromSettings = isStoreRow ? isSwitchOn(isStoreRow.value) : false + const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet') + setCachedMainWalletProductIds(parseMainWalletProductIds(mainWalletRow?.value)) } catch { storeModeFromSettings = false + const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet') + setCachedMainWalletProductIds([]) + } finally { + settingsBootstrapped = true } +} - return storeModeFromSettings +/** is_store و main_wallet_products از API تنظیمات — نه از get_user */ +export async function initStoreModeFromSettings(): Promise { + if (storeModeFromSettings !== null) return storeModeFromSettings + + await bootstrapSettingsFromApi() + + return storeModeFromSettings === true +} + +export async function initWalletSettingsFromApi(): Promise { + await bootstrapSettingsFromApi() } export function isStoreApp(): boolean {