From 284594c7827b0992d311c569f79492ac8c44e4cc Mon Sep 17 00:00:00 2001 From: Kavehhn174 Date: Wed, 19 Aug 2026 06:49:53 +0330 Subject: [PATCH] feat(seeder): add one-time database seeding endpoint with status tracking --- components/setting/settingController.js | 18 +++++++++ components/setting/settingRoutes.js | 12 ++++++ components/setting/settingService.js | 54 +++++++++++++++++++++++++ seeder/seederRunner.js | 14 ++++++- 4 files changed, 96 insertions(+), 2 deletions(-) diff --git a/components/setting/settingController.js b/components/setting/settingController.js index 1820038..0af9ae5 100644 --- a/components/setting/settingController.js +++ b/components/setting/settingController.js @@ -40,3 +40,21 @@ exports.bulkUpdateSearchSettings = catchAsync(async (req, res, next) => { data: results, }) }) + +exports.getSeedStatus = catchAsync(async (req, res, next) => { + const status = await settingService.getSeedStatus() + + res.status(200).json({ + status: 'success', + data: status, + }) +}) + +exports.seedDatabase = catchAsync(async (req, res, next) => { + const result = await settingService.seedDatabase(req.user?._id) + + res.status(200).json({ + status: 'success', + data: result, + }) +}) diff --git a/components/setting/settingRoutes.js b/components/setting/settingRoutes.js index dec6062..2d8bdcf 100644 --- a/components/setting/settingRoutes.js +++ b/components/setting/settingRoutes.js @@ -31,4 +31,16 @@ router.put( settingController.bulkUpdateSearchSettings ) +router.get( + '/seed-status', + perm.requires('admindashboard', 'viewdashboard', 'getallpermissions'), + settingController.getSeedStatus +) + +router.post( + '/seed-database', + perm.requires('admindashboard', 'viewdashboard', 'getallpermissions'), + settingController.seedDatabase +) + module.exports = router diff --git a/components/setting/settingService.js b/components/setting/settingService.js index d5fb9e5..e023778 100644 --- a/components/setting/settingService.js +++ b/components/setting/settingService.js @@ -170,6 +170,8 @@ const setSearchMethod = async (pageKey, searchMethod, extraConfig = {}) => { } } +const seederRunner = require('../../seeder/seederRunner') + const bulkUpdateSearchSettings = async (settingsArray) => { if (!Array.isArray(settingsArray)) { throw new AppError('InvalidDataFormat', 400, { message: 'Expected an array of settings' }) @@ -185,10 +187,62 @@ const bulkUpdateSearchSettings = async (settingsArray) => { 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: 'پایگاه داده با موفقیت مقداردهی اولیه شد.', + } +} + module.exports = { DEFAULT_SEARCH_PAGES, getSearchSettings, getSearchSettingByPage, setSearchMethod, bulkUpdateSearchSettings, + getSeedStatus, + seedDatabase, } diff --git a/seeder/seederRunner.js b/seeder/seederRunner.js index be543d4..7c11a5e 100644 --- a/seeder/seederRunner.js +++ b/seeder/seederRunner.js @@ -12,6 +12,16 @@ module.exports.run = async () => { await roleSeeder.runSeeder() await featureSeeder.runSeeder() await propertyStatusSeeder.runSeeder() - await propertyService.indexAllProperties() - await transactionService.indexAllTransactions() + + try { + await propertyService.indexAllProperties() + } catch (err) { + console.warn('Typesense property indexing warning during seed:', err.message) + } + + try { + await transactionService.indexAllTransactions() + } catch (err) { + console.warn('Typesense transaction indexing warning during seed:', err.message) + } }