feat: add MongoDB search method, endpoints, and settings module
deploy-chabokan / deploy (push) Canceled after 0s
deploy-chabokan / deploy (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
const catchAsync = require('../../globalErrorHandler/catchAsync')
|
||||
const settingService = require('./settingService')
|
||||
|
||||
exports.getSearchSettings = catchAsync(async (req, res, next) => {
|
||||
const settings = await settingService.getSearchSettings()
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: settings.length,
|
||||
data: settings,
|
||||
})
|
||||
})
|
||||
|
||||
exports.getSearchSettingByPage = catchAsync(async (req, res, next) => {
|
||||
const setting = await settingService.getSearchSettingByPage(req.params.pageKey)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
data: setting,
|
||||
})
|
||||
})
|
||||
|
||||
exports.updateSearchSetting = catchAsync(async (req, res, next) => {
|
||||
const { searchMethod, extraConfig } = req.body
|
||||
const setting = await settingService.setSearchMethod(req.params.pageKey, searchMethod, extraConfig)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
data: setting,
|
||||
})
|
||||
})
|
||||
|
||||
exports.bulkUpdateSearchSettings = catchAsync(async (req, res, next) => {
|
||||
const { settings } = req.body
|
||||
const results = await settingService.bulkUpdateSearchSettings(settings)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: results.length,
|
||||
data: results,
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,46 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const settingSchema = new mongoose.Schema(
|
||||
{
|
||||
key: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
trim: true,
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
default: 'search',
|
||||
},
|
||||
pageKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
searchMethod: {
|
||||
type: String,
|
||||
enum: ['typesense', 'mongo'],
|
||||
default: 'mongo',
|
||||
},
|
||||
extraConfig: {
|
||||
type: mongoose.Schema.Types.Mixed,
|
||||
default: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
)
|
||||
|
||||
settingSchema.index({ key: 1 }, { unique: true })
|
||||
settingSchema.index({ pageKey: 1 })
|
||||
|
||||
const Setting = mongoose.model('Setting', settingSchema)
|
||||
module.exports = Setting
|
||||
@@ -0,0 +1,34 @@
|
||||
const express = require('express')
|
||||
const settingController = require('./settingController')
|
||||
const perm = require('../../middlewares/permissionMiddleware')
|
||||
const loginCheck = require('../../middlewares/loginCheck')
|
||||
|
||||
const router = new express.Router()
|
||||
|
||||
router.use(loginCheck.loginProtect)
|
||||
|
||||
router.get(
|
||||
'/search-settings',
|
||||
perm.requires('admindashboard', 'viewdashboard', 'getallpermissions'),
|
||||
settingController.getSearchSettings
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/search-settings/:pageKey',
|
||||
perm.requires('admindashboard', 'viewdashboard', 'getallpermissions'),
|
||||
settingController.getSearchSettingByPage
|
||||
)
|
||||
|
||||
router.put(
|
||||
'/search-settings/:pageKey',
|
||||
perm.requires('admindashboard', 'viewdashboard', 'getallpermissions'),
|
||||
settingController.updateSearchSetting
|
||||
)
|
||||
|
||||
router.put(
|
||||
'/search-settings',
|
||||
perm.requires('admindashboard', 'viewdashboard', 'getallpermissions'),
|
||||
settingController.bulkUpdateSearchSettings
|
||||
)
|
||||
|
||||
module.exports = router
|
||||
@@ -0,0 +1,194 @@
|
||||
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 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
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DEFAULT_SEARCH_PAGES,
|
||||
getSearchSettings,
|
||||
getSearchSettingByPage,
|
||||
setSearchMethod,
|
||||
bulkUpdateSearchSettings,
|
||||
}
|
||||
Reference in New Issue
Block a user