290 lines
10 KiB
JavaScript
290 lines
10 KiB
JavaScript
const Setting = require('./settingModel')
|
|
const AppError = require('../../globalErrorHandler/AppError')
|
|
|
|
const DEFAULT_SEARCH_PAGES = [
|
|
{
|
|
pageKey: 'properties',
|
|
title: 'املاک (Properties)',
|
|
description: 'جستجوی املاک، کد نوسازی، شناسه ملی جغرافیایی، مشخصات سند، مالک و پلاک ثبتی',
|
|
defaultMethod: 'typesense',
|
|
supportedMethods: ['typesense', 'mongo'],
|
|
endpointTypesense: '/api/properties/admin/search',
|
|
endpointMongo: '/api/properties/admin/search-mongo',
|
|
routePath: '/property/list-properties',
|
|
icon: 'pi pi-file',
|
|
},
|
|
{
|
|
pageKey: 'transactions',
|
|
title: 'تراکنشهای املاک (Transactions)',
|
|
description: 'جستجوی تراکنشهای واریز و برداشت، توضیحات، نام کاربر و ملک مرتبط',
|
|
defaultMethod: 'typesense',
|
|
supportedMethods: ['typesense', 'mongo'],
|
|
endpointTypesense: '/api/transactions/admin/search',
|
|
endpointMongo: '/api/transactions/admin/search-mongo',
|
|
routePath: '/transactions/list-transactions',
|
|
icon: 'pi pi-history',
|
|
},
|
|
{
|
|
pageKey: 'warehouseItems',
|
|
title: 'اقلام انبار (Warehouse Items)',
|
|
description: 'جستجوی اقلام کالا، نام فارسی، نام انگلیسی، کد کالا و دستهبندی',
|
|
defaultMethod: 'mongo',
|
|
supportedMethods: ['mongo', 'typesense'],
|
|
endpointTypesense: '/api/warehouse-items/admin/items',
|
|
endpointMongo: '/api/warehouse-items/admin/items',
|
|
routePath: '/warehouse-items/list',
|
|
icon: 'pi pi-box',
|
|
},
|
|
{
|
|
pageKey: 'warehouses',
|
|
title: 'مکانهای انبار (Warehouses)',
|
|
description: 'جستجوی نام انبار، کد و آدرس انبارها',
|
|
defaultMethod: 'mongo',
|
|
supportedMethods: ['mongo', 'typesense'],
|
|
endpointTypesense: '/api/warehouses/admin/get-all',
|
|
endpointMongo: '/api/warehouses/admin/get-all',
|
|
routePath: '/warehouse-items/warehouses',
|
|
icon: 'pi pi-map',
|
|
},
|
|
{
|
|
pageKey: 'categories',
|
|
title: 'دستهبندیها (Categories)',
|
|
description: 'جستجوی دستهبندیهای املاک بر اساس نام فارسی و انگلیسی',
|
|
defaultMethod: 'mongo',
|
|
supportedMethods: ['mongo', 'typesense'],
|
|
endpointTypesense: '/api/categories/admin/get-all',
|
|
endpointMongo: '/api/categories/admin/get-all',
|
|
routePath: '/categories/list-categories',
|
|
icon: 'pi pi-th-large',
|
|
},
|
|
{
|
|
pageKey: 'users',
|
|
title: 'کاربران (Users)',
|
|
description: 'جستجوی کاربران سیستم بر اساس نام، ایمیل و نقش کاربری',
|
|
defaultMethod: 'mongo',
|
|
supportedMethods: ['mongo', 'typesense'],
|
|
endpointTypesense: '/api/users/admin/get-all',
|
|
endpointMongo: '/api/users/admin/get-all',
|
|
routePath: '/users/list-users',
|
|
icon: 'pi pi-users',
|
|
},
|
|
{
|
|
pageKey: 'roles',
|
|
title: 'نقشها و دسترسیها (Roles)',
|
|
description: 'جستجوی نقشها بر اساس عنوان فارسی و انگلیسی',
|
|
defaultMethod: 'mongo',
|
|
supportedMethods: ['mongo', 'typesense'],
|
|
endpointTypesense: '/api/roles/admin/get-all',
|
|
endpointMongo: '/api/roles/admin/get-all',
|
|
routePath: '/roles/list-roles',
|
|
icon: 'pi pi-shield',
|
|
},
|
|
]
|
|
|
|
const getSearchSettings = async () => {
|
|
const dbSettings = await Setting.find({ category: 'search' }).lean()
|
|
const dbSettingsMap = new Map()
|
|
|
|
dbSettings.forEach((s) => {
|
|
dbSettingsMap.set(s.pageKey, s)
|
|
})
|
|
|
|
return DEFAULT_SEARCH_PAGES.map((pageDef) => {
|
|
const dbRecord = dbSettingsMap.get(pageDef.pageKey)
|
|
if (dbRecord) {
|
|
return {
|
|
...pageDef,
|
|
_id: dbRecord._id,
|
|
searchMethod: dbRecord.searchMethod || pageDef.defaultMethod,
|
|
isPersisted: true,
|
|
updatedAt: dbRecord.updatedAt,
|
|
createdAt: dbRecord.createdAt,
|
|
}
|
|
}
|
|
return {
|
|
...pageDef,
|
|
searchMethod: pageDef.defaultMethod,
|
|
isPersisted: false,
|
|
}
|
|
})
|
|
}
|
|
|
|
const getSearchSettingByPage = async (pageKey) => {
|
|
const pageDef = DEFAULT_SEARCH_PAGES.find((p) => p.pageKey === pageKey)
|
|
if (!pageDef) {
|
|
throw new AppError('PageNotFound', 404, { message: `Page key ${pageKey} not found in search configurations` })
|
|
}
|
|
|
|
const dbRecord = await Setting.findOne({ pageKey, category: 'search' }).lean()
|
|
if (dbRecord) {
|
|
return {
|
|
...pageDef,
|
|
_id: dbRecord._id,
|
|
searchMethod: dbRecord.searchMethod || pageDef.defaultMethod,
|
|
isPersisted: true,
|
|
updatedAt: dbRecord.updatedAt,
|
|
createdAt: dbRecord.createdAt,
|
|
}
|
|
}
|
|
|
|
return {
|
|
...pageDef,
|
|
searchMethod: pageDef.defaultMethod,
|
|
isPersisted: false,
|
|
}
|
|
}
|
|
|
|
const setSearchMethod = async (pageKey, searchMethod, extraConfig = {}) => {
|
|
if (!['typesense', 'mongo'].includes(searchMethod)) {
|
|
throw new AppError('InvalidSearchMethod', 400, { message: 'Search method must be either "typesense" or "mongo"' })
|
|
}
|
|
|
|
const pageDef = DEFAULT_SEARCH_PAGES.find((p) => p.pageKey === pageKey) || {
|
|
pageKey,
|
|
title: pageKey,
|
|
description: `Settings for ${pageKey}`,
|
|
defaultMethod: 'mongo',
|
|
}
|
|
|
|
const setting = await Setting.findOneAndUpdate(
|
|
{ pageKey, category: 'search' },
|
|
{
|
|
key: `search_${pageKey}`,
|
|
category: 'search',
|
|
pageKey,
|
|
title: pageDef.title,
|
|
description: pageDef.description,
|
|
searchMethod,
|
|
extraConfig,
|
|
},
|
|
{ upsert: true, new: true, setDefaultsOnInsert: true }
|
|
)
|
|
|
|
return {
|
|
...pageDef,
|
|
_id: setting._id,
|
|
searchMethod: setting.searchMethod,
|
|
isPersisted: true,
|
|
updatedAt: setting.updatedAt,
|
|
createdAt: setting.createdAt,
|
|
}
|
|
}
|
|
|
|
const seederRunner = require('../../seeder/seederRunner')
|
|
|
|
const bulkUpdateSearchSettings = async (settingsArray) => {
|
|
if (!Array.isArray(settingsArray)) {
|
|
throw new AppError('InvalidDataFormat', 400, { message: 'Expected an array of settings' })
|
|
}
|
|
|
|
const results = []
|
|
for (const item of settingsArray) {
|
|
if (item.pageKey && item.searchMethod) {
|
|
const updated = await setSearchMethod(item.pageKey, item.searchMethod, item.extraConfig || {})
|
|
results.push(updated)
|
|
}
|
|
}
|
|
return results
|
|
}
|
|
|
|
const getSeedStatus = async () => {
|
|
const record = await Setting.findOne({ key: 'system_database_seeded' }).lean()
|
|
if (record && record.extraConfig && record.extraConfig.isSeeded) {
|
|
return {
|
|
isSeeded: true,
|
|
seededAt: record.extraConfig.seededAt || record.updatedAt,
|
|
seededBy: record.extraConfig.seededBy || null,
|
|
}
|
|
}
|
|
return {
|
|
isSeeded: false,
|
|
seededAt: null,
|
|
seededBy: null,
|
|
}
|
|
}
|
|
|
|
const seedDatabase = async (userId = null) => {
|
|
const currentStatus = await getSeedStatus()
|
|
if (currentStatus.isSeeded) {
|
|
throw new AppError('DatabaseAlreadySeeded', 400, {
|
|
message: 'پایگاه داده قبلاً مقداردهی شده است و امکان مقداردهی مجدد وجود ندارد.',
|
|
})
|
|
}
|
|
|
|
await seederRunner.run()
|
|
|
|
const record = await Setting.findOneAndUpdate(
|
|
{ key: 'system_database_seeded' },
|
|
{
|
|
key: 'system_database_seeded',
|
|
category: 'system',
|
|
pageKey: 'system_seeder',
|
|
title: 'مقداردهی اولیه پایگاه داده',
|
|
description: 'وضعیت اجرای مقداردهی اولیه دادههای پایه سیستم',
|
|
extraConfig: {
|
|
isSeeded: true,
|
|
seededAt: new Date(),
|
|
seededBy: userId,
|
|
},
|
|
},
|
|
{ upsert: true, new: true, setDefaultsOnInsert: true }
|
|
)
|
|
|
|
return {
|
|
isSeeded: true,
|
|
seededAt: record.extraConfig.seededAt,
|
|
message: 'پایگاه داده با موفقیت مقداردهی اولیه شد.',
|
|
}
|
|
}
|
|
|
|
const getAutoSaveSetting = async () => {
|
|
const record = await Setting.findOne({ key: 'general_autosave' }).lean()
|
|
if (record && record.extraConfig) {
|
|
return {
|
|
enabled: record.extraConfig.enabled !== undefined ? record.extraConfig.enabled : true,
|
|
intervalSeconds: Number(record.extraConfig.intervalSeconds) || 60,
|
|
updatedAt: record.updatedAt,
|
|
}
|
|
}
|
|
return {
|
|
enabled: true,
|
|
intervalSeconds: 60,
|
|
}
|
|
}
|
|
|
|
const updateAutoSaveSetting = async ({ enabled = true, intervalSeconds = 60 }) => {
|
|
const validInterval = Math.max(10, Number(intervalSeconds) || 60)
|
|
const setting = await Setting.findOneAndUpdate(
|
|
{ key: 'general_autosave' },
|
|
{
|
|
key: 'general_autosave',
|
|
category: 'general',
|
|
pageKey: 'general',
|
|
title: 'تنظیمات ذخیره خودکار (Auto-Save Settings)',
|
|
description: 'پیکربندی فعالسازی و فاصله زمانی ذخیره خودکار فرمها',
|
|
extraConfig: {
|
|
enabled: Boolean(enabled),
|
|
intervalSeconds: validInterval,
|
|
},
|
|
},
|
|
{ upsert: true, new: true, setDefaultsOnInsert: true }
|
|
)
|
|
return {
|
|
enabled: setting.extraConfig.enabled,
|
|
intervalSeconds: setting.extraConfig.intervalSeconds,
|
|
updatedAt: setting.updatedAt,
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
DEFAULT_SEARCH_PAGES,
|
|
getSearchSettings,
|
|
getSearchSettingByPage,
|
|
setSearchMethod,
|
|
bulkUpdateSearchSettings,
|
|
getSeedStatus,
|
|
seedDatabase,
|
|
getAutoSaveSetting,
|
|
updateAutoSaveSetting,
|
|
}
|