Add customer multi-level referral profit editor and related settings UI.
Expose enable_customer_level_profit in config and let admins edit per-customer level percents from the customers table/mobile sheets. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,4 +14,6 @@ export const postAdminChatUnfocus = async (room_id: string) =>
|
||||
await useAxios.post('/admin/chat/unfocus', { room_id })
|
||||
|
||||
export const postAdminChatEnsureWebhook = async () =>
|
||||
await useAxios.post('/admin/chat/ensure-webhook')
|
||||
await useAxios.post('/admin/chat/ensure-webhook', undefined, {
|
||||
meta: { silent: true },
|
||||
})
|
||||
|
||||
+20
-14
@@ -87,29 +87,35 @@ _axios.interceptors.response.use(
|
||||
await router.push({ name: 'login' })
|
||||
} else if (error.response && error.response.status == 403) {
|
||||
if (!error.config?.meta?.silent) {
|
||||
message.error('شما دسترسی لازم برای انجام این عملیات را ندارید')
|
||||
message.error('شما دسترسی لازم برای انجام این عملیات را ندارید (403)')
|
||||
}
|
||||
} else if (error.response && error.response.status == 422) {
|
||||
if (!error.config?.meta?.silent) {
|
||||
message.error(error.response.data?.message)
|
||||
}
|
||||
} else if (error.response) {
|
||||
if (!error.config?.meta?.silent) {
|
||||
const apiMessage = error.response.data?.message
|
||||
message.error(
|
||||
typeof apiMessage === 'string' && apiMessage.trim()
|
||||
? formatApiErrorMessage(apiMessage)
|
||||
: 'خطا در بارگذاری اطلاعات',
|
||||
? `${apiMessage} (422)`
|
||||
: 'خطا در اعتبارسنجی (422)',
|
||||
)
|
||||
}
|
||||
} else if (error.response) {
|
||||
if (!error.config?.meta?.silent) {
|
||||
const status = Number(error.response.status)
|
||||
if (status >= 500) {
|
||||
message.error(`خطا در برقراری ارتباط با سرور (${status})`)
|
||||
} else {
|
||||
const apiMessage = error.response.data?.message
|
||||
const base =
|
||||
typeof apiMessage === 'string' && apiMessage.trim()
|
||||
? formatApiErrorMessage(apiMessage)
|
||||
: 'خطا در بارگذاری اطلاعات'
|
||||
message.error(`${base} (${status})`)
|
||||
}
|
||||
}
|
||||
} else if (!error.config?.meta?.silent) {
|
||||
// بدون status (نه 4xx نه 5xx): قطع شبکه، timeout، DNS، …
|
||||
message.error('لطفا اینترنت خود را بررسی کنید و مجددا تلاش کنید')
|
||||
}
|
||||
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
||||
// Do something with response error
|
||||
|
||||
//const { response, code, message, config } = error || {}
|
||||
//const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none'
|
||||
//const msg: string = response?.data?.error?.message ?? ''
|
||||
//checkStatus(error?.response?.status, msg)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -41,5 +41,12 @@ export interface Customer {
|
||||
gold: number
|
||||
moshtari_code?: string | number | null
|
||||
pargar_account_id?: string | number | null
|
||||
/** درصد سود چندسطحی از کارمزد زیرمجموعهها — `{ level, present }` */
|
||||
profit_amount_by_lvl?: ProfitByLevel[]
|
||||
// print_name: string
|
||||
}
|
||||
|
||||
export interface ProfitByLevel {
|
||||
level: number
|
||||
present: number
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ export const SYSTEM_SETTING_GROUPS: SettingGroupDef[] = [
|
||||
title: 'دسترسی مشتری به قابلیتها',
|
||||
icon: 'vuesax-linear:people',
|
||||
match: (k) =>
|
||||
/^(enable_conditional_order|enable_product_funds|has_page_price_trigger|has_page_notification|banner_enabled|jibit_enabled|customer_direct_sms|has_page_earn_money|group_sms|tracking_systems_enabled|permision__enabled|show_to_users_chat)$/.test(
|
||||
/^(enable_conditional_order|enable_product_funds|has_page_price_trigger|has_page_notification|has_page_gift_card|enable_customer_level_profit|banner_enabled|jibit_enabled|customer_direct_sms|has_page_earn_money|group_sms|tracking_systems_enabled|permision__enabled|show_to_users_chat)$/.test(
|
||||
k
|
||||
)
|
||||
},
|
||||
|
||||
@@ -263,6 +263,8 @@ const KEY_TYPE_FALLBACK: Record<string, SettingFieldType> = {
|
||||
enable_product_funds: 'switch',
|
||||
has_page_price_trigger: 'switch',
|
||||
has_page_notification: 'switch',
|
||||
has_page_gift_card: 'switch',
|
||||
enable_customer_level_profit: 'switch',
|
||||
min_withdraw: 'price',
|
||||
min_deposit: 'price',
|
||||
min_first_buy: 'price',
|
||||
@@ -363,6 +365,7 @@ const KEY_TYPE_FALLBACK: Record<string, SettingFieldType> = {
|
||||
deposit_support_message_text: 'longtext',
|
||||
deposit_account_holder: 'text',
|
||||
deposit_card_number: 'text',
|
||||
deposit_account_number: 'text',
|
||||
deposit_sheba: 'text',
|
||||
invite_link_text: 'longtext',
|
||||
support_messenger: 'select',
|
||||
@@ -649,6 +652,10 @@ const KEY_HELP_FALLBACK: Record<string, string> = {
|
||||
'روشن: قابلیت سفارش شرطی سراسری فعال است. خاموش: منو و ارزیابی اجرا نمیشود. فقط از صفحه دیپلوی قابل تغییر است.',
|
||||
enable_product_funds:
|
||||
'روشن: ساخت و مدیریت قلک per-product در اپ مشتری فعال است (یک محصول در هر قلک؛ انتقال بدون سند حسابداری). خاموش: منو و API ساخت قلک جدید در دسترس نیست. فقط از دیپلوی قابل تغییر است.',
|
||||
has_page_gift_card:
|
||||
'روشن: منوی «ثبت کارت هدیه» و صفحه ثبت کد در اپ کاربر فعال است. خاموش: منو و صفحه مخفی است و API استفاده از کد هدیه در دسترس نیست. فقط از دیپلوی قابل تغییر است.',
|
||||
enable_customer_level_profit:
|
||||
'روشن: در لیست مشتریان آیکون تنظیم درصد سود هر سطح زیرمجموعه فعال است و پس از سفارش، سهم کارمزد طبق درصدهای هر معرف به کیف طلا واریز میشود. خاموش: آیکون و واریز سود چندسطحی غیرفعال است. فقط از دیپلوی قابل تغییر است.',
|
||||
has_page_price_trigger:
|
||||
'روشن: منوی هشدار قیمت در اپ مشتری نمایش داده میشود. خاموش: منو و صفحه مخفی است. فقط از صفحه دیپلوی قابل تغییر است.',
|
||||
has_page_notification:
|
||||
@@ -756,13 +763,15 @@ const KEY_HELP_FALLBACK: Record<string, string> = {
|
||||
support_messenger_id:
|
||||
'شناسه تماس در پیامرسان انتخابشده: یوزرنیم، آیدی یا لینک کامل. فقط روی آیکون پیامرسان و دکمه شناور اعمال میشود؛ تماس تلفنی از فیلد «شماره پشتیبانی» خوانده میشود.',
|
||||
support_messenger_text:
|
||||
'متن راهنمای واریز در مودال شارژ حساب. متن را بنویسید و متغیرها (نام صاحب حساب، شماره کارت، شبا) را با کلیک اضافه کنید؛ پیشنمایش نتیجه را با مقادیر نمونه نشان میدهد. خالی = متن پیشفرض اپ.',
|
||||
'متن راهنمای واریز در مودال شارژ حساب. متن را بنویسید و متغیرها (نام صاحب حساب، شماره کارت، شماره حساب، شبا) را با کلیک اضافه کنید؛ پیشنمایش نتیجه را با مقادیر نمونه نشان میدهد. خالی = متن پیشفرض اپ.',
|
||||
deposit_support_message_text:
|
||||
'متن پیشنویس فقط وقتی کاربر از مودال راهنمای واریز روی «پیام به پشتیبانی» یا SMS میزند. منوی شناور پشتیبانی این متن را نمیگذارد. خالی = متن پیشفرض اپ.',
|
||||
deposit_account_holder:
|
||||
'نام صاحب حساب واریز — در متن راهنمای واریز با ٪نام یا %نام جایگزین میشود. در پیام پشتیبانی فقط وقتی نام مشتری موجود نباشد استفاده میشود.',
|
||||
deposit_card_number:
|
||||
'شماره کارت واریز — در متنها با ٪کارت یا %کارت جایگزین میشود.',
|
||||
deposit_account_number:
|
||||
'شماره حساب بانکی واریز — در مودال راهنمای شارژ کنار کارت و شبا نمایش داده میشود. در متنها با ٪حساب یا %حساب جایگزین میشود.',
|
||||
deposit_sheba:
|
||||
'شماره شبا واریز — در متنها با ٪شبا یا %شبا جایگزین میشود.',
|
||||
deposit_sms_support_number:
|
||||
@@ -939,6 +948,8 @@ export const KEY_LABEL_FALLBACK: Record<string, string> = {
|
||||
fee_conditional_order: 'کارمزد سفارش شرطی',
|
||||
enable_conditional_order: 'سفارش شرطی',
|
||||
enable_product_funds: 'قلک محصول',
|
||||
has_page_gift_card: 'کارت هدیه',
|
||||
enable_customer_level_profit: 'سود چندسطحی معرف',
|
||||
has_page_price_trigger: 'هشدار قیمت',
|
||||
has_page_notification: 'اعلان داخل اپ',
|
||||
jibit_enabled: 'احراز هویت جیبیت',
|
||||
@@ -1016,6 +1027,7 @@ export const KEY_LABEL_FALLBACK: Record<string, string> = {
|
||||
deposit_support_message_text: 'متن پیام به پشتیبانی (واریز)',
|
||||
deposit_account_holder: 'نام صاحب حساب واریز',
|
||||
deposit_card_number: 'شماره کارت واریز',
|
||||
deposit_account_number: 'شماره حساب واریز',
|
||||
deposit_sheba: 'شبا واریز',
|
||||
deposit_sms_support_number: 'شماره تماس پشتیبانی',
|
||||
price_channel_enabled: 'ارسال قیمت به کانال',
|
||||
@@ -1056,6 +1068,8 @@ export const SETTING_LOCKED_KEYS = new Set([
|
||||
'enable_product_funds',
|
||||
'has_page_price_trigger',
|
||||
'has_page_notification',
|
||||
'has_page_gift_card',
|
||||
'enable_customer_level_profit',
|
||||
'jibit_enabled',
|
||||
'has_page_earn_money',
|
||||
'is_store',
|
||||
@@ -1103,7 +1117,7 @@ export const SETTING_EDITABLE_KEYS = new Set([
|
||||
'sms_notif_fund_withdraw_admin', 'sms_notif_fund_withdraw_customer',
|
||||
'sms_notif_price_trigger', 'sms_notif_wallet_alert', 'sms_notif_support_admin',
|
||||
'deposit_sms_support_number', 'deposit_support_message_text',
|
||||
'deposit_account_holder', 'deposit_card_number', 'deposit_sheba',
|
||||
'deposit_account_holder', 'deposit_card_number', 'deposit_account_number', 'deposit_sheba',
|
||||
'endDay',
|
||||
'fee_free', 'fee_service_charge_percentage',
|
||||
'gift_for_referral', 'gift_for_referrer',
|
||||
@@ -1122,7 +1136,7 @@ export const SETTING_EDITABLE_KEYS = new Set([
|
||||
'startDay',
|
||||
'support_messengers', 'support_messenger_text',
|
||||
'has_chat',
|
||||
'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba',
|
||||
'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_account_number', 'deposit_sheba',
|
||||
'text_about', 'text_rule',
|
||||
'zaarbox_price_key',
|
||||
'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff',
|
||||
|
||||
@@ -182,7 +182,7 @@ export const TEMPLATE_FIELD_CONFIGS: Record<string, TemplateFieldConfig> = {
|
||||
previewTitle: 'پیشنمایش راهنما',
|
||||
placeholder: 'متن راهنمای واریز در مودال شارژ حساب را بنویسید…',
|
||||
hint: 'روی هر متغیر کلیک کنید تا در محل نشانگر اضافه شود. اگر خالی بگذارید، متن پیشفرض اپ استفاده میشود.',
|
||||
legend: 'مقادیر بالا نمونهاند؛ در اپ، نام/کارت/شبا از فیلدهای «نام صاحب حساب واریز»، «شماره کارت واریز» و «شبا واریز» پر میشوند.',
|
||||
legend: 'مقادیر بالا نمونهاند؛ در اپ، نام/کارت/حساب/شبا از فیلدهای مربوطه پر میشوند.',
|
||||
rows: 8,
|
||||
defaultTemplate: DEPOSIT_GUIDE_DEFAULT,
|
||||
variableGroups: [
|
||||
@@ -192,6 +192,7 @@ export const TEMPLATE_FIELD_CONFIGS: Record<string, TemplateFieldConfig> = {
|
||||
items: [
|
||||
{ token: 'نام', label: 'صاحب حساب', help: 'نام صاحب حساب (از فیلد «نام صاحب حساب واریز»)' },
|
||||
{ token: 'کارت', label: 'شماره کارت', help: 'شماره کارت (از فیلد «شماره کارت واریز»)' },
|
||||
{ token: 'حساب', label: 'شماره حساب', help: 'شماره حساب (از فیلد «شماره حساب واریز»)' },
|
||||
{ token: 'شبا', label: 'شماره شبا', help: 'شماره شبا (از فیلد «شبا واریز»)' },
|
||||
],
|
||||
},
|
||||
@@ -199,6 +200,7 @@ export const TEMPLATE_FIELD_CONFIGS: Record<string, TemplateFieldConfig> = {
|
||||
sampleValues: {
|
||||
نام: 'علی رضایی',
|
||||
کارت: '۶۰۳۷-۹۹۷۹-۱۲۳۴-۵۶۷۸',
|
||||
حساب: '۰۱۰۸۱۷۹۰۹۰۰۲',
|
||||
شبا: 'IR۸۲۰۵۴۰۱۰۲۶۸۰۰۲۰۸۱۷۹۰۹۰۰۲',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
v-model:visible="visibleProxy"
|
||||
:width="isMobile ? '94vw' : '32rem'"
|
||||
title="سود چندسطحی معرف"
|
||||
ok-text="ذخیره"
|
||||
:loading="loading"
|
||||
@ok="submit"
|
||||
@close="close"
|
||||
>
|
||||
<div class="flex flex-col gap-3">
|
||||
<p class="m-0 text-sm" style="color: var(--admin-text-secondary)">
|
||||
مشتری:
|
||||
<strong class="text-[var(--admin-text)]">{{ customer?.name || '—' }}</strong>
|
||||
</p>
|
||||
<p class="m-0 text-xs" style="color: var(--admin-text-secondary)">
|
||||
درصد از کارمزد سفارش زیرمجموعهها. سطح ۱ یعنی معرف مستقیم، سطح ۲ معرفِ معرف، و همینطور الی آخر.
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div
|
||||
v-for="(item, index) in levels"
|
||||
:key="index"
|
||||
class="flex flex-wrap items-end gap-2"
|
||||
>
|
||||
<BasicInput
|
||||
v-model:value="item.level"
|
||||
type="number"
|
||||
class="min-w-28 flex-1"
|
||||
:addon-after="Number(item.level) === 0 ? 'سطح (جدید)' : 'سطح'"
|
||||
/>
|
||||
<BasicInput
|
||||
v-model:value="item.present"
|
||||
type="number"
|
||||
class="min-w-28 flex-1"
|
||||
addon-after="درصد سود"
|
||||
/>
|
||||
<BaseButton size="small" type="default" danger @click="removeLevel(index)">
|
||||
حذف
|
||||
</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BaseButton type="dashed" class="!w-full" icon="vuesax-linear:add" @click="addLevel">
|
||||
افزودن سطح
|
||||
</BaseButton>
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { message } from 'ant-design-vue'
|
||||
import BasicModal from '@/components/BasicModal.vue'
|
||||
import BasicInput from '@/components/BasicInput.vue'
|
||||
import { updateCustomer } from '@/api/customer'
|
||||
import type { Customer, ProfitByLevel } from '@/model/customer'
|
||||
import { isMobile } from '@core/utils/is'
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
customer: Customer | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', value: boolean): void
|
||||
(e: 'success'): void
|
||||
}>()
|
||||
|
||||
const loading = ref(false)
|
||||
const levels = ref<ProfitByLevel[]>([])
|
||||
|
||||
const visibleProxy = computed({
|
||||
get: () => props.visible,
|
||||
set: (value: boolean) => emit('update:visible', value),
|
||||
})
|
||||
|
||||
function normalizeLevels(raw: unknown): ProfitByLevel[] {
|
||||
if (!Array.isArray(raw)) return []
|
||||
return raw
|
||||
.map((row) => {
|
||||
if (Array.isArray(row)) {
|
||||
return { level: Number(row[0] ?? 0), present: Number(row[1] ?? 0) }
|
||||
}
|
||||
const item = row as ProfitByLevel
|
||||
return {
|
||||
level: Number(item?.level ?? 0),
|
||||
present: Number(item?.present ?? 0),
|
||||
}
|
||||
})
|
||||
.filter((row) => Number.isFinite(row.level) && Number.isFinite(row.present))
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [props.visible, props.customer] as const,
|
||||
([visible]) => {
|
||||
if (!visible) return
|
||||
const fromCustomer = normalizeLevels(props.customer?.profit_amount_by_lvl)
|
||||
levels.value = fromCustomer.length
|
||||
? cloneDeep(fromCustomer)
|
||||
: [{ level: 1, present: 0 }]
|
||||
},
|
||||
)
|
||||
|
||||
function addLevel() {
|
||||
const nextLevel =
|
||||
levels.value.reduce((max, row) => Math.max(max, Number(row.level) || 0), 0) + 1
|
||||
levels.value.push({ level: nextLevel, present: 0 })
|
||||
}
|
||||
|
||||
function removeLevel(index: number) {
|
||||
levels.value.splice(index, 1)
|
||||
}
|
||||
|
||||
function close() {
|
||||
visibleProxy.value = false
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
if (!props.customer?.id) return
|
||||
|
||||
const payload = levels.value
|
||||
.map((row) => ({
|
||||
level: Number(row.level) || 0,
|
||||
present: Number(row.present) || 0,
|
||||
}))
|
||||
.filter((row) => row.level > 0 && row.present > 0)
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
await updateCustomer(props.customer.id, {
|
||||
profit_amount_by_lvl: payload,
|
||||
} as Customer)
|
||||
message.success('درصدهای سود سطح ذخیره شد.')
|
||||
emit('success')
|
||||
close()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -30,6 +30,7 @@
|
||||
@confirmUser="forwardAndClose('confirmUser', $event)"
|
||||
@sendSms="forwardAndClose('sendSms', $event)"
|
||||
@editAccounting="forwardAndClose('editAccounting', $event)"
|
||||
@levelProfit="forwardAndClose('levelProfit', $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -61,6 +62,7 @@ const emit = defineEmits<{
|
||||
(e: 'confirmUser', item: Customer): void
|
||||
(e: 'sendSms', item: Customer): void
|
||||
(e: 'editAccounting', item: Customer): void
|
||||
(e: 'levelProfit', item: Customer): void
|
||||
}>()
|
||||
|
||||
const { sheetVisible, selectedItem, openSheet, syncSelectedItem } = useMobileDetailSheet<Customer>()
|
||||
@@ -75,6 +77,7 @@ type SheetAction =
|
||||
| 'confirmUser'
|
||||
| 'sendSms'
|
||||
| 'editAccounting'
|
||||
| 'levelProfit'
|
||||
|
||||
function forward(action: SheetAction, item: Customer) {
|
||||
emit(action, item)
|
||||
|
||||
@@ -53,6 +53,15 @@
|
||||
<BaseButton size="small" type="default" icon="vuesax-linear:edit" @click="closeAndEmit('edit', row)">
|
||||
ویرایش
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="customerLevelProfitEnabled"
|
||||
size="small"
|
||||
type="default"
|
||||
icon="vuesax-linear:hierarchy-2"
|
||||
@click="closeAndEmit('levelProfit', row)"
|
||||
>
|
||||
سود چندسطحی
|
||||
</BaseButton>
|
||||
<BaseButton size="small" type="default" icon="vuesax-linear:archive-tick" @click="closeAndEmit('archive', row)">
|
||||
بایگانی
|
||||
</BaseButton>
|
||||
@@ -121,6 +130,7 @@ import CustomerWalletBalancePanel from '@/components/customer/CustomerWalletBala
|
||||
import {
|
||||
accountingProviderSetting,
|
||||
customerDirectSmsEnabledSetting,
|
||||
customerLevelProfitEnabledSetting,
|
||||
initAccountingSettingsFromApi
|
||||
} from '@/utils/config'
|
||||
import { displayAccountingCode } from '@/utils/accountingCode'
|
||||
@@ -142,10 +152,12 @@ const emit = defineEmits<{
|
||||
(e: 'confirmUser', item: Customer): void
|
||||
(e: 'sendSms', item: Customer): void
|
||||
(e: 'editAccounting', item: Customer): void
|
||||
(e: 'levelProfit', item: Customer): void
|
||||
}>()
|
||||
|
||||
const chargeTargets = ref<ChargeTarget[]>([])
|
||||
const customerDirectSmsEnabled = customerDirectSmsEnabledSetting
|
||||
const customerLevelProfitEnabled = customerLevelProfitEnabledSetting
|
||||
|
||||
const accountingCodeLabel = computed(() => {
|
||||
const provider = accountingProviderSetting.value
|
||||
|
||||
@@ -108,6 +108,15 @@
|
||||
<template #title><span>ویرایش</span></template>
|
||||
<Icon icon="vuesax-linear:edit" color="#4572E9" />
|
||||
</a-tooltip>
|
||||
<a-tooltip
|
||||
v-if="customerLevelProfitEnabled"
|
||||
placement="bottom"
|
||||
class="cursor-pointer"
|
||||
@click="openLevelProfit(record)"
|
||||
>
|
||||
<template #title><span>سود چندسطحی معرف</span></template>
|
||||
<Icon icon="vuesax-linear:hierarchy-2" color="#ca8a04" />
|
||||
</a-tooltip>
|
||||
<a-tooltip
|
||||
:key="record.trade_active"
|
||||
placement="bottom"
|
||||
@@ -157,11 +166,18 @@
|
||||
@confirmUser="openConfirmUser"
|
||||
@sendSms="openDirectSms"
|
||||
@editAccounting="openAccountingCodeEdit"
|
||||
@levelProfit="openLevelProfit"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<CustomerDirectSmsModal v-model:visible="directSmsVisible" :customer="directSmsCustomer" />
|
||||
|
||||
<CustomerLevelProfitModal
|
||||
v-model:visible="levelProfitVisible"
|
||||
:customer="levelProfitCustomer"
|
||||
@success="fetch"
|
||||
/>
|
||||
|
||||
<CustomerAccountingCodeModal
|
||||
v-model:visible="accountingCodeVisible"
|
||||
:customer="accountingCodeCustomer"
|
||||
@@ -234,6 +250,7 @@ import {
|
||||
import { buildCustomerColumns } from '@/pages/menuPages/customers/base/hooks/customerColumns'
|
||||
import CustomerMobileCardList from '@/pages/menuPages/customers/base/components/CustomerMobileCardList.vue'
|
||||
import CustomerDirectSmsModal from '@/pages/menuPages/customers/base/components/CustomerDirectSmsModal.vue'
|
||||
import CustomerLevelProfitModal from '@/pages/menuPages/customers/base/components/CustomerLevelProfitModal.vue'
|
||||
import CustomerAccountingCodeModal from '@/pages/menuPages/customers/base/components/CustomerAccountingCodeModal.vue'
|
||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
import useBaseTable from '@core/components/BaseTable/hooks/useBaseTable'
|
||||
@@ -251,6 +268,7 @@ import {
|
||||
pargarEnabledSetting,
|
||||
accountingProviderSetting,
|
||||
customerDirectSmsEnabledSetting,
|
||||
customerLevelProfitEnabledSetting,
|
||||
initAccountingSettingsFromApi,
|
||||
initWalletSettingsFromApi
|
||||
} from '@/utils/config'
|
||||
@@ -272,6 +290,9 @@ const pargarRegisterVisible = ref(false)
|
||||
const pargarCustomer = ref<Customer>()
|
||||
const pargarEnabled = pargarEnabledSetting
|
||||
const customerDirectSmsEnabled = customerDirectSmsEnabledSetting
|
||||
const customerLevelProfitEnabled = customerLevelProfitEnabledSetting
|
||||
const levelProfitVisible = ref(false)
|
||||
const levelProfitCustomer = ref<Customer | null>(null)
|
||||
const accountingCodeVisible = ref(false)
|
||||
const accountingCodeCustomer = ref<Customer | null>(null)
|
||||
const accountingEnabled = computed(() => {
|
||||
@@ -329,6 +350,11 @@ function openDirectSms(user: Customer) {
|
||||
directSmsVisible.value = true
|
||||
}
|
||||
|
||||
function openLevelProfit(user: Customer) {
|
||||
levelProfitCustomer.value = user
|
||||
levelProfitVisible.value = true
|
||||
}
|
||||
|
||||
async function changeCustomerActivationFunction(id: number) {
|
||||
try {
|
||||
loading.value = true
|
||||
|
||||
@@ -1707,7 +1707,7 @@ export const bootstrapAdminChat = async (
|
||||
bootstrapPromise = (async () => {
|
||||
try {
|
||||
void postAdminChatEnsureWebhook().catch((error) => {
|
||||
console.error('admin chat ensure webhook failed:', error)
|
||||
console.warn('admin chat ensure webhook failed:', error)
|
||||
})
|
||||
|
||||
await fetchAdminRooms()
|
||||
|
||||
@@ -49,6 +49,9 @@ export const conditionalOrderEnabledSetting = ref(false)
|
||||
/** reactive — قلک per-product در اپ مشتری */
|
||||
export const productFundsEnabledSetting = ref(false)
|
||||
|
||||
/** reactive — سود چندسطحی معرف در لیست مشتریان */
|
||||
export const customerLevelProfitEnabledSetting = ref(false)
|
||||
|
||||
/** reactive — منو و UI هشدار قیمت */
|
||||
export const priceTriggerEnabledSetting = ref(false)
|
||||
|
||||
@@ -154,6 +157,10 @@ export function setProductFundsEnabledFromSettings(value: boolean): void {
|
||||
productFundsEnabledSetting.value = value
|
||||
}
|
||||
|
||||
export function setCustomerLevelProfitEnabledFromSettings(value: boolean): void {
|
||||
customerLevelProfitEnabledSetting.value = value
|
||||
}
|
||||
|
||||
export function setPriceTriggerEnabledFromSettings(value: boolean): void {
|
||||
priceTriggerEnabledSetting.value = value
|
||||
}
|
||||
@@ -257,6 +264,13 @@ export function applyProductFundsEnabledFromRows(
|
||||
if (row) setProductFundsEnabledFromSettings(isSwitchOn(row.value))
|
||||
}
|
||||
|
||||
export function applyCustomerLevelProfitEnabledFromRows(
|
||||
rows: Array<{ key?: string; value?: string | null }>
|
||||
) {
|
||||
const row = rows.find((item) => item.key === 'enable_customer_level_profit')
|
||||
if (row) setCustomerLevelProfitEnabledFromSettings(isSwitchOn(row.value))
|
||||
}
|
||||
|
||||
export function applyPriceTriggerEnabledFromRows(
|
||||
rows: Array<{ key?: string; value?: string | null }>
|
||||
) {
|
||||
@@ -305,6 +319,7 @@ async function bootstrapSettingsFromApi(): Promise<void> {
|
||||
applyCustomerDirectSmsFromRows(list)
|
||||
applyConditionalOrderEnabledFromRows(list)
|
||||
applyProductFundsEnabledFromRows(list)
|
||||
applyCustomerLevelProfitEnabledFromRows(list)
|
||||
applyPriceTriggerEnabledFromRows(list)
|
||||
applyAppNotificationEnabledFromRows(list)
|
||||
applySupportChatMenuEnabledFromRows(list)
|
||||
|
||||
Reference in New Issue
Block a user