Files
boursecu_admin/src/utils/config.ts
T
safavimohadeseh78 88271dba2a feat(customers): add Digipay installment admin section
Wire routes, settings groups, page access, and customer UI for installment management.
2026-10-21 03:38:59 -04:00

538 lines
19 KiB
TypeScript

import { ref } from 'vue'
import { setCachedMainMetal } from '@/utils/metalLabels'
export type AccountingProvider = 'none' | 'pargar' | 'tahesab' | 'zarin' | 'shayegan'
export function getConfigApp(key: string) {
const config = window.__APP_CONFIG__ ? window.__APP_CONFIG__.user : {}
if (config) {
return config[key]
}
return null
}
/** true اگر ui_config یا app_ui_config در get_user مقدار داشته باشد */
export function hasAppUiConfig(): boolean {
const cfg = getConfigApp('ui_config') ?? getConfigApp('app_ui_config')
if (cfg == null) return false
if (typeof cfg === 'string') return cfg.trim().length > 0
if (Array.isArray(cfg)) return cfg.length > 0
if (typeof cfg === 'object') return Object.keys(cfg as object).length > 0
return Boolean(cfg)
}
/** true اگر get_user → ui_variant برابر modular باشد (بنرهای تم اپ) */
export function isModularUiVariant(): boolean {
return String(getConfigApp('ui_variant') ?? '')
.trim()
.toLowerCase() === 'modular'
}
let storeModeFromSettings: boolean | null = null
let settingsBootstrapped = false
/** reactive — برای فیلتر منوی «بنرها» در پیکربندی */
export const bannerEnabledSetting = ref(false)
/** reactive — برای فیلتر منوی «سایت‌های ری‌گیری» در پیکربندی */
export const trackingSystemsEnabledSetting = ref(false)
/** reactive — نمایش UI ته‌حساب در حسابداری و ... */
export const tahesabEnabledSetting = ref(false)
/** reactive — نمایش UI زرین در حسابداری و ... */
export const zarinEnabledSetting = ref(false)
/** reactive — نمایش UI پرگار در حسابداری و ... */
export const pargarEnabledSetting = ref(false)
/** reactive — نمایش UI شایگان در حسابداری و ... */
export const shayeganEnabledSetting = ref(false)
/** reactive — دکمه پیامک تکی در لیست مشتریان */
export const customerDirectSmsEnabledSetting = ref(false)
/** reactive — منو و UI سفارش شرطی (ادمین + کنترل‌های مشتری) */
export const conditionalOrderEnabledSetting = ref(false)
/** reactive — منوی اتوماسیون در تنظیمات ادمین */
export const automationEnabledSetting = ref(false)
/** reactive — قلک per-product در اپ مشتری */
export const productFundsEnabledSetting = ref(false)
/** reactive — سود چندسطحی معرف در لیست مشتریان */
export const customerLevelProfitEnabledSetting = ref(false)
/** reactive — منو و UI هشدار قیمت */
export const priceTriggerEnabledSetting = ref(false)
/** reactive — منوی کارت هدیه ادمین (همان has_page_gift_card اپ کاربر) */
export const giftCardEnabledSetting = ref(false)
/** reactive — دکمه ارسال پیامک گروهی در صفحه پیامک‌ها */
export const groupSmsEnabledSetting = ref(false)
/** reactive — زیرمنوی قیمت ویژه مشتری */
export const customerSpecialPricingEnabledSetting = ref(false)
/** reactive — زیرمنوی اعتبار طلایی در مشتریان */
export const goldCreditEnabledSetting = ref(false)
/** reactive — زیرمنوی خرید اقساطی دیجی‌پی */
export const digipayInstallmentEnabledSetting = ref(false)
/** reactive — منو و زنگوله اعلان داخل اپ */
export const appNotificationEnabledSetting = ref(true)
/** reactive — منبع قیمت فعال (montzar / zaarbox / main_product) */
export const priceProviderSetting = ref('')
/** reactive — منوی افقی / دکمه «چت پشتیبانی» */
export const supportChatMenuEnabledSetting = ref(false)
/** reactive — سوییچ دیپلوی show_to_users_chat (برای مخفی کردن has_chat در تنظیمات عادی) */
export const showToUsersChatSetting = ref(false)
/** reactive — منوی تنظیمات وبسایت وقتی has_landing روشن است */
export const hasLandingSetting = ref(false)
/** reactive — سوییچ دیپلوی price_channel_access (گروه کانال در تنظیمات عادی) */
export const priceChannelAccessSetting = ref(false)
export const accountingProviderSetting = ref<AccountingProvider>('none')
let tahesabEnabledFromSettings: boolean | null = null
let zarinEnabledFromSettings: boolean | null = null
let pargarEnabledFromSettings: boolean | null = null
let shayeganEnabledFromSettings: boolean | null = null
let customerDirectSmsFromSettings: boolean | null = null
let accountingProviderFromSettings: AccountingProvider | null = null
function isSwitchOn(value: string | number | boolean | undefined | null): boolean {
if (value === true || value === 1) return true
const v = String(value ?? '')
.trim()
.toLowerCase()
return v === 'true' || v === '1' || v === 'yes' || v === 'activate'
}
function normalizeAccountingProvider(value: string | undefined | null): AccountingProvider {
const v = (value ?? '').trim().toLowerCase()
if (v === 'pargar' || v === 'tahesab' || v === 'zarin' || v === 'shayegan') return v
return 'none'
}
/** بورس مس: UI حسابداری همیشه شایگان — settings/legacy نادیده گرفته می‌شود. */
function resolveAccountingProviderFromRows(
_list: Array<{ key?: string; value?: string | null }>
): AccountingProvider {
return 'shayegan'
}
export function applyAccountingProviderFromRows(
list: Array<{ key?: string; value?: string | null }>
): void {
const provider = resolveAccountingProviderFromRows(list)
accountingProviderFromSettings = provider
accountingProviderSetting.value = provider
setTahesabEnabledFromSettings(provider === 'tahesab')
setZarinEnabledFromSettings(provider === 'zarin')
setPargarEnabledFromSettings(provider === 'pargar')
setShayeganEnabledFromSettings(provider === 'shayegan')
}
export function setStoreModeFromSettings(value: boolean): void {
storeModeFromSettings = value
}
export function setBannerEnabledFromSettings(value: boolean): void {
bannerEnabledSetting.value = value
}
export function setTrackingSystemsEnabledFromSettings(value: boolean): void {
trackingSystemsEnabledSetting.value = value
}
export function setTahesabEnabledFromSettings(value: boolean): void {
tahesabEnabledFromSettings = value
tahesabEnabledSetting.value = value
}
export function setZarinEnabledFromSettings(value: boolean): void {
zarinEnabledFromSettings = value
zarinEnabledSetting.value = value
}
export function setPargarEnabledFromSettings(value: boolean): void {
pargarEnabledFromSettings = value
pargarEnabledSetting.value = value
}
export function setShayeganEnabledFromSettings(value: boolean): void {
shayeganEnabledFromSettings = value
shayeganEnabledSetting.value = value
}
export function setCustomerDirectSmsEnabledFromSettings(value: boolean): void {
customerDirectSmsFromSettings = value
customerDirectSmsEnabledSetting.value = value
}
export function setGroupSmsEnabledFromSettings(value: boolean): void {
groupSmsEnabledSetting.value = value
}
export function setCustomerSpecialPricingEnabledFromSettings(value: boolean): void {
customerSpecialPricingEnabledSetting.value = value
}
export function setDigipayInstallmentEnabledFromSettings(value: boolean): void {
digipayInstallmentEnabledSetting.value = value
}
export function setGoldCreditEnabledFromSettings(value: boolean): void {
goldCreditEnabledSetting.value = value
}
export function setConditionalOrderEnabledFromSettings(value: boolean): void {
conditionalOrderEnabledSetting.value = value
}
export function setAutomationEnabledFromSettings(value: boolean): void {
automationEnabledSetting.value = value
}
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
}
export function setGiftCardEnabledFromSettings(value: boolean): void {
giftCardEnabledSetting.value = value
}
export function setAppNotificationEnabledFromSettings(value: boolean): void {
appNotificationEnabledSetting.value = value
}
export function setSupportChatMenuEnabledFromSettings(value: boolean): void {
supportChatMenuEnabledSetting.value = value
}
export function setShowToUsersChatFromSettings(value: boolean): void {
showToUsersChatSetting.value = value
}
export function setHasLandingFromSettings(value: boolean): void {
hasLandingSetting.value = value
}
export function setPriceChannelAccessFromSettings(value: boolean): void {
priceChannelAccessSetting.value = value
}
let lastShowToUsersChat = ''
let lastHasChat = ''
let lastChatApi = ''
/** منوی چت: show_to_users_chat + has_chat + chat_api */
export function resolveSupportChatMenuEnabled(
getValue: (key: string) => string | undefined | null
): boolean {
const api = String(getValue('chat_api') ?? '').trim()
return (
isSwitchOn(getValue('show_to_users_chat')) &&
isSwitchOn(getValue('has_chat')) &&
Boolean(api) &&
api.toLowerCase() !== 'null'
)
}
export function applySupportChatMenuEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
): void {
let touched = false
for (const row of rows) {
const key = String(row.key ?? '')
if (key === 'show_to_users_chat') {
lastShowToUsersChat = String(row.value ?? '')
touched = true
} else if (key === 'has_chat') {
lastHasChat = String(row.value ?? '')
touched = true
} else if (key === 'chat_api') {
lastChatApi = String(row.value ?? '')
touched = true
}
}
if (!touched) return
setShowToUsersChatFromSettings(isSwitchOn(lastShowToUsersChat))
setSupportChatMenuEnabledFromSettings(
resolveSupportChatMenuEnabled((key) => {
if (key === 'show_to_users_chat') return lastShowToUsersChat
if (key === 'has_chat') return lastHasChat
if (key === 'chat_api') return lastChatApi
return undefined
})
)
}
export function setPriceProviderFromSettings(value?: string | null): void {
priceProviderSetting.value = (value ?? '').trim().toLowerCase()
}
/** فقط وقتی کلید در rows باشد آپدیت می‌شود — پاسخ ناقص (editable/system) فلگ قبلی را پاک نکند */
export function applyBannerEnabledFromRows(rows: Array<{ key?: string; value?: string | null }>) {
const row = rows.find((item) => item.key === 'banner_enabled')
if (row) setBannerEnabledFromSettings(isSwitchOn(row.value))
}
export function applyTrackingSystemsEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'tracking_systems_enabled')
if (row) setTrackingSystemsEnabledFromSettings(isSwitchOn(row.value))
}
export function applyCustomerDirectSmsFromRows(rows: Array<{ key?: string; value?: string | null }>) {
const row = rows.find((item) => item.key === 'customer_direct_sms')
if (row) setCustomerDirectSmsEnabledFromSettings(isSwitchOn(row.value))
}
export function applyGroupSmsFromRows(rows: Array<{ key?: string; value?: string | null }>) {
const row = rows.find((item) => item.key === 'group_sms')
if (row) setGroupSmsEnabledFromSettings(isSwitchOn(row.value))
}
export function applyCustomerSpecialPricingFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'customer_special_pricing')
if (row) setCustomerSpecialPricingEnabledFromSettings(isSwitchOn(row.value))
}
export function applyDigipayInstallmentEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'enable_digipay_installment')
if (row) setDigipayInstallmentEnabledFromSettings(isSwitchOn(row.value))
}
export function applyGoldCreditEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'enable_gold_credit')
if (row) setGoldCreditEnabledFromSettings(isSwitchOn(row.value))
}
/** بعد از همگام‌سازی سوپرادمین — bootstrap بعدی دوباره از API می‌خواند */
export function invalidateSettingsBootstrap(): void {
settingsBootstrapped = false
}
/**
* اعمال مستقیم ۱۶ دسترسی سوپرادمین روی فلگ‌های منو/UI
* (پاسخ refresh-superadmin.items یا ردیف‌های get_settings).
*/
export function applySuperAdminAccessFlagsFromItems(
items: Record<string, string> | Array<{ key?: string; value?: string | null }>
): void {
const rows = Array.isArray(items)
? items
: Object.entries(items).map(([key, value]) => ({ key, value }))
applyCustomerDirectSmsFromRows(rows)
applyGroupSmsFromRows(rows)
applyCustomerSpecialPricingFromRows(rows)
applyGoldCreditEnabledFromRows(rows)
applyDigipayInstallmentEnabledFromRows(rows)
applyConditionalOrderEnabledFromRows(rows)
applyAutomationEnabledFromRows(rows)
applyProductFundsEnabledFromRows(rows)
applyCustomerLevelProfitEnabledFromRows(rows)
applyPriceTriggerEnabledFromRows(rows)
applyGiftCardEnabledFromRows(rows)
applyAppNotificationEnabledFromRows(rows)
applySupportChatMenuEnabledFromRows(rows)
applyHasLandingFromRows(rows)
}
export function applyConditionalOrderEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'enable_conditional_order')
if (row) setConditionalOrderEnabledFromSettings(isSwitchOn(row.value))
}
export function applyAutomationEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'enable_automation')
if (row) setAutomationEnabledFromSettings(isSwitchOn(row.value))
}
export function applyProductFundsEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'enable_product_funds')
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 }>
) {
const row = rows.find((item) => item.key === 'has_page_price_trigger')
if (row) setPriceTriggerEnabledFromSettings(isSwitchOn(row.value))
}
export function applyGiftCardEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'has_page_gift_card')
if (row) setGiftCardEnabledFromSettings(isSwitchOn(row.value))
}
export function applyAppNotificationEnabledFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'has_page_notification')
if (row) setAppNotificationEnabledFromSettings(isSwitchOn(row.value))
}
export function applyHasLandingFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'has_landing')
if (row) setHasLandingFromSettings(isSwitchOn(row.value))
}
export function applyPriceProviderFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'price_provider')
if (row) {
setPriceProviderFromSettings(row.value)
}
}
export function applyPriceChannelAccessFromRows(
rows: Array<{ key?: string; value?: string | null }>
) {
const row = rows.find((item) => item.key === 'price_channel_access')
if (row) setPriceChannelAccessFromSettings(isSwitchOn(row.value))
}
async function bootstrapSettingsFromApi(): Promise<void> {
if (settingsBootstrapped) return
try {
const { getConfiguration } = await import('@/api/configuration')
const { parseMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
const rows = await getConfiguration()
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')
const mainMetalRow = list.find((item) => item.key === 'main_metal')
storeModeFromSettings = isStoreRow ? isSwitchOn(isStoreRow.value) : false
applyAccountingProviderFromRows(list)
applyBannerEnabledFromRows(list)
applyTrackingSystemsEnabledFromRows(list)
applyCustomerDirectSmsFromRows(list)
applyGroupSmsFromRows(list)
applyCustomerSpecialPricingFromRows(list)
applyGoldCreditEnabledFromRows(list)
applyDigipayInstallmentEnabledFromRows(list)
applyConditionalOrderEnabledFromRows(list)
applyAutomationEnabledFromRows(list)
applyProductFundsEnabledFromRows(list)
applyCustomerLevelProfitEnabledFromRows(list)
applyPriceTriggerEnabledFromRows(list)
applyGiftCardEnabledFromRows(list)
applyAppNotificationEnabledFromRows(list)
applySupportChatMenuEnabledFromRows(list)
applyHasLandingFromRows(list)
applyPriceProviderFromRows(list)
applyPriceChannelAccessFromRows(list)
setCachedMainMetal(mainMetalRow?.value)
const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
setCachedMainWalletProductIds(parseMainWalletProductIds(mainWalletRow?.value))
settingsBootstrapped = true
} catch {
// Allow retry on next init* call — do not lock flags to false forever.
}
}
/** is_store و main_wallet_products از API تنظیمات — نه از get_user */
export async function initStoreModeFromSettings(): Promise<boolean> {
if (storeModeFromSettings !== null) return storeModeFromSettings
await bootstrapSettingsFromApi()
return storeModeFromSettings === true
}
export async function initWalletSettingsFromApi(): Promise<void> {
await bootstrapSettingsFromApi()
}
export function isStoreApp(): boolean {
return storeModeFromSettings === true
}
export function isTahesabEnabled(): boolean {
return tahesabEnabledFromSettings === true
}
export function isZarinEnabled(): boolean {
return zarinEnabledFromSettings === true
}
export function isPargarEnabled(): boolean {
return pargarEnabledFromSettings === true
}
export function isShayeganEnabled(): boolean {
return shayeganEnabledFromSettings === true
}
export function getAccountingProvider(): AccountingProvider {
return accountingProviderFromSettings ?? 'none'
}
/** بارگذاری accounting_provider و فلگ‌های UI */
export async function initAccountingSettingsFromApi(): Promise<AccountingProvider> {
if (accountingProviderFromSettings !== null) return accountingProviderFromSettings
await bootstrapSettingsFromApi()
return accountingProviderFromSettings ?? 'none'
}
/** @deprecated از initAccountingSettingsFromApi استفاده کنید */
export async function initTahesabSettingFromApi(): Promise<boolean> {
await initAccountingSettingsFromApi()
return tahesabEnabledFromSettings === true
}
/** @deprecated از initAccountingSettingsFromApi استفاده کنید */
export async function initPargarSettingFromApi(): Promise<boolean> {
await initAccountingSettingsFromApi()
return pargarEnabledFromSettings === true
}