Merge branch 'main' of https://git.profit-planet.partners/DK404/CentralBackend
This commit is contained in:
commit
e86986d40c
@ -17,7 +17,7 @@ class UserStatusController {
|
|||||||
// If no status exists, create one with default values
|
// If no status exists, create one with default values
|
||||||
if (!status) {
|
if (!status) {
|
||||||
logger.info(`[UserStatusController] No status found for userId: ${userId}, creating default status`);
|
logger.info(`[UserStatusController] No status found for userId: ${userId}, creating default status`);
|
||||||
await userStatusRepo.initializeUserStatus(userId, 'inactive');
|
await userStatusRepo.initializeUserStatus(userId, 'pending');
|
||||||
status = await userStatusRepo.getStatusByUserId(userId);
|
status = await userStatusRepo.getStatusByUserId(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
controller/dev/DevManagementController.js
Normal file
34
controller/dev/DevManagementController.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
const DevManagementService = require('../../services/dev/DevManagementService');
|
||||||
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
|
function previewSql(sql, max = 180) {
|
||||||
|
if (!sql) return '';
|
||||||
|
const s = String(sql).replace(/\s+/g, ' ').trim();
|
||||||
|
return s.length > max ? `${s.slice(0, max)}…` : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.importSqlDump = async (req, res) => {
|
||||||
|
try {
|
||||||
|
if (!req.file || !req.file.buffer) {
|
||||||
|
return res.status(400).json({ success: false, error: 'SQL dump file is required' });
|
||||||
|
}
|
||||||
|
const sql = req.file.buffer.toString('utf8');
|
||||||
|
if (!sql.trim()) {
|
||||||
|
return res.status(400).json({ success: false, error: 'SQL dump file is empty' });
|
||||||
|
}
|
||||||
|
const start = Date.now();
|
||||||
|
const { rows, fields } = await DevManagementService.executeDump(sql);
|
||||||
|
const durationMs = Date.now() - start;
|
||||||
|
|
||||||
|
const isMulti = Array.isArray(fields) && fields.length > 0 && Array.isArray(fields[0]);
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
data: { result: rows, isMulti: !!isMulti },
|
||||||
|
meta: { durationMs }
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
logger.error('[DevManagementController.importSqlDump] error', { msg: e?.message, sql: previewSql(req.file?.buffer?.toString('utf8')) });
|
||||||
|
return res.status(500).json({ success: false, error: e?.message || 'SQL execution failed' });
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -54,7 +54,7 @@ if (NODE_ENV === 'development') {
|
|||||||
|
|
||||||
const allowCreateDb = String(process.env.DB_ALLOW_CREATE_DB || 'false').toLowerCase() === 'true';
|
const allowCreateDb = String(process.env.DB_ALLOW_CREATE_DB || 'false').toLowerCase() === 'true';
|
||||||
|
|
||||||
// --- Performance Helpers (added) ---
|
// --- Performance Helpers ---
|
||||||
async function ensureIndex(conn, table, indexName, indexDDL) {
|
async function ensureIndex(conn, table, indexName, indexDDL) {
|
||||||
const [rows] = await conn.query(`SHOW INDEX FROM \`${table}\` WHERE Key_name = ?`, [indexName]);
|
const [rows] = await conn.query(`SHOW INDEX FROM \`${table}\` WHERE Key_name = ?`, [indexName]);
|
||||||
if (!rows.length) {
|
if (!rows.length) {
|
||||||
@ -225,6 +225,23 @@ const createDatabase = async () => {
|
|||||||
`);
|
`);
|
||||||
console.log('✅ Company profiles table created/verified');
|
console.log('✅ Company profiles table created/verified');
|
||||||
|
|
||||||
|
// Ensure registration_number allows NULL if table already existed
|
||||||
|
try {
|
||||||
|
await connection.query(`ALTER TABLE company_profiles MODIFY COLUMN registration_number VARCHAR(255) UNIQUE NULL`);
|
||||||
|
console.log('🔧 Ensured registration_number allows NULL');
|
||||||
|
} catch (e) {
|
||||||
|
console.log('ℹ️ registration_number column already allows NULL or ALTER not required');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure phone columns are nullable if tables already existed
|
||||||
|
try {
|
||||||
|
await connection.query(`ALTER TABLE personal_profiles MODIFY COLUMN phone VARCHAR(255) NULL`);
|
||||||
|
await connection.query(`ALTER TABLE company_profiles MODIFY COLUMN phone VARCHAR(255) NULL`);
|
||||||
|
console.log('🔧 Ensured phone columns are nullable');
|
||||||
|
} catch (e) {
|
||||||
|
console.log('ℹ️ Phone columns already nullable or ALTER not required');
|
||||||
|
}
|
||||||
|
|
||||||
// 4. user_status table: Comprehensive tracking of user verification and completion steps
|
// 4. user_status table: Comprehensive tracking of user verification and completion steps
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS user_status (
|
CREATE TABLE IF NOT EXISTS user_status (
|
||||||
@ -527,6 +544,43 @@ const createDatabase = async () => {
|
|||||||
console.log('✅ News table created/verified');
|
console.log('✅ News table created/verified');
|
||||||
console.log('✅ Referral tokens table created/verified');
|
console.log('✅ Referral tokens table created/verified');
|
||||||
|
|
||||||
|
// Generated label columns (virtual) to display 'unlimited' instead of -1 in UI tools
|
||||||
|
try {
|
||||||
|
await connection.query(`
|
||||||
|
ALTER TABLE referral_tokens
|
||||||
|
ADD COLUMN max_uses_label VARCHAR(20)
|
||||||
|
GENERATED ALWAYS AS (CASE WHEN max_uses = -1 THEN 'unlimited' ELSE CAST(max_uses AS CHAR) END) VIRTUAL
|
||||||
|
`);
|
||||||
|
console.log('🆕 Added virtual column referral_tokens.max_uses_label');
|
||||||
|
} catch (e) {
|
||||||
|
console.log('ℹ️ max_uses_label already exists or cannot add:', e.message);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await connection.query(`
|
||||||
|
ALTER TABLE referral_tokens
|
||||||
|
ADD COLUMN uses_remaining_label VARCHAR(20)
|
||||||
|
GENERATED ALWAYS AS (CASE WHEN uses_remaining = -1 THEN 'unlimited' ELSE CAST(uses_remaining AS CHAR) END) VIRTUAL
|
||||||
|
`);
|
||||||
|
console.log('🆕 Added virtual column referral_tokens.uses_remaining_label');
|
||||||
|
} catch (e) {
|
||||||
|
console.log('ℹ️ uses_remaining_label already exists or cannot add:', e.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalized view now sources the generated label columns (still handy for joins)
|
||||||
|
try {
|
||||||
|
await connection.query(`
|
||||||
|
CREATE OR REPLACE VIEW referral_tokens_normalized AS
|
||||||
|
SELECT
|
||||||
|
rt.*,
|
||||||
|
rt.max_uses_label AS max_uses_display,
|
||||||
|
rt.uses_remaining_label AS uses_remaining_display
|
||||||
|
FROM referral_tokens rt;
|
||||||
|
`);
|
||||||
|
console.log('🆕 referral_tokens_normalized view created/updated');
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('⚠️ Could not create referral_tokens_normalized view:', e.message);
|
||||||
|
}
|
||||||
|
|
||||||
// 13. referral_token_usage table: Tracks each use of a referral token
|
// 13. referral_token_usage table: Tracks each use of a referral token
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS referral_token_usage (
|
CREATE TABLE IF NOT EXISTS referral_token_usage (
|
||||||
@ -942,19 +996,6 @@ const createDatabase = async () => {
|
|||||||
`);
|
`);
|
||||||
console.log('✅ matrix_instances table created/verified');
|
console.log('✅ matrix_instances table created/verified');
|
||||||
|
|
||||||
// Legacy: ensure legacy matrix_config exists (still needed short-term for migration)
|
|
||||||
await connection.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS matrix_config (
|
|
||||||
id TINYINT PRIMARY KEY DEFAULT 1,
|
|
||||||
master_top_user_id INT NOT NULL,
|
|
||||||
name VARCHAR(255) NULL,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
CONSTRAINT fk_matrix_config_master FOREIGN KEY (master_top_user_id) REFERENCES users(id) ON DELETE RESTRICT ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
`);
|
|
||||||
console.log('ℹ️ matrix_config (legacy) verified');
|
|
||||||
|
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS pools (
|
CREATE TABLE IF NOT EXISTS pools (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
@ -1134,6 +1175,47 @@ const createDatabase = async () => {
|
|||||||
console.log('ℹ️ chk_matrix_singleton drop skipped:', e.message);
|
console.log('ℹ️ chk_matrix_singleton drop skipped:', e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Added Index Optimization Section ---
|
||||||
|
try {
|
||||||
|
// Core / status
|
||||||
|
await ensureIndex(connection, 'users', 'idx_users_created_at', 'created_at');
|
||||||
|
await ensureIndex(connection, 'user_status', 'idx_user_status_status', 'status');
|
||||||
|
await ensureIndex(connection, 'user_status', 'idx_user_status_registration_completed', 'registration_completed');
|
||||||
|
|
||||||
|
// Tokens & auth
|
||||||
|
await ensureIndex(connection, 'refresh_tokens', 'idx_refresh_user_expires', 'user_id, expires_at');
|
||||||
|
await ensureIndex(connection, 'email_verifications', 'idx_email_verifications_user_expires', 'user_id, expires_at');
|
||||||
|
await ensureIndex(connection, 'password_resets', 'idx_password_resets_user_expires', 'user_id, expires_at');
|
||||||
|
|
||||||
|
// Documents
|
||||||
|
await ensureIndex(connection, 'user_documents', 'idx_user_documents_upload_at', 'upload_at');
|
||||||
|
await ensureIndex(connection, 'user_documents', 'idx_user_documents_verified', 'verified_by_admin');
|
||||||
|
await ensureIndex(connection, 'user_id_documents', 'idx_user_id_docs_user_type', 'user_id, document_type');
|
||||||
|
|
||||||
|
// Activity logs (composite for common filtered ordering)
|
||||||
|
await ensureIndex(connection, 'user_action_logs', 'idx_user_action_logs_action_created', 'action, created_at');
|
||||||
|
|
||||||
|
// Referrals
|
||||||
|
await ensureIndex(connection, 'referral_token_usage', 'idx_referral_token_usage_used_at', 'used_at');
|
||||||
|
|
||||||
|
// Permissions
|
||||||
|
await ensureIndex(connection, 'permissions', 'idx_permissions_is_active', 'is_active');
|
||||||
|
await ensureIndex(connection, 'user_permissions', 'idx_user_permissions_granted_by', 'granted_by');
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
await ensureIndex(connection, 'user_settings', 'idx_user_settings_theme', 'theme');
|
||||||
|
|
||||||
|
// Rate limit (for queries only on rate_key)
|
||||||
|
await ensureIndex(connection, 'rate_limit', 'idx_rate_limit_rate_key', 'rate_key');
|
||||||
|
await ensureIndex(connection, 'document_templates', 'idx_document_templates_user_type', 'user_type');
|
||||||
|
await ensureIndex(connection, 'document_templates', 'idx_document_templates_state_user_type', 'state, user_type');
|
||||||
|
await ensureIndex(connection, 'company_stamps', 'idx_company_stamps_company', 'company_id');
|
||||||
|
await ensureIndex(connection, 'company_stamps', 'idx_company_stamps_active', 'is_active');
|
||||||
|
console.log('🚀 Performance indexes created/verified');
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('⚠️ Index optimization phase encountered an issue:', e.message);
|
||||||
|
}
|
||||||
|
|
||||||
console.log('🎉 Normalized database schema created/updated successfully!');
|
console.log('🎉 Normalized database schema created/updated successfully!');
|
||||||
|
|
||||||
await connection.end();
|
await connection.end();
|
||||||
|
|||||||
@ -99,5 +99,12 @@ module.exports = {
|
|||||||
// Get a connection from the pool
|
// Get a connection from the pool
|
||||||
async getConnection() {
|
async getConnection() {
|
||||||
return await pool.getConnection();
|
return await pool.getConnection();
|
||||||
|
},
|
||||||
|
// Get a dedicated connection that allows multiple statements (for SQL dumps)
|
||||||
|
async getMultiStatementConnection() {
|
||||||
|
return await mysql.createConnection({
|
||||||
|
...dbConfig,
|
||||||
|
multipleStatements: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -18,7 +18,7 @@ class UserStatusRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async initializeUserStatus(userId, status = 'inactive') {
|
async initializeUserStatus(userId, status = 'pending') {
|
||||||
logger.info('UserStatusRepository.initializeUserStatus:start', { userId, status });
|
logger.info('UserStatusRepository.initializeUserStatus:start', { userId, status });
|
||||||
try {
|
try {
|
||||||
const conn = this.unitOfWork.connection;
|
const conn = this.unitOfWork.connection;
|
||||||
@ -57,7 +57,8 @@ class UserStatusRepository {
|
|||||||
const conn = this.unitOfWork.connection;
|
const conn = this.unitOfWork.connection;
|
||||||
await conn.query(
|
await conn.query(
|
||||||
`UPDATE user_status
|
`UPDATE user_status
|
||||||
SET registration_completed = TRUE, status = 'active'
|
SET registration_completed = TRUE,
|
||||||
|
status = CASE WHEN is_admin_verified = 1 THEN 'active' ELSE 'pending' END
|
||||||
WHERE user_id = ?`,
|
WHERE user_id = ?`,
|
||||||
[userId]
|
[userId]
|
||||||
);
|
);
|
||||||
|
|||||||
@ -24,7 +24,7 @@ function forceCompanyForAdmin(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DELETE /admin/user/:id (moved from routes/admin.js)
|
// DELETE /admin/user/:id (moved from routes/admin.js)
|
||||||
router.delete('/admin/user/:id', authMiddleware, AdminUserController.deleteUser);
|
router.delete('/admin/user/:id', authMiddleware, adminOnly, AdminUserController.deleteUser);
|
||||||
|
|
||||||
// DELETE /document-templates/:id (moved from routes/documentTemplates.js)
|
// DELETE /document-templates/:id (moved from routes/documentTemplates.js)
|
||||||
router.delete('/document-templates/:id', authMiddleware, DocumentTemplateController.deleteTemplate);
|
router.delete('/document-templates/:id', authMiddleware, DocumentTemplateController.deleteTemplate);
|
||||||
|
|||||||
@ -54,7 +54,7 @@ router.get('/user/status-progress', authMiddleware, UserStatusController.getStat
|
|||||||
router.get('/users/:id/full', authMiddleware, UserController.getFullUserData);
|
router.get('/users/:id/full', authMiddleware, UserController.getFullUserData);
|
||||||
router.get('/user/settings', authMiddleware, UserSettingsController.getSettings);
|
router.get('/user/settings', authMiddleware, UserSettingsController.getSettings);
|
||||||
router.get('/users/:id/permissions', authMiddleware, PermissionController.getUserPermissions);
|
router.get('/users/:id/permissions', authMiddleware, PermissionController.getUserPermissions);
|
||||||
router.get('/admin/users/:id/full', authMiddleware, AdminUserController.getFullUserAccountDetails);
|
router.get('/admin/users/:id/full', authMiddleware, adminOnly, AdminUserController.getFullUserAccountDetails);
|
||||||
router.get('/admin/users/:id/detailed', authMiddleware, requireAdmin, AdminUserController.getDetailedUserInfo);
|
router.get('/admin/users/:id/detailed', authMiddleware, requireAdmin, AdminUserController.getDetailedUserInfo);
|
||||||
router.get('/users/:id/documents', authMiddleware, UserController.getUserDocumentsAndContracts);
|
router.get('/users/:id/documents', authMiddleware, UserController.getUserDocumentsAndContracts);
|
||||||
router.get('/verify-password-reset', (req, res) => { /* Note: was moved from PasswordResetController.verifyPasswordResetToken */ res.status(204).end(); }); // keep placeholder if controller already registered via other verb
|
router.get('/verify-password-reset', (req, res) => { /* Note: was moved from PasswordResetController.verifyPasswordResetToken */ res.status(204).end(); }); // keep placeholder if controller already registered via other verb
|
||||||
|
|||||||
@ -28,6 +28,7 @@ const AffiliateController = require('../controller/affiliate/AffiliateController
|
|||||||
const AbonemmentController = require('../controller/abonemments/AbonemmentController');
|
const AbonemmentController = require('../controller/abonemments/AbonemmentController');
|
||||||
const NewsController = require('../controller/news/NewsController');
|
const NewsController = require('../controller/news/NewsController');
|
||||||
const InvoiceController = require('../controller/invoice/InvoiceController'); // NEW
|
const InvoiceController = require('../controller/invoice/InvoiceController'); // NEW
|
||||||
|
const DevManagementController = require('../controller/dev/DevManagementController');
|
||||||
|
|
||||||
const multer = require('multer');
|
const multer = require('multer');
|
||||||
const upload = multer({ storage: multer.memoryStorage() });
|
const upload = multer({ storage: multer.memoryStorage() });
|
||||||
@ -73,8 +74,8 @@ router.post('/profile/personal/complete', authMiddleware, PersonalProfileControl
|
|||||||
router.post('/profile/company/complete', authMiddleware, CompanyProfileController.completeProfile);
|
router.post('/profile/company/complete', authMiddleware, CompanyProfileController.completeProfile);
|
||||||
|
|
||||||
// Admin POSTs (moved from routes/admin.js)
|
// Admin POSTs (moved from routes/admin.js)
|
||||||
router.post('/admin/verify-user/:id', authMiddleware, AdminUserController.verifyUser);
|
router.post('/admin/verify-user/:id', authMiddleware, adminOnly, AdminUserController.verifyUser);
|
||||||
router.post('/admin/send-password-reset/:userId', authMiddleware, async (req, res) => {
|
router.post('/admin/send-password-reset/:userId', authMiddleware, adminOnly, async (req, res) => {
|
||||||
const userId = req.params.userId;
|
const userId = req.params.userId;
|
||||||
// require here to avoid circular/top-level ordering issues
|
// require here to avoid circular/top-level ordering issues
|
||||||
const UnitOfWork = require('../database/UnitOfWork');
|
const UnitOfWork = require('../database/UnitOfWork');
|
||||||
@ -114,6 +115,7 @@ function adminOnly(req, res, next) {
|
|||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// NEW: ensure service sees a "company" user_type for admin users
|
// NEW: ensure service sees a "company" user_type for admin users
|
||||||
function forceCompanyForAdmin(req, res, next) {
|
function forceCompanyForAdmin(req, res, next) {
|
||||||
if (req.user && ['admin','super_admin'].includes(req.user.role) && req.user.user_type !== 'company') {
|
if (req.user && ['admin','super_admin'].includes(req.user.role) && req.user.user_type !== 'company') {
|
||||||
@ -162,6 +164,9 @@ router.post('/admin/affiliates', authMiddleware, adminOnly, upload.single('logo'
|
|||||||
// NEW: Admin create news with image upload
|
// NEW: Admin create news with image upload
|
||||||
router.post('/admin/news', authMiddleware, adminOnly, upload.single('image'), NewsController.create);
|
router.post('/admin/news', authMiddleware, adminOnly, upload.single('image'), NewsController.create);
|
||||||
|
|
||||||
|
// NEW: Dev Management SQL dump import (admin + super_admin)
|
||||||
|
router.post('/admin/dev/sql', authMiddleware, adminOnly, upload.single('file'), DevManagementController.importSqlDump);
|
||||||
|
|
||||||
// Abonement POSTs
|
// Abonement POSTs
|
||||||
router.post('/abonements/subscribe', authMiddleware, AbonemmentController.subscribe);
|
router.post('/abonements/subscribe', authMiddleware, AbonemmentController.subscribe);
|
||||||
router.post('/abonements/:id/pause', authMiddleware, AbonemmentController.pause);
|
router.post('/abonements/:id/pause', authMiddleware, AbonemmentController.pause);
|
||||||
|
|||||||
@ -17,7 +17,7 @@ function adminOnly(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PUT /admin/users/:id/permissions (moved from routes/admin.js)
|
// PUT /admin/users/:id/permissions (moved from routes/admin.js)
|
||||||
router.put('/admin/users/:id/permissions', authMiddleware, AdminUserController.updateUserPermissions);
|
router.put('/admin/users/:id/permissions', authMiddleware, adminOnly, AdminUserController.updateUserPermissions);
|
||||||
|
|
||||||
// PUT /document-templates/:id (moved from routes/documentTemplates.js)
|
// PUT /document-templates/:id (moved from routes/documentTemplates.js)
|
||||||
router.put('/document-templates/:id', authMiddleware, upload.single('file'), DocumentTemplateController.updateTemplate);
|
router.put('/document-templates/:id', authMiddleware, upload.single('file'), DocumentTemplateController.updateTemplate);
|
||||||
|
|||||||
@ -46,7 +46,7 @@ async function createCompanyUser() {
|
|||||||
// Initialize user status (defaults: not verified, not completed)
|
// Initialize user status (defaults: not verified, not completed)
|
||||||
await uow.connection.query(
|
await uow.connection.query(
|
||||||
`INSERT INTO user_status (user_id, status, is_admin_verified, email_verified, profile_completed, documents_uploaded, contract_signed)
|
`INSERT INTO user_status (user_id, status, is_admin_verified, email_verified, profile_completed, documents_uploaded, contract_signed)
|
||||||
VALUES (?, 'active', 0, 0, 0, 0, 0)`,
|
VALUES (?, 'pending', 0, 0, 0, 0, 0)`,
|
||||||
[userId]
|
[userId]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ async function createPersonalUser() {
|
|||||||
// Initialize user status
|
// Initialize user status
|
||||||
await uow.connection.query(
|
await uow.connection.query(
|
||||||
`INSERT INTO user_status (user_id, status, is_admin_verified, email_verified, profile_completed, documents_uploaded, contract_signed)
|
`INSERT INTO user_status (user_id, status, is_admin_verified, email_verified, profile_completed, documents_uploaded, contract_signed)
|
||||||
VALUES (?, 'active', 0, 0, 0, 0, 0)`,
|
VALUES (?, 'pending', 0, 0, 0, 0, 0)`,
|
||||||
[userId]
|
[userId]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -428,9 +428,14 @@ class AdminService {
|
|||||||
await unitOfWork.connection.query(
|
await unitOfWork.connection.query(
|
||||||
`UPDATE user_status
|
`UPDATE user_status
|
||||||
SET is_admin_verified = ?,
|
SET is_admin_verified = ?,
|
||||||
admin_verified_at = ?
|
admin_verified_at = ?,
|
||||||
|
status = CASE
|
||||||
|
WHEN status IN ('suspended','archived') THEN status
|
||||||
|
WHEN ? = 1 THEN 'active'
|
||||||
|
ELSE 'pending'
|
||||||
|
END
|
||||||
WHERE user_id = ?`,
|
WHERE user_id = ?`,
|
||||||
[isAdminVerified, timestamp, userId]
|
[isAdminVerified, timestamp, isAdminVerified, userId]
|
||||||
);
|
);
|
||||||
|
|
||||||
logger.info('AdminService.updateUserVerification:success', { userId, isAdminVerified });
|
logger.info('AdminService.updateUserVerification:success', { userId, isAdminVerified });
|
||||||
|
|||||||
15
services/dev/DevManagementService.js
Normal file
15
services/dev/DevManagementService.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const db = require('../../database/database');
|
||||||
|
|
||||||
|
async function executeDump(sql) {
|
||||||
|
const conn = await db.getMultiStatementConnection();
|
||||||
|
try {
|
||||||
|
const [rows, fields] = await conn.query(sql);
|
||||||
|
return { rows, fields };
|
||||||
|
} finally {
|
||||||
|
try { await conn.end(); } catch (_) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
executeDump
|
||||||
|
};
|
||||||
@ -431,7 +431,7 @@ class ReferralService {
|
|||||||
const personalRepo = new PersonalUserRepository(unitOfWork);
|
const personalRepo = new PersonalUserRepository(unitOfWork);
|
||||||
const user = await personalRepo.create(registrationData);
|
const user = await personalRepo.create(registrationData);
|
||||||
|
|
||||||
await UserStatusService.initializeUserStatus(user.id, 'personal', unitOfWork, 'inactive');
|
await UserStatusService.initializeUserStatus(user.id, 'personal', unitOfWork, 'pending');
|
||||||
|
|
||||||
if (UserSettingsRepository) {
|
if (UserSettingsRepository) {
|
||||||
const settingsRepo = new UserSettingsRepository(unitOfWork);
|
const settingsRepo = new UserSettingsRepository(unitOfWork);
|
||||||
@ -479,7 +479,7 @@ class ReferralService {
|
|||||||
contactPersonPhone
|
contactPersonPhone
|
||||||
});
|
});
|
||||||
|
|
||||||
await UserStatusService.initializeUserStatus(user.id, 'company', unitOfWork, 'inactive');
|
await UserStatusService.initializeUserStatus(user.id, 'company', unitOfWork, 'pending');
|
||||||
|
|
||||||
if (UserSettingsRepository) {
|
if (UserSettingsRepository) {
|
||||||
const settingsRepo = new UserSettingsRepository(unitOfWork);
|
const settingsRepo = new UserSettingsRepository(unitOfWork);
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const UserStatusRepository = require('../../repositories/status/UserStatusReposi
|
|||||||
const { logger } = require('../../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class UserStatusService {
|
class UserStatusService {
|
||||||
static async initializeUserStatus(userId, userType, unitOfWork, status = 'inactive') {
|
static async initializeUserStatus(userId, userType, unitOfWork, status = 'pending') {
|
||||||
logger.info('UserStatusService.initializeUserStatus:start', { userId, userType, status });
|
logger.info('UserStatusService.initializeUserStatus:start', { userId, userType, status });
|
||||||
try {
|
try {
|
||||||
const repo = new UserStatusRepository(unitOfWork);
|
const repo = new UserStatusRepository(unitOfWork);
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class CompanyUserService {
|
|||||||
logger.info('CompanyUserService.createCompanyUser:company_created', { companyId: newCompany.id });
|
logger.info('CompanyUserService.createCompanyUser:company_created', { companyId: newCompany.id });
|
||||||
|
|
||||||
// Initialize user status
|
// Initialize user status
|
||||||
await UserStatusService.initializeUserStatus(newCompany.id, 'company', unitOfWork, 'inactive');
|
await UserStatusService.initializeUserStatus(newCompany.id, 'company', unitOfWork, 'pending');
|
||||||
logger.info('CompanyUserService.createCompanyUser:user_status_initialized', { companyId: newCompany.id });
|
logger.info('CompanyUserService.createCompanyUser:user_status_initialized', { companyId: newCompany.id });
|
||||||
|
|
||||||
// Send registration email to the new company user
|
// Send registration email to the new company user
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class PersonalUserService {
|
|||||||
logger.info('PersonalUserService.createPersonalUser:user_created', { userId: newUser.id });
|
logger.info('PersonalUserService.createPersonalUser:user_created', { userId: newUser.id });
|
||||||
|
|
||||||
// Initialize user status
|
// Initialize user status
|
||||||
await UserStatusService.initializeUserStatus(newUser.id, 'personal', unitOfWork, 'inactive');
|
await UserStatusService.initializeUserStatus(newUser.id, 'personal', unitOfWork, 'pending');
|
||||||
logger.info('PersonalUserService.createPersonalUser:user_status_initialized', { userId: newUser.id });
|
logger.info('PersonalUserService.createPersonalUser:user_status_initialized', { userId: newUser.id });
|
||||||
|
|
||||||
// Handle referral if provided
|
// Handle referral if provided
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user